// Name: rtl.c
// Compile: gcc -o rtl rtl.c -fno-PIE -no-pie
#include <stdio.h>
#include <unistd.h>
const char* binsh = "/bin/sh";
int main() {
char buf[0x30];
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
// Add system function to plt's entry
system("echo 'system@plt");
// Leak canary
printf("[1] Leak Canary\\n");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\\n", buf);
// Overwrite return address
printf("[2] Overwrite return address\\n");
printf("Buf: ");
read(0, buf, 0x100);
return 0;
}
위는 문제의 소스코드다
┌ 241: int main (int argc, char **argv, char **envp);
│ ; var int64_t var_8h @ rbp-0x8
│ ; var int64_t var_40h @ rbp-0x40
│ 0x004006f7 55 push rbp
│ 0x004006f8 4889e5 mov rbp, rsp
│ 0x004006fb 4883ec40 sub rsp, 0x40
│ 0x004006ff 64488b042528. mov rax, qword fs:[0x28]
│ 0x00400708 488945f8 mov qword [var_8h], rax
│ 0x0040070c 31c0 xor eax, eax
│ 0x0040070e 488b055b0920. mov rax, qword [obj.stdin] ; obj.stdin__GLIBC_2.2.5
│ ; [0x601070:8]=0
│ 0x00400715 b900000000 mov ecx, 0
│ 0x0040071a ba02000000 mov edx, 2
│ 0x0040071f be00000000 mov esi, 0
│ 0x00400724 4889c7 mov rdi, rax
│ 0x00400727 e8d4feffff call sym.imp.setvbuf ; int setvbuf(FILE*stream, char *buf, int mode, size_t size)
│ 0x0040072c 488b052d0920. mov rax, qword [obj.stdout] ; obj.__TMC_END__
│ ; [0x601060:8]=0
│ 0x00400733 b900000000 mov ecx, 0
│ 0x00400738 ba02000000 mov edx, 2
│ 0x0040073d be00000000 mov esi, 0
│ 0x00400742 4889c7 mov rdi, rax
│ 0x00400745 e8b6feffff call sym.imp.setvbuf ; int setvbuf(FILE*stream, char *buf, int mode, size_t size)
│ 0x0040074a bf7c084000 mov edi, str.echo_system_plt ; 0x40087c ; "echo 'system@plt"
│ 0x0040074f b800000000 mov eax, 0
│ 0x00400754 e877feffff call sym.imp.system ; int system(const char *string)
│ 0x00400759 bf8d084000 mov edi, str._1__Leak_Canary ; 0x40088d ; "[1] Leak Canary"
│ 0x0040075e e84dfeffff call sym.imp.puts ; int puts(const char *s)
│ 0x00400763 bf9d084000 mov edi, str.Buf:_ ; 0x40089d ; "Buf: "
│ 0x00400768 b800000000 mov eax, 0
│ 0x0040076d e86efeffff call sym.imp.printf ; int printf(const char *format)
│ 0x00400772 488d45c0 lea rax, [var_40h]
│ 0x00400776 ba00010000 mov edx, 0x100 ; 256
│ 0x0040077b 4889c6 mov rsi, rax
│ 0x0040077e bf00000000 mov edi, 0
│ 0x00400783 e868feffff call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
│ 0x00400788 488d45c0 lea rax, [var_40h]
│ 0x0040078c 4889c6 mov rsi, rax
│ 0x0040078f bfa3084000 mov edi, str.Buf:__s_n ; 0x4008a3 ; "Buf: %s\\n"
│ 0x00400794 b800000000 mov eax, 0
│ 0x00400799 e842feffff call sym.imp.printf ; int printf(const char *format)
│ 0x0040079e bfac084000 mov edi, str._2__Overwrite_return_address ; 0x4008ac ; "[2] Overwrite return address"
│ 0x004007a3 e808feffff call sym.imp.puts ; int puts(const char *s)
│ 0x004007a8 bf9d084000 mov edi, str.Buf:_ ; 0x40089d ; "Buf: "
│ 0x004007ad b800000000 mov eax, 0
│ 0x004007b2 e829feffff call sym.imp.printf ; int printf(const char *format)
│ 0x004007b7 488d45c0 lea rax, [var_40h]
│ 0x004007bb ba00010000 mov edx, 0x100 ; 256
│ 0x004007c0 4889c6 mov rsi, rax
│ 0x004007c3 bf00000000 mov edi, 0
│ 0x004007c8 e823feffff call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
│ 0x004007cd b800000000 mov eax, 0
│ 0x004007d2 488b4df8 mov rcx, qword [var_8h]
│ 0x004007d6 6448330c2528. xor rcx, qword fs:[0x28]
│ ┌─< 0x004007df 7405 je 0x4007e6
│ │ 0x004007e1 e8dafdffff call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
│ └─> 0x004007e6 c9 leave
└ 0x004007e7 c3 ret
위는 Radare2로 디스어셈블 한 모습이다.

Main 함수에서 선언된 지역변수들의 위치를 나타낸다.

보호기법은 Canary, NX, Partial_RelR0 가 걸려있다.
RET주소에 쉘코드를 삼입해도 실행할 수 없으며 Canary로 인해 BOF를 일으킬때 Canary 또한 우회해야 한다.
