前言
今日学习计划原本是打算搭建shiro Remeberme 的漏洞来复现然后分析其代码的。
刚开始费劲千辛万苦终于找到了源码,接着开始安装环境,配置maven。
直到我打开了idea,导入项目,问题就出来了。
首先不熟悉软件,开始百度怎么导入,一步一步来,发现idea版本太高了,和网上的文章很多操作都不符合,但是按照第七感,一路next,开始导入maven包了,等了几分钟,看着好像导入结束了,然后一点开代码,一堆红色。
后面的时间,都在漫长的百度和尝试的路上,可惜最后都失败了。
被折磨了半天,最后身心俱疲,打开了0day安全 软件漏洞分析技术第二版
看书转移注意力,忘却java带给我的痛苦。
栈溢出
首先栈指的是一种数据结构,是一种先进后出的数据表。栈的常见操作有两种:压栈(push)、弹栈(pop);用于标识栈的属性也有两个:栈顶(top)、栈底(base)
首先了解一点:大多数情况下,局部变量在栈中的分布是相邻的,但也有可能出于编译优化等需要而有所例外。具体情况需要在动态调试中具体对待。
1 |
|
如果从代码逻辑来看,通过输入一个值传入password
,进入verify_password
进行处理,函数对输入的值与常量进行比较,返回的值,如果等于0则验证成功,反之验证失败。
分析代码
没有od,只能用x32dbg进行分析。首先进入到main
函数,从键盘输入一个值
然后跳转到verify_password
函数
F7
跟进函数,然后f8
走一遍
一路F8
走出函数后,观察寄存器中EAX
的值
EAX=FFFFFFFF
根据strcmp
的特性,当str1<str2
则返回负数,也就是-1
,这时内存中的值按照双字-1的补码存放,也就为0xFFFFFFFF,所以EAX得值就等于FFFFFFFF
下一个函数就是strcpy
复制函数,但是现在复制也突破不了密码验证,F8
跟回去main
函数内
这里,将eax
的值赋值给[ebp-4]
,此时eax=0xFFFFFF
,接着,让[ebp-4]
与0
进行比较,如果等于就进行跳转,否则就不跳转。所以现在就没跳转,输出了incorrect password!
密码验证突破
一开始被strcmp
这个函数卡住,一直在观察到底怎么执行,后面跟大佬一波有力沟通以后,才知道自己关注点错了。
他通过内存来解释,清晰易懂
首先 内存地址 007AF3DC
是authenticated
申请的空间 4字节
007AF3CC
是buffer
申请的空间 8字节 理论上只能设7个 因为要\00 收尾截断
由内存地址可知,buffer
的内存地址是在authenticated
这个变量上面,他只有8字节,现在程序逻辑就是,输入的值要与常量PASSWORD
的值一样,然后经过strcmp
比较,两个值相同返回0
,就能输出Congratulation! You have passed the verification!
所以此时,只需要输入字符串为8字节,并且大于常量1234567
就能绕过。
为什么要大于常量的1234657
将程序放入x32dbg
走一趟,观察内存地址就清楚了。
首先输入12345678
,此时经过strcmp
函数比较,也是大于常量,所以会返回1
首先将程序改了改,此时将buffer
和authenticated
的内存地址打印出来,方便观察内存变化。
程序首先断在了strcmp
函数处一路F8
走到函数底部,可以看到EAX的值等于1,意思就是经过比较,输入的值大于常量,所以返回1.
内存地址中现在就是01.
接着现在进入strcpy
函数
F8走一圈后,当跳到底部时候。观察buffer
的内存地址,现在这里还是01
当在走一步,就发生变化了,由于buffer
只有8个字节,复制了九个字节的值过来,所以最后一个直接将会被\00
转为NULL,所以变为0,因此authenticated
的值也从1转为0.此时密码成功突破验证。
可能输入12345678
看不太明显。所以我输入了比较长的一个值12345678qaz
。按照上面的分析,这个时候如果复制过去buffer
内,8
就会被转为NULL,就剩下qaz在后面
确实如此。看此时edi
和转储空间中内存地址的变化
为什么不能传小于常量的值
首先strcmp
函数比较,按照分析中发现,函数是逐字节进行比较,比如我输入一个8字节的字符串01234567
观察寄存器中EAX的值,此时是FFFFFFFF
,其实就是-1
,按照双字-1
的补码存放,为0xFFFFFFFF
那么此时,即使将其复制到BUFFER
中,字节溢出,将最后的两个FF
转为00
那返回去的值也是FFFFFF00
这样子就不能突破,将会继续循环,输入新的值
分析完了,也终于写完了,诶二进制还是好玩的。
继续去研究web,shiro的漏洞环境一定要搭起来。