软安实验1—密码验证
实验1:更改密码验证结果
1. 实验目标
读懂并能够独立编写密码验证的小程序。
运行Ollydbg,并学习用其调试密码验证小程序。
通过修改汇编语句来修改程序的判断条件,改变程序的运行路线。
信安思考题:
破解crackme.exe程序,尝试绕过密码验证逻辑,至少采用2种破解方式方法,并提交破解后的程序。
双培思考题:
尝试通过其他方法绕过test.exe的密码验证,方法可自由选择,至少找出2种破解方法,并提交破解后的程序。
2. 实验要求
- 详述修改过程
- 实验结果需要截图证明
- 绘出程序运行的结构图,以及修改原理的图示(通过程序运行的结构图)
3. 测试步骤与结果
生成exe文件
需要生成对应exe文件,此处采用
Dev-C++
只需要编译运行即可在当前目录下生成同名的exe文件。需要注意的是OllyDBG只能反编译32位的exe程序,所以Dev-C++
也需要如下图选择32位生成,再进行编译。OllyDBG调试
将创建好的exe可执行文件拖入OllyDBG中,得到反编译界面。
通过运行exe文件,可以了解到输入正确密码会弹出
Congratulation! You have passed the verification!
,错误时弹出incorrect password!
,因此可以判断其输出前存在判断语句,判断输入字符串是否与密码符合,从而输出结果。可以看到若密码正确EAX寄存器会等于0,如果判断结果等于0,则输出密码正确的语句。
若在不知道密码的情况下,先通过输出的字符串定位到结果字符串的输出位置,再往上找可以发现
je
的跳转指令,在网上找即可找到判断对比结果的汇编代码。由此可以发现,将je
改为jne
则结果会直接颠倒,输入正确密码时输出incorrect password!
,输入其他错误密码时则会判定密码正确。具体更改,只需要在跳转前设置一个断点,
右键->Binary->Edit
,将je
对应的二进制值74
改为jne
对应的75
二进制值即可。继续运行,测试即可发现判断输出结果相反。
4. 思考题
信安
破解crackme.exe程序,尝试绕过密码验证逻辑,至少采用2种破解方式方法,并提交破解后的程序。
解析crackme.exe
运行
crackme.exe
程序尝试输入数据进行注册,可以看到显示注册失败,猜测其对输入的内容进行比对从而确认是否注册成功。
将
crackme.exe
拖入Ollydbg。根据文本字串定位到程序比对的程序段。
如下图,可以看到在此字串附近有判断验证字串是否相符的语句。
在相应位置设置断点并运行动态调试,输入密码为
crackmepassword
可以更好的观察程序的运行。程序会将输入的密码存储的起始地址保存到EAX寄存器中,正确的密码存储的起始地址保存到ESP寄存器中。将通过循环一次次取值并赋值给EDX和EBX后八位,之后进行对比,如果对比一致则继续循环,反之跳出循环运行注册不成功的代码。
CL作为跳出循环的条件,当其通过TEST汇编指令测试为0时表示循环到了用户输入字符串的结尾截断符00,此时跳出循环并运行对比成功的指令。
方法一:修改比对的失败跳转地址
由上述分析可以看到当CL和DL比对不一致时会通过语句JNZ SHORT 00401611
跳转执行比对不成功的指令。可以将跳转指令地址更改为JNZ SHORT 0040160D
,既可以在对比不成功的时候会跳转到比对成功跳出循环的下一语句。
需要注意的是一个循环中是比对两个字符,所以需要改两条语句。另外,如果将JNZ
改为JZ
可能会在出现恰巧与密码一致的字符时判断为注册失败。
可以看到输入密码为LLrber
时,运行结束弹出注册成功的结果。
方法二:更改判断逻辑
通过分析如果密码比对成功是将EAX清零并跳转到00401616
,而比对失败是跳转到00401611
后将EAX通过SBB运算为-1
,之后TEST验证EAX是否为零来判断比对是否成功。
由此在00401618
前方设置断点,并输入非正确密码运行到此处,将TEST EAX,EAX
改为XOR EAX,EAX
,即将待判断数值改成恒为零,从而实现0040161E
处的判断跳转。双击更改。
继续运行,可以看到注册成功。
双培
尝试通过其他方法绕过test.exe的密码验证,方法可自由选择,至少找出2种破解方法,并提交破解后的程序。
方法一:修改判断条件
上面的方法是将判断后的跳转语句反过来,同时还可以从判断条件下手,将判断条件改为输入错误密码时的结果就可实现。
可以在汇编语言中看到其调用了strcmp函数,其两个字符串相同返回值为0,两个字符串不同,根据前后字符串大小返回大于或小于0的数。
通过动态调试可以看到当输入不正确的字符时,EAX返回值为FFFFFFFF
表示-1,因此将对比语句cmp
处的判断条件改为-1,则只要输入比密码小的字符串即可通过。
最后保存成新的exe文件,右键->Copy to executable->All modifications->Copy
。
之后会弹出一个新的窗口,右键->Save file
即可保存。之后运行测试。
方法二:寄存器赋值
通过上面判断条件的改值,将原本判断条件设定的值更改。当然还可以将输入进来的值更改,而EAX寄存器专门用来存储返回值,由此可以更改strcmp中的EAX寄存器的值,即可更改返回值。
首先,在call <jmp.&msvcrt.strcmp>
处设置断点,运行到此处时进行步入操作。可以看到进入函数后,通过跳转进入下图处,然后可以看到对EAX先是sbb
自减为-1。若在此时直接将0赋值给EAX即可更改返回值。
只需要在返回之前将EAX赋值回0即可,同上方更改机器码操作相同。
同样保存后运行,最后即可达到不管输入任何数据均可输入成功。
但是因为此处更改的是strcmp中的函数,所以保存出来的exe文件是系统文件,目前不知道如何保存带有系统文件更改的exe文件。