实验1:更改密码验证结果

1. 实验目标

  • 读懂并能够独立编写密码验证的小程序。

  • 运行Ollydbg,并学习用其调试密码验证小程序。

  • 通过修改汇编语句来修改程序的判断条件,改变程序的运行路线。

  • 信安思考题:

            破解crackme.exe程序,尝试绕过密码验证逻辑,至少采用2种破解方式方法,并提交破解后的程序。

  • 双培思考题:

            尝试通过其他方法绕过test.exe的密码验证,方法可自由选择,至少找出2种破解方法,并提交破解后的程序。

2. 实验要求

  • 详述修改过程
  • 实验结果需要截图证明
  • 绘出程序运行的结构图,以及修改原理的图示(通过程序运行的结构图)

3. 测试步骤与结果

  1. 生成exe文件

            需要生成对应exe文件,此处采用Dev-C++只需要编译运行即可在当前目录下生成同名的exe文件。需要注意的是OllyDBG只能反编译32位的exe程序,所以Dev-C++也需要如下图选择32位生成,再进行编译。

  2. 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

  1. 运行crackme.exe程序

            尝试输入数据进行注册,可以看到显示注册失败,猜测其对输入的内容进行比对从而确认是否注册成功。

  2. crackme.exe拖入Ollydbg。

    根据文本字串定位到程序比对的程序段。

    如下图,可以看到在此字串附近有判断验证字串是否相符的语句。

  3. 在相应位置设置断点并运行动态调试,输入密码为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文件。