HCTF2017的三个WriteUp

0x00 题目

感觉自己还是太菜了,比赛结束前只做出来了三道题。

Evr_Q (level - 1)

guestbook (level - 2)

babystack (level - 3)

0x01 Evr_Q

程序会先要求输入 User

载入到 IDA 进行分析

但是在进行 F5 反编译的时候发生了一个错误

Decompilation failure:

413238: positive sp value has been found

解决方法就是先 undefine 掉函数,再右键选择 Code,最后 Create function 就可以正常反编译了。

可以看到 User 的输入时保存在全局数组 Str 里的,然后下面的 sub_411316() 函数进行 User 的 check

这就是这个函数的主要部分了,我先爆破出第一个循环加密后的字符串,又因为第一个循环本身只用了异或,所以爆破出来之后再循环一次就是正确的 User 了,脚本如下:

User 验证成功以后,程序又要求输入 Start Code ,其实就是 flag 。

以上就是第二次输入 flag 的进行加密和验证的地方,最后的解密我也是通过爆破完成的,不算太难,脚本如下:

其实这个程序还加了一个检测调试器和一些工具进程的回调函数,如果需要动态调试的话,可以把这个函数对应跳表位置的jmp改为ret。:P

0x02 guestbook

Arch:     i386-32-little

RELRO:    Full RELRO

Stack:    Canary found

NX:       NX enabled

PIE:      PIE enabled

程序主要有三个主要的功能

add() : 添加 guest

see() : 打印 guest 信息 - name 和 phone

del() : 删除 guest

add() 主要代码如下:

这里进行两次输入,输入 name 和 phone ,name 会保存在 bss 上,phone 会额外 malloc 一块内存进行保存。而且两个输入都有长度限制,而且 phone 还会通过 \_ctype\_b\_loc() 对字符类型进行检测,无法输入英文字母。

del():

流程比较简单:guest 标志位置 0 -> name 字段置 0 -> free 掉 phone 的内存 -> phone 的指针置 null

see():

这里通过 snprintf() 和 puts() 对 guest 的信息进行打印,snprintf() 通过格式控制先将信息打印到栈上,puts() 再将这些信息统一进行输出。

那这里就有一个问题,snprintf() 和 printf() 一样存在格式化字符串漏洞。

那我们就已经 get 到了一个格式化字符串的漏洞了。

思路:

程序保护全开,通过写 GOT 表肯定不可能了,于是我决定写 __free_hook,但是刚开始想写一个 one_gadget 完事,结果发现三个 one_gadget 都没法用,于是我在程序段找了一个栈溢出的地方,写到那里去,之后通过泄漏 text 段地址和 canary 来通过栈溢出完成攻击。

EXP:

0x03 babystack

Arch:     amd64-64-little

RELRO:    Partial RELRO

Stack:    No canary found

NX:       NX enabled

PIE:      No PIE (0x400000)

很巧的是 pwnable.tw 上也有一道题叫 babystack ,而且对于这两道题我最后的解题思想也是基本一致的。

程序功能很简单,直接看 main 的代码

程序可以接受两次输入,第一次可以接受一个指针的值,之后会有一个 printf 函数将指针指向的内容以 %lld 格式打印出来。

再之后会进入一个我重命名的叫 load_filter 的函数,这个函数的作用就是创建一个系统调用白名单,这份白名单里有:

read()

open()

exit()

其他系统调用被调用时,内核会向进程发送 SIGSYS 信号并终止进程。

这个函数完成之后会进入下一个函数(也是我重命名过的),这个函数就可以进行栈溢出。

但是这里有一个问题就是,由于系统调用被禁用了,我们没有办法正常启 shell。

思路:

这时候有两个思路:

使过滤失效或者将 execve 加入到白名单中

利用仅有的三个系统调用获取 flag

刚开始我选择将重点放在过滤上,选择了第一种思路,走了很多弯路。因为我后来调试发现用来将过滤规则载入内核的 load 函数也是被禁用的状态。

于是后来我选择了第二种思路。

先通过 open() 打开 flag 文件,再通过 read() 将内容读入内存,再找一个同时带有 cmp 和跳转到一个被禁用的系统调用前的 je 或 jnz 的这么一个 gadget(有点难懂么? XD )。

由于跳到其他系统调用时进程接收到的信号时 SIGSYS ,而程序因为无效返回地址终止时接收到的信号是 SIGSEGV

这样我们就能对内存中的 flag 内容进行爆破了。

EXP:

由于题目特殊性,exp 看看思路就好。

个人作品展

2017-NSCTF-PWN

二进制漏洞学习笔记

栈溢出利用之Return to dl-resolve

how2heap总结-上

个人简介

笔者是一名就读于成都信息工程大学的大二狗,Syclover 混吃等死只知后退不思进取二进制选手,主要学习二进制漏洞的分析和利用。

我是从大一进校之后才开始学习信安的,说实话进校之前我都不知道信息安全是干嘛的。

刚开始学习的是 php、sql 注入之类的东西,后来不知道怎么回事学到了二进制上面去 XD,觉得挺有意思,之后就一路坚持了下来。

实话就说这么多,求二进制大佬带一波 Orz。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值