#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);
}

int main(int argc, char *argv[]) {
    char buf[0x40] = {};

    initialize();

    read(0, buf, 0x400);
    write(1, buf, sizeof(buf));

    return 0;
}

32bit라는 것만 제외하고 코드는 basic_rop_x64와 동일하다.

32bit는 함수인자값을 스택에서 참조한다.

[그림 1-1]

buf 위치가 ebp-0x44라는 걸 알 수 있다.

[그림 1-2]

puts를 이용해 read_got 값을 출력해 system 함수 주소를 얻고 read를 이용해 read_got 값에 system 함수 주소와 "/bin/sh" 문자열을 넣어 다시 read 함수를 호출하여 system 함수를 실행시키도록 하자

[그림 1-3]
[그림 1-4]

성공!

 

알게 된 점

1. GOT 값을 overwrite 할 수 있는 이유는 GOT 영역에 쓰기(w) 권한이 있기 때문이다.

[그림 2-1]

익스 코드에서 0x804a00c에 system 함수주소를 넣고 0x804a00c + 0x4 에 "/bin/sh" 문자열을 넣는다.

[그림 2-1] 보면 0x804a00c와 0x804a00c + 0x4 모두 쓰기(w) 권한이 있는 곳에 존재하기 때문에 쓸 수 있다.

 

2. 32bit 환경에서 라이브러리 주소는 0xf7로 시작한다. 64bit는 0x7f로 시작

 

3. 문제에서 라이브러리 파일을 제공하면 gdb를 통해 offset 값을 쉽게 확인할 수 있다.

[그림 3-1]

따라서 라이브러리 매핑된 주소만 찾으면 함수를 실행시킬 수 있다.

libc.symbols ['system'] -> 잘 동작되지 않을 때 직접 주소를 넣어보자

 

4. 문제에서 라이브러리 파일을 제공하면 strings 명령어를 통해 "/bin/sh" offset 값을 쉽게 확인할 수 있다.

[그림 4-1]

따라서 라이브러리 매핑된 주소만 찾으면 실제 "/bin/sh" 위치를 알 수 있다.

"/bin/sh" 문자열을 입력할 수 없을때 사용하자

'Dreamhack - pwnable' 카테고리의 다른 글

RELRO (RELocation Read-Only)  (0) 2023.01.16
basic_rop_x86 (ret2main + bss 쓰기)  (0) 2023.01.15
basic_rop_x64 (ret2main)  (0) 2023.01.15
basic_rop_x64 (GOT Overwrite)  (0) 2023.01.14
Return Oriented Programming  (0) 2023.01.13