首页
论坛
课程
招聘
[原创]8月29号网鼎杯pwn1-impossible简单调试过程
2018-8-31 20:22 13181

[原创]8月29号网鼎杯pwn1-impossible简单调试过程

2018-8-31 20:22
13181

检测程序

拿到文件,为64位linux文件,然后checksec为


发现开了canary和nx(栈上不可执行)

canary:(函数返回时会检测这个值,如果改变,就会崩溃,可以防止shellcode覆盖返回地址)

nx:防止栈上执行代码

RELRO(表示重定位表只读)

分析流程

     这里大家多看一下程序,运行一下,就可以知道逻辑了,这个是main函数主体:


简单的意思输入不同的数字,会进入不同的流程

当输入9011时,会进入sub_4008A3这个函数


这里存在栈溢出,因为buf的长度为16个字节,拷贝的长度为0x1000,所以会存在栈溢出,所以当时想到的解题思路就是进入这个分支,栈溢出,覆盖返回地址,直接进入调用system(“/bin/sh”)拿到shell,读取flag(后来由于程序本身的原因是走不通的)。

解题思路

        继续看,如果进入这个if分支,需要输入的数值和读到的数值一样才行。

fd = open("/dev/urandom", 0); 这个是读取随机数,每次读取的值不一样,然后和我们输入的数值相比较,因为每次都随机,无法预测到随机数,这样永远都猜不到读取到的随机数值,也无法进入if大括号内,无法触发执行qmemcpy触发栈溢出。方法是:这里需要打开1024次,然后再次打开这个设备文件会出错,返回错误,读进去的unk_602068数组也全为0,然后我们输入8个0,判断相等,就可以进入if分支内了。


       再看unk_602080这个全局变量,最后需要布置好数据,而且需要绕过canary,才能覆盖返回地址,那么如何知道canary值呢?

这里提醒一下,每次程序运行的时候canary的值是不一样的,而且,一个程序运行时候所有的canary值都是一样的值。

我们回到主程序:

当输入数值2的时候,会进入这个函数:


会从键盘输入的字符拷贝到这个全局变量中。


当输入1的时候:


       函数的意思是会将输入的字符串拷贝到栈中的buf中,然后输出,这里只能执行一次函数read,puts,不能执行第二次,从这里我们通过利用这个函数可以打印出canary值,直接上gdb调试,进入这个函数。

在0x40a22下断点:输入1,会进入这个函数:


看到canary值,0x4dc9d7e 0x8b445b00,存放在rbp-8的位置,而buf的位置为rpb-0x110,只要puts出0x110-8位置的8个值,就是canary值,前面的buf直接填充可见字符,但是8位的canary值,最低地址为0,会被截断,所以也需要覆盖最低位为0x00替换为可见字符,直接打印后面的7个字符,就可以算出canary值了

     下图为没有读取字符时的buf


通过生成0x110-8 -1个可见字符,这样会打印后面的7位的canary,这里啰嗦一下。


下一步会调用puts进行打印所有可见字符


打印最后的7位值即位canary值。通过python转化为16进制即可。

这时候拿到canary值了。但是接下来在退出函数的时候会崩溃,因为修改了canary值,然后跟原始的值比较,不一样程序会异常退出,这样就无法利用了。


       所以这里想想,应该如何拿到canary值,而且不会出现异常退出呢,我们必须让canary值落在0x7fff~dc80 – 0x7fff~dc80+0x108=0x7fff~dd88区间内,因为这个区间才是buf的内容,才能打印出来,而且程序不会崩溃,一旦出界了,就打印不出来,而且会破坏栈。

豁然开朗

      所以采取的办法是,调用递归函数,一直压栈数据,将canary值压到很低的栈上,然后栈不会清空数据,将会保存一些canary值,这时候调用sub_400a22函数,但要记住,这个函数只会调用一次,会从这个区间看到想要的canary然后打印出来,这里再次记住一下刚才的buf首地址末尾为dc80,一直观察这个区间的数据变化情况。

      重新运行程序,回到main函数:输入2,会进入这个函数,读取键盘内容到全局数组,unk_602080中


这里如果用户输入n,就会一直递归调用,随时观察栈的变化

这次运行的canary值为:$1 = 0x52be8e08d875400


第一次运行0x400999这个递归函数的栈地址rsp=0x7ff~0xdd80,与刚才的区间dc80~dd88还差一点,对应的canary值也在对应的栈中


第二次进入这个函数,再观察栈:


这次为dd60,

第三次进入递归:


第4次为dd20,第5次为dd00,第6:次:dce0:,发现每次减去0x20

第7次为dcc0,第8次为dca0 ,相应的canary值依次散落在这个区间。

只要进入了这个区间,canary值会分布在这里,这时退出这个函数,然后进入sub_400a22函数打印出来通过puts将buf的内容打印出来,也会打印出相应的canary值了。


进入这个函数看对应的堆栈


      dc80+0xa8=dd28,就能看到canary,可见在第4次递归,canary值就落在那个区间中了,通过sub_400a22,填充a9个可见字符,0xdd28-0xdc80=0xa8 0xa8+1=0xa9,因为canary的值低地址一个字节为0,防止被puts截断,需要a8+1,然后就可以打印出canary值了,程序也没有崩溃。



    这时输入9011进入函数,进行栈布置,覆盖返回地址,


因为程序不包含system的地址,没有libc,并且nx,所以覆盖返回地址,并且构造栈中数据,进行rop,直接调用 open(“./flag”), read, puts就可以打印出flags了

总结:                                         

1.     进行递归,打印出canary

2.     通过多次打开设备文件出错,然后栈溢出,进行rop,直接输出flag

note:rop这步挺浪费时间的, 不知道有什么好用的工具吗?

写的比较简单,也是这几年来第一次学习和调试pwn,一直想学,就是没精力....希望能与大家学习交流。

最后谢谢id:another,流韵山庄的思路和指导


《0day安全 软件漏洞分析技术(第二版)》第三次再版印刷预售开始!

最后于 2018-8-31 20:48 被LowRebSwrd编辑 ,原因: 拼写错误
上传的附件:
  • 1.py (1.49kb,73次下载)
  • pwn (9.91kb,44次下载)
收藏
点赞0
打赏
分享
最新回复 (25)
雪    币: 2224
活跃值: 活跃值 (16)
能力值: ( LV13,RANK:275 )
在线值:
发帖
回帖
粉丝
foyjog 活跃值 2 2018-8-31 20:46
2
0
前排赞一个
雪    币: 4500
活跃值: 活跃值 (377)
能力值: (RANK:30 )
在线值:
发帖
回帖
粉丝
CCkicker 活跃值 2018-8-31 21:09
3
0
楼主厉害了
雪    币: 3481
活跃值: 活跃值 (111)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
不知世事 活跃值 1 2018-8-31 21:21
4
0
版主厉害了,666
雪    币: 1
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_秋木 活跃值 2018-8-31 21:50
5
0
楼主的实力那么强,容我好好消化一下......
雪    币: 24
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Vuler 活跃值 2018-9-1 00:33
6
0
正好学习学习,期待剩下的pwn题呀
雪    币: 18
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
Nepire 活跃值 2018-9-1 00:51
7
0
太强了吧,1024次打开会出错
雪    币: 0
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_DsjTy 活跃值 2018-9-1 05:53
8
0
不明觉厉
雪    币: 1
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Roger_382982 活跃值 2018-9-1 09:34
9
0
雪    币: 1
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
活跃值 2018-9-1 09:42
10
0
好叼
雪    币: 234
活跃值: 活跃值 (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kinglinzi 活跃值 2018-9-1 12:17
11
0
厉害了老师
雪    币: 68
活跃值: 活跃值 (33)
能力值: ( LV12,RANK:557 )
在线值:
发帖
回帖
粉丝
skytar 活跃值 1 2018-9-1 13:29
12
0
厉害,我刚还看了下,默认文件句柄上限还真是1024。学到了
雪    币: 5453
活跃值: 活跃值 (232)
能力值: ( LV17,RANK:1155 )
在线值:
发帖
回帖
粉丝
holing 活跃值 15 2018-9-1 17:40
13
0
所以请问1024次操作如何让服务器不timeout?这个一分钟的时限真的恶心
雪    币: 3032
活跃值: 活跃值 (311)
能力值: (RANK:110 )
在线值:
发帖
回帖
粉丝
LowRebSwrd 活跃值 2 2018-9-1 18:17
14
0
holing 所以请问1024次操作如何让服务器不timeout?这个一分钟的时限真的恶心
多少次会timeout呢,应该跟网络延迟有关吧
雪    币: 1
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
青桐 活跃值 2018-9-1 18:19
15
0
厉害了,我的哥
雪    币: 5453
活跃值: 活跃值 (232)
能力值: ( LV17,RANK:1155 )
在线值:
发帖
回帖
粉丝
holing 活跃值 15 2018-9-1 19:09
16
0
LowRebSwrd 多少次会timeout呢,应该跟网络延迟有关吧
我当时200多次就timeout了,迷了。。。延迟50-60,不算高吧。。。
雪    币: 7409
活跃值: 活跃值 (67)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
sqdebug 活跃值 2 2018-9-1 21:14
17
0
学长厉害,学习了。
雪    币: 2
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_A0Yang 活跃值 2018-9-2 08:42
18
0
常总
雪    币: 2
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_A0Yang 活跃值 2018-9-2 08:43
19
0
厉害厉害
雪    币: 20
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ashooter 活跃值 2018-9-2 18:42
20
0
666,学习了
雪    币: 39
活跃值: 活跃值 (443)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
葫芦娃 活跃值 1 2018-9-3 11:39
21
0
常总
雪    币: 112
活跃值: 活跃值 (314)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
netwind 活跃值 13 2018-9-3 21:58
22
0
研究了一下 实在无法SHELL 只能读文件,充其量还可以写文件
雪    币: 308
活跃值: 活跃值 (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
想猫的鱼 活跃值 2018-9-4 18:55
23
0
感谢楼主!
雪    币: 239
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
网络风尘 活跃值 2018-9-18 11:07
24
0
学习了,感谢楼主
雪    币: 14
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Lemonr 活跃值 2018-10-16 20:31
25
0
游客
登录 | 注册 方可回帖
返回