首页
社区
课程
招聘
[原创] 如何在pwn题中更有效地使用GDB
发表于: 2017-12-15 14:33 11899

[原创] 如何在pwn题中更有效地使用GDB

2017-12-15 14:33
11899

【时间】2017.9

【出处】SEC-T CTF

【类型】PWN

【分值】250

程序功能简单,在开始的时候会要求输入Username,之后就会打印出菜单。

1) Change user 可以修改 Username

2) Make it rain 会要求验证一串hash值,验证通过可以再进行一次输入(栈溢出),验证没通过就直接exit

3) Exit exit()

main中只有四个函数

init()

/dev/urandom读取四个字节的随机字节组成一个int变量rand_data,保存位置在bss上,而且紧挨着username

而在输入username的时候我们可以输入9个字节,我们输入八个字节的话就可以在打印username的时候泄漏出rand_data的值了。

而之后的srand()又是以rand_data作为种子,所以之后的rand()的值就是可预测的了。

login()

这里就是进行第一次的username的输入了,观察到可以输入九个字节,而且没有加上'\x00'截断。

create_secret()

首先创建一片内存映射区域,并且是可读可执行的,只有在往里面写入数据的时候才改为可读可写,之后又改回可读可执行。

它这片区域固定地从0x40000开始,并且长度为0x30D40个字节。

开头的前九个字节是输入的username,后面的数据则全部是由rand()生成的随机数。

menu()

这里就是主循环的地方了,主要的就是一个函数make_it_rain()这个函数下面有两个函数

verify_secure_hash()负责生成hash值和验证输入是否与hash值相等

而这串hash的生成主要就是和secret指向的username的值以及后面的随机数有关。

如果这里验证成功了,就可以进入withdraw函数,验证失败就exit()给你看。

withdraw()

这里就可以进行栈溢出了。

程序除了canary,其他保护全开,但是程序刚开始创建的那片mmap区域是可执行的,而且刚开始的九个字节可控。

所以我们首先要控制username的9个字节作为可以正常开启shell的shellcode,然后控制rip跳过去执行就可以了。

所以总体思路如下

将9个字节以内的shellcode作为username进行输入。

在进行hash验证之前计算出正确的hash。

栈溢出,控制rip到0x40000

什么样的shellcode可以控制在9个字节以内?

这里一共八个字节,只要控制好栈上的内容,这串shellcode就是有效的。

如何计算出hash?


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
  • bank (17.55kb,29次下载)
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 47
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
pwntools里有gdb的函数可以用,测试exp还是不错的
2017-12-15 15:51
0
游客
登录 | 注册 方可回帖
返回
//