re学习(36)看雪CTF 2017 -Crackme

百度网盘已收集,需要回顾在文件夹【CTF题库收集】查看即可

刚开始先运行一下

这是一道crackme类型题目,是一道看雪CTF上的竞赛题,用OD进行分析一下。

刚开始用的是IDA分析,分析了半天也没有看出来什么,然后就在网上搜,还真搜出来了,直接上flag,解决了我的燃眉之急,哈哈,事后又看了看wp,才知道了真正的解法,还是应该总结的,毕竟有的题目是搜不到的......

问题:为什么用OD,不用IDA呢?

OD可以动态跟踪变量变化过程。OD反汇编代码可以着色,比较醒目。Crackme类题目

                              →动调首选

IDA可以看到数据结构乃至反汇编至C代码,有利于把握整体结构。

                              →静调首选

在OD中运行程序,发现在地址00401494处运行函数后出来messagebox,可知这是关键函数,F2下断点,F7跟进

在跟进这个函数的过程中,会发生Windows GUI -- 消息循环与消息,可以参考这篇文章

Windows GUI -- 消息循环与消息_gui 消息循环_我家有一口鱼塘的博客-CSDN博客

好像是必须得输入东西才能跳出这个循环,然后下断点,F9运行并输入字符跳出循环

在哪里下断点呢?如果在这里下断点,下图,

运行完后,就会直接报错了因为汇编指令retn用来结束当前过程返回到上一调用过程

所以最早得在这条汇编指令的下一条指令下断点

成功在断点处运行下来了,接下来就是反汇编的关键代码了:
 

CPU Disasm
地址        十六进制数据            指令                             注释                                                             标签
00401225   .  83F8 04       CMP EAX,4
00401228   .  59            POP ECX
00401229   .  0F85 A0000000 JNE 004012CF                   strlen()函数
0040122F   .  6A 30         PUSH 30
00401231   .  59            POP ECX
00401232   .  384D E4       CMP BYTE PTR SS:[EBP-1C],CL    判断key第1个字符是否为“0”
00401235   .  0F84 94000000 JE 004012CF
0040123B   .  384D E5       CMP BYTE PTR SS:[EBP-1B],CL    判断key第2个字符是否为“0”
0040123E   .  0F84 8B000000 JE 004012CF
00401244   .  384D E6       CMP BYTE PTR SS:[EBP-1A],CL    判断key第3个字符是否为“0”
00401247   .  0F84 82000000 JE 004012CF
0040124D   .  384D E7       CMP BYTE PTR SS:[EBP-19],CL    判断key第4个字符是否为“0”
00401250   .  74 7D         JE SHORT 004012CF
00401252   .  807D E4 31    CMP BYTE PTR SS:[EBP-1C],31    判断key第1个字符是否等于“1”,不等于则直接跳转弹出“error”
00401256   .  75 77         JNE SHORT 004012CF
00401258   .  807D E5 35    CMP BYTE PTR SS:[EBP-1B],35    判断key第2个字符是否等于“5”,不等于则直接跳转弹出“error”
0040125C   .  75 71         JNE SHORT 004012CF
0040125E   .  74 03         JE SHORT 00401263              花指令
00401260   .  75 01         JNE SHORT 00401263
00401262      E8            DB E8                          CHAR 'è'
00401263   >  66:B8 0800    MOV AX,8
00401267   .  66:35 0700    XOR AX,0007
0040126B   .  0FBE45 E6     MOVSX EAX,BYTE PTR SS:[EBP-1A] 取输入key的第3位数
0040126F   .  2BC1          SUB EAX,ECX                    减去0x30,得到a
00401271   .  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX   把得到的值保存在[ebp-0x4]中
00401274   .  0FBE45 E4     MOVSX EAX,BYTE PTR SS:[EBP-1C] 取输入key的第1位值“1”
00401278   .  DB45 FC       FILD DWORD PTR SS:[EBP-4]      把[ebp-0x4]中保存的值压入到ST(0)中
0040127B   .  2BC1          SUB EAX,ECX                    0x31减去0x30,则为1
0040127D   .  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX   把得到的值1保存在[ebp-0x4]中
00401280   .  0FBE45 E5     MOVSX EAX,BYTE PTR SS:[EBP-1B] 取输入key的第2位值“5”
00401284   .  DB45 FC       FILD DWORD PTR SS:[EBP-4]      把[ebp-0x4]中保存的值1压入到ST(0)中
00401287   .  2BC1          SUB EAX,ECX                    0x35减去0x30,则为5
00401289   .  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX   把得到的值5保存在[ebp-0x4]中
0040128C   .  DA75 FC       FIDIV DWORD PTR SS:[EBP-4]     st(0)中的值1除以[ebp-0x4]中的值5,得到0.2保存到st(0)中
0040128F   .  0FBE45 E7     MOVSX EAX,BYTE PTR SS:[EBP-19] 取输入key的第4位值
00401293   .  2BC1          SUB EAX,ECX                    减去0x30,得到b
00401295   .  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX   把得到的值b保存在[ebp-0x4]中
00401298   .  DEE9          FSUBP ST(1),ST                 st(1)-st并保存在st(0)中,即(a-0.2)
0040129A   .  DA4D FC       FIMUL DWORD PTR SS:[EBP-4]     st(0)乘以[ebp-0x4] 中保存的值b,结果保存在st(0)中
0040129D   .  D80D 1C714000 FMUL DWORD PTR DS:[40711C]     数据段ds:[0x40711C]值为16,这里则是st(0)乘以16
004012A3   .  D95D FC       FSTP DWORD PTR SS:[EBP-4]      把上面得到值保存在[ebp-0x4]中
004012A6   .  74 03         JE SHORT 004012AB
004012A8   .  75 01         JNE SHORT 004012AB
004012AA      E8            DB E8                          CHAR 'è'
004012AB  />  66:B8 0800    MOV AX,8
004012AF  |.  66:35 0700    XOR AX,0007
004012B3  |.  D945 FC       FLD DWORD PTR SS:[EBP-4]       取出[ebp-0x4]中保存的值
004012B6  |.  D81D 18714000 FCOMP DWORD PTR DS:[407118]    得出的值与384比较是否相等
004012BC  |.  6A 00         PUSH 0
004012BE  |.  68 78804000   PUSH OFFSET 00408078           ASCII "CrackMe 2017 CTF"
004012C3  |.  DFE0          FSTSW AX
004012C5  |.  9E            SAHF
004012C6  |.  75 0E         JNE SHORT 004012D6
004012C8  |.  68 5C804000   PUSH OFFSET 0040805C           ASCII "Registration successful !"
004012CD  \.  EB 0C         JMP SHORT 004012DB
004012CF  />  6A 00         PUSH 0
004012D1  |.  68 48804000   PUSH OFFSET 00408048           ASCII "CrackMe 2017 CTF v2"
004012D6  |>  68 40804000   PUSH OFFSET 00408040           ASCII "error !"

 0x01  判断输入值的长度

可以查看到我们输入后传入值的部分,并通过 strlen 来获取其长度是否为 4 ,不为 4 则直接跳转到 004012CF

现在可以确定key的长度为4

0x02 验证key前2位的值

这里验证key的值是否都为字符串“0”,如果4位的key又一个为“0”,则直接跳转到“error”弹出框

然后接着就是继续验证key前2位字符串的值,即给出字符串的前2位为“15”
如果 key 的前 2 位的值不为 “15” ,则直接跳转到 “error” 弹出框

这里得到前2为key的值为“15”

0x03 分析算法

这里运作流程:

1、取key中第3位的十六进制值,然后减去0x30,这里则假定值为a

2、取key中第1位值为“1”的十六进制值即0x31,然后减去0x30,0x31-0x30 =1

3、取key中第2位值为“5”的十六进制值即0x35,然后减去0x30,0x31-0x30 =5 ,接着就是1除以5得出浮点数0.2

4、取key中第4位的十六进制值,然后减去0x30,这里则假定值为b

5、接着就是(a-0.2)*b乘以16得出的结果为c

6、判断c与384是否相等,相等则Registration successful !,不相同则“error”
公式: (a-0.2)*b*16 = 384 求解 a 和 b
0x04 编写算法脚本

这里根据上面分析,写了个简单的脚本,跑出了 2 个结果 “151N” 和 "1555"

for i in range(126):
    for j in range(126):
        if(((i-48)-0.2)*(j-48) == 24):
            print(i)
            print(j)
            print("15"+"%s"%(chr(i))+"%s"%(chr(j)))
            print("------")

猜你喜欢

转载自blog.csdn.net/m0_66039322/article/details/132619302