11

[原创] CTF2017 第8题 loudy Crackme 破解过程(迟来的成功)

爱琴海 2017-6-18 16:44 1243

序言:


        这几天有点感冒,看反汇编代码就头晕,看不下去了休息、休息浪费了一天比赛时间。算法在比赛结束前已经搞得清清楚楚,只可惜没来得及用python写个高效率穷举的程序。在群里发誓要把它破出来,所以现在补上破文,以免浪费了时间和精力。对第三段注册码的穷举我使用了彩虹表(索引)的办法,弥补了python执行效率低的问题,脑洞大开,代码都贴上了,希望思路可以供今后借鉴。

        本题作者构思全面,涵盖了TLS、虚拟机、内存校验、SMC、多线程、密码学算法(RSA)、大数运算等反调试、反分析手段。难度算高的了,也许作者是奔着防御组冠军去的,如果对算法第三段部分再进行严谨构思,应该算很棒的作品了。

        按以往惯例,文章末尾都会总结一下,本文破例,就写在前面了,需要建议各位新手的是对付这样的算法很复杂、流程很乱的作品,应合理使用OD的RUN跟踪功能,记录执行过的每条重要指令和跳转,动态记录注释信息和寄存器内容,随时重放函数和执行流程,助你准确调试分析,动态图演示一下:



一、查壳、PE格式,了解作品(套路了)


//查壳 Microsoft Visual C/C++(2005)[msvcrt]
//算法侦查:Big number:406490  Referenced at 40213C-->提示了作品可能包含大数运算
//PE格式检查:TLS 3 FUNC:402D00 402D20 402D30 -->提示了作品可能利用TLS反调试

//双击运行查看界面,命令行模式,输入错误注册码,弹出对话框,运行时间略久,怀疑计算量不少


二、TLS反调试


//TLS 1 反调试:
public TlsCallback_0
TlsCallback_0 proc near
var_4= dword ptr -4
push    ecx
push    eax
mov     eax, large fs:30h
movzx   eax, byte ptr [eax+2]
mov     [esp+8+var_4], eax
pop     eax
pop     ecx
retn    0Ch
TlsCallback_0 endp

//TLS 2 反调试
public TlsCallback_1
TlsCallback_1 proc near
call    sub_401000
retn    0Ch
TlsCallback_1 endp

//TLS 3 反调试
public TlsCallback_2
TlsCallback_2 proc near
arg_4= dword ptr  8
cmp     [esp+arg_4], 1
jnz     short locret_402D3C
call    sub_402C70
locret_402D3C:
retn    0Ch
TlsCallback_2 endp

//OD载入,断TLS,勾选隐藏OD插件配置,TLS跟踪一遍发现对开了插件的OD没有影响,开了很多线程,比较卡。


三、主流程、VM分析


粗略翻一下代码,找到402D40关键函数,在402D40下断

00402D40    55              PUSH EBP
00402D41    8BEC            MOV EBP,ESP
00402D43    83E4 F8         AND ESP,0xFFFFFFF8
00402D46    81EC AC010000   SUB ESP,0x1AC
00402D4C    A1 00604000     MOV EAX,DWORD PTR DS:[0x406000]

很快就能跟到虚拟机部分:

//ECX指向了下表Array1

0040355F    3A11            CMP DL,BYTE PTR DS:[ECX]

//Array1
0012FEE8  18 0D 16 16 45 0D 02 11 49 03 18 4C 03 01 1B 50  .E.ILP
0012FEF8  03 1B 14 1C 01 57 93 7C 18 0D 16 44 02 09 13 48  W搢.D.H
0012FF08  1D 02 0E 4C 1F 07 08 18 05 52 18 11 0C 57 00 00  LR.W..
0012FF18  AA 15 20 01 00 00 AA 15 40 01 00 00 A0 10 00 00  ? ..?@..?..
0012FF28  00 00 A8 A0 10 F0 00 00 00 A8 A0 10 60 01 00 00  ..?..`..
0012FF38  A7 AA 11 80 00 00 00 AA 10 60 00 00 00 AA 12 B0  И€...?`...?
0012FF48  00 00 00 A9 A2 EA A6 0E A0 10 20 01 00 00 A0 11  ...軎? ..?
0012FF58  10 01 00 00 A4 A5 A0 10 40 01 00 00 A0 11 10 01  ..ぅ?@..?
0012FF68  00 00 A4 A5

//ESI指向了下表Array2,[ESI+0x14]指向了EIP,EIP包含操作数同时又指向了函数入口

00403576    8B4E 14         MOV ECX,DWORD PTR DS:[ESI+0x14]                   ; 貌似取虚拟指令
//Array2
0012FDD0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0012FDE0  00 00 00 00 1E FF 12 00 A0 00 00 00 C0 34 40 00  .....?..?@.
0012FDF0  A1 00 00 00 C0 33 40 00 A2 00 00 00 D0 33 40 00  ?..?@.?..?@.
0012FE00  A4 00 00 00 40 34 40 00 A5 00 00 00 70 34 40 00  ?..@4@.?..p4@.
0012FE10  A3 00 00 00 30 34 40 00 A6 00 00 00 00 34 40 00  ?..04@.?...4@.
0012FE20  A7 00 00 00 80 34 40 00 A8 00 00 00 A0 34 40 00  ?..€4@.?..?@.
0012FE30  A9 00 00 00 00 27 40 00 AA 00 00 00 20 27 40 00  ?...'@.?.. '@.

//Array2表整理如下:

A0 —— 4034C0
A1 —— 4033C0
A2 —— 4033D0
A4 —— 403440
A5 —— 403470
A3 —— 403430
A6 —— 403400
A7 —— 403480
A8 —— 4034A0
A9 —— 402700
AA —— 402720

//Array1表整理如下:

————————————————————————————————
AA  15  20 01 00 00 —— 402720
//402720 (address,offset,mode)
//0x15子程序选择分支,操作数为偏移,解密成功字符信息
//比如将EBP压入堆栈,EBP存放需要解密的参考基地址,则操作数 00000120 作为偏移
//EBP+0x20指向需要参考源地址,EBP+0x120指向需要解密的地址,0x15则代表对应函数的分支对应不同模式,有0x10、0x11、0x12、0x15

————————————————————————————————
AA  15  40 01 00 00 —— 402720
//402720 (address,offset,mode)
//0x15子程序选择分支,操作数为偏移,解密成功字符信息
//比如将EBP压入堆栈,EBP存放需要解密的参考基地址,则操作数 00000140 作为偏移
//EBP+0x20指向需要参考源地址,EBP+0x140指向需要解密的地址,0x15则代表对应函数的分支对应不同模式,有0x10、0x11、0x12、0x15

————————————————————————————————
A0  10  00 00 00 00 —— 4034C0
//0x10 —— MOV VM_eax,0x0
//0x10子程序选择分支对应VM多个寄存器,操作数为数值,将数值存放VM_Eax=0x0

————————————————————————————————
A8                  —— 4034A0
//Printf
//单指令,Printf,显示[EBP+VM_Eax]地址字符串,标题

————————————————————————————————
A0  10  F0 00 00 00 —— 4034C0
//0x10 —— MOV VM_eax,0xF0
//0x10子程序选择分支,操作数为数值,将数值存放到VM_Eax寄存器,VM_Eax=0xF0

————————————————————————————————
A8                  —— 4034A0
//Printf
//单指令,Printf,显示[EBP+VM_Eax]地址字符串,提示输入

————————————————————————————————
A0  10  60 01 00 00 —— 4034C0
//0x10 —— MOV VM_eax,0x160
//0x10子程序选择分支对应VM多个寄存器,操作数为数值,将数值存放VM_Eax=0x160

————————————————————————————————
A7                  —— 403480
//Scanf
//单指令,Scanf,输入的字符存放在[EBP+VM_Eax]地址(0xA0字节空间,不知道是否存在溢出问题)

————————————————————————————————
AA  11  80 00 00 00 —— 402720
//402720 (address,offset,mode)
//0x11子程序选择分支,操作数为偏移,
//比如将EBP压入堆栈,EBP存放需要解密的参考基地址,则操作数 00000080 作为偏移
//EBP+0x20指向需要参考源地址,EBP+0x80指向需要解密的地址,0x11则代表对应函数的分支对应不同模式,有0x10、0x11、0x12、0x15
//解密前:
00406038  50 57 57 5D 52 5E 57 5E 5C 58 5B 5F 5B 5C 5A 48  PWW]R^W^\X[_[\ZH
00406048  45 4A 47 40 47 42 40 4D 48 4D 51 57 52 54 57 51  EJG@GB@MHMQWRTWQ
00406058  5F 59 51 52 5F 5F 55 58 5E 41 42 00 58 55 56 57  _YQR__UX^AB
//解密后:
00406038  31 35 34 39 37 38 30 36 35 32 30 33 36 32 35 38  1549780652036258
00406048  34 38 34 34 32 34 37 35 31 37 30 35 31 30 32 37  4844247517051027
00406058  38 31 38 38 34 33 38 36 31 31 33                 81884386113

————————————————————————————————
AA  10  60 00 00 00 —— 402720
//402720 (address,offset,mode)
//0x10子程序选择分支,操作数为偏移,
//比如将EBP压入堆栈,EBP存放需要解密的参考基地址,则操作数 00000060 作为偏移
//EBP+0x20指向需要参考源地址,EBP+0x60指向需要解密的地址,0x10则代表对应函数的分支对应不同模式,有0x10、0x11、0x12、0x15
//解密前:
00406020  58 5A 54 52 50 52 54 5A 58 5A 52 54 5A 58 5A 44  XZTRPRTZXZRTZXZD
00406030  42 40 42 44 44 44 44 00                          B@BDDDD.
//解密后:
00406020  39 38 37 36 35 34 33 32 31 30 39 38 37 36 35 34  9876543210987654
00406030  33 32 31 30 31 32 33 00                          3210123.

————————————————————————————————
AA  12  B0 00 00 00 —— 402720
//402720 (address,offset,mode)
//0x12子程序选择分支,操作数为偏移,
//比如将EBP压入堆栈,EBP存放需要解密的参考基地址,则操作数 000000B0 作为偏移
//EBP+0x20指向需要参考源地址,EBP+0xB0指向需要解密的地址,0x12则代表对应函数的分支对应不同模式,有0x10、0x11、0x12、0x15
//解密前:
00406064  58 55 56 57 54 54 53 5E 51 5A 52 5B 58 5D 5E 42  XUVWTTS^QZR[X]^B
00406074  45 44 4B 44 4C 41 42 4B 48 48 55 54 5B 54 5C 51  EDKDLABKHHUT[T\Q
00406084  52 5B 58 58 5F 5A 55 5E 00                       R[XX_ZU^.
//解密后:
00406064  39 37 35 33 31 32 34 36 38 30 39 37 35 33 31 32  9753124680975312
00406074  34 36 38 30 39 37 35 33 31 32 34 36 38 30 39 37  4680975312468097
00406084  35 33 31 32 34 36 38 30 00                       53124680.

————————————————————————————————
A9                  —— 402700
//调用402450对输入的注册码进行计算,按每4位一组,相邻两位做计算,生成3位密文,理论上密文长度大概是输入长度的3/4
//例如输入“12345678”
//第1、2位:4*(0x31+4)+(0x32+4)//16 = D7
//第2、3位:16*(0x32+4)+(0x33+4)//4 = 6D
//第3、4位:64*(0x33+4)+(0x34+4)    = F8
//第4、5位:4*(0x35+4)+(0x36+4)//16 = E7
//第5、6位:16*(0x36+4)+(0x37+4)//4 = AE
//第6、7位:64*(0x37+4)+(0x38+4)    = FC
0012FC38  D7 6D F8 E7 AE FC 00 00                          譵.....

格式整理一下:
每组第1、2位字符格式转换:
== 0x2B --> 0x3E
== 0x2F --> 0x3F
<= 0x39 --> sn+0x4
== 0x3D --> 0x40
<= 0x5A --> sn-0x41
>  0x7A --> 0x40
ELSE    --> sn-0x47

每组第3、4位字符格式转换:
== 0x3D --> Return 0 结束本次函数
== 0x2B --> 0x3E
== 0x2F --> 0x3F
<= 0x39 --> sn+0x4
<= 0x5A --> sn-0x41
>  0x7A --> 0x40
ELSE    --> sn-0x47
————————————————————————————————

A2  EA              —— 4033D0
//CMP VM_Eax,0x1
//比较VM_Eax与0x1,将比较结果True=0x1,False=0写入VM_Zf
//也就是比较上个函数的返回值

————————————————————————————————
A6  0E              —— 403400
//JNZ 0E
//对上条指令的跳转判断,正确流程是不跳走

————————————————————————————————
正确流程:
————————————————————————————————
A0  10 20 01 00 00  —— 4034C0
//0x10 —— MOV VM_eax,0x120
//0x10子程序选择分支对应VM多个寄存器,操作数为数值,将数值存放VM_Eax=0x120

————————————————————————————————
A0  11 10 01 00 00  —— 4034C0
//0x11 —— MOV VM_ecx,0x110
//0x11子程序选择分支对应VM多个寄存器,操作数为数值,将数值存放VM_Ecx=0x110

————————————————————————————————
A4                  —— 403440
//MSG [EBP+VM_Eax]
//取 VM_Eax 正确为0x120,错误为0x140

————————————————————————————————
A5                  —— 403470
//ExitProcess

————————————————————————————————
错误流程:
————————————————————————————————
A0  10 40 01 00 00  —— 4034C0
//0x10 —— MOV VM_eax,0x140
//0x10子程序选择分支对应VM多个寄存器,操作数为数值,将数值存放VM_Eax=0x140

————————————————————————————————
A0  11 10 01 00 00  —— 4034C0
//0x11 —— MOV VM_ecx,0x110
//0x11子程序选择分支对应VM多个寄存器,操作数为数值,将数值存放VM_Ecx=0x110

————————————————————————————————
A4                  —— 403440
//MSG [EBP+VM_Eax]
//取 VM_Eax 正确为0x120,错误为0x140

————————————————————————————————
A5                  —— 403470 
//ExitProcess

————————————————————————————————

//还原VM程序如下:

//CALL 402720 (EBP,0x120,0x15) //解密字符
//CALL 402720 (EBP,0x140,0x15) //解密字符
//MOV VM_eax,0x0
//Printf (EBP+VM_Eax) //显示字符
//MOV VM_eax,0xF0
//Printf (EBP+VM_Eax) //显示字符
//MOV VM_eax,0x160
//Scanf (EBP+VM_Eax) //获得输入
//CALL 402720 (EBP,0x80,0x11) //解密字符
//CALL 402720 (EBP,0x60,0x10) //解密字符
//CALL 402720 (EBP,0xB0,0x12) //解密字符
//CALL 402700 //对输入的注册码进行计算,按每4位一组,相邻两位做计算,生成3位密文,校验成功返回0x1,失败返回0x0
//CMP VM_Eax,0x1
//JNZ 0E //对上条指令的跳转判断,正确不跳走
//MOV VM_eax,0x120
//MOV VM_ecx,0x110
//MSG [EBP+VM_Eax]
//CALL ExitProcess
0E:
//MOV VM_eax,0x140
//MOV VM_ecx,0x110
//MSG [EBP+VM_Eax]
//ExitProcess

//断点403571就可以跟踪到虚拟机每次调用的函数入口

00403551    33C0            XOR EAX,EAX
00403553    8BCF            MOV ECX,EDI
00403555    83F8 20         CMP EAX,0x20
00403558    7D 1C           JGE X8.00403576
0040355A    8B56 14         MOV EDX,DWORD PTR DS:[ESI+0x14]                   ; Array2表 [ESI+0x14] —— Vm_Eip
0040355D    8A12            MOV DL,BYTE PTR DS:[EDX]                          ; 取虚拟指令Array1 Byte —— VM_Code
0040355F    3A11            CMP DL,BYTE PTR DS:[ECX]                          ; 搜索 VM_Code 在 Array2 的位置,计算函数入口用
00403561    74 08           JE X8.0040356B
00403563    83C0 01         ADD EAX,0x1                                       ; 搜索计数器+1
00403566    83C1 08         ADD ECX,0x8                                       ; 每次跨越8字节搜索+8
00403569  ^ EB EA           JMP X8.00403555
0040356B    8B44C6 1C       MOV EAX,DWORD PTR DS:[ESI+EAX*8+0x1C]             ; 子程序入口
0040356F    55              PUSH EBP                                          ; 参数2
00403570    56              PUSH ESI                                          ; 参数1
00403571    FFD0            CALL EAX                                          ; 调用子程序,奔跑吧兄弟
00403573    83C4 08         ADD ESP,0x8
00403576    8B4E 14         MOV ECX,DWORD PTR DS:[ESI+0x14]                   ; Array2表 [ESI+0x14] —— Vm_Eip
00403579    8039 A3         CMP BYTE PTR DS:[ECX],0xA3                        ; 0xA3 VM_Quit
0040357C  ^ 75 D3           JNZ X8.00403551
0040357E    5F              POP EDI
0040357F    5D              POP EBP
00403580    C3              RETN


四、算法流程一:根据第三节VM,搞清楚 CALL 402700 才可完成破解


//现在重新开始,断点 402700 的末尾附近貌似死循环的位置,等待全局变量赋值

004025D0   > /A1 ECB69900   MOV EAX,DWORD PTR DS:[0x99B6EC]                 ;  这里真奇怪,必须留意
004025D5   . |83F8 00       CMP EAX,0x0
004025D8   . |74 02         JE X8.004025DC
004025DA   .^\EB F4         JMP X8.004025D0
004025DC   >  68 EA264000   PUSH 8.004026EA
004025E1   .  C3            RETN                                            ;  RET 用作跳转到 004026EA
004025E2   .  8D8D F0FEFFFF LEA ECX,DWORD PTR SS:[EBP-0x110]
004025E8   .  51            PUSH ECX
004025E9   .  E8 D2F8FFFF   CALL 8.00401EC0

//赋值了全局变量[0x99B6EC]为1,改变了线程1的流程,线程1将此处末尾代码进行SMC,
//断点会出问题,必须跟踪线程1,待线程1修改完代码后再来此处断点继续跟踪算法流程。
//线程1,修改主算法流程末尾代码

0187FF80  68 C0 8B FF 8B DB                                h缷嬠..

00402910   >  8A5C0C 10     MOV BL,BYTE PTR SS:[ESP+ECX+0x10]
00402914   . |8D440C 10     LEA EAX,DWORD PTR SS:[ESP+ECX+0x10]
00402918   . |8A1406        MOV DL,BYTE PTR DS:[ESI+EAX]                    ;  取主流程算法末端代码SMC
0040291B   . |83C1 01       ADD ECX,0x1
0040291E   . |83F9 06       CMP ECX,0x6                                     ;  改变6字节
00402921   . |881C06        MOV BYTE PTR DS:[ESI+EAX],BL                    ;  0x8B替换
00402924   . |8810          MOV BYTE PTR DS:[EAX],DL
00402926   .^\7C E8         JL X8.00402910

//现在SMC之后,流程才能显现出来

004025C6   > \C705 ECB69900>MOV DWORD PTR DS:[0x99B6EC],0x1
004025D0   >  A1 ECB69900   MOV EAX,DWORD PTR DS:[0x99B6EC]                 ;  这里真奇怪,必须留意
004025D5   .  83F8 00       CMP EAX,0x0
004025D8   .  74 02         JE X8.004025DC
004025DA   .^ EB F4         JMP X8.004025D0
004025DC   >  8BC0          MOV EAX,EAX                                     ;  线程1修改完后,此处重新下断点
004025DE   .  8BFF          MOV EDI,EDI
004025E0   .  8BDB          MOV EBX,EBX
004025E2   .  8D8D F0FEFFFF LEA ECX,DWORD PTR SS:[EBP-0x110]
004025E8   .  51            PUSH ECX
004025E9   .  E8 D2F8FFFF   CALL 8.00401EC0

//线程1将全局变量重新置0,主流程算法可以继续

00402935   .  51            PUSH ECX
00402936   .  52            PUSH EDX
00402937   .  6A 06         PUSH 0x6
00402939   .  50            PUSH EAX
0040293A   .  FFD7          CALL EDI                                        ;  将4025DC内存属性改回来
0040293C   .  C705 ECB69900>MOV DWORD PTR DS:[0x99B6EC],0x0                 ;  修改全局变量置0,激活主流程算法末尾代码
00402946   .  B3 8B         MOV BL,0x8B                                     ;  BL=0x8B

//子算法程序,为了避免RDTSC反调试,可以断点在00401EFE

00401EC0  /$  55            PUSH EBP
00401EC1  |.  8BEC          MOV EBP,ESP
00401EC3  |.  83E4 F8       AND ESP,0xFFFFFFF8
00401EC6  |.  83EC 2C       SUB ESP,0x2C
00401EC9  |.  53            PUSH EBX
00401ECA  |.  56            PUSH ESI
00401ECB  |.  57            PUSH EDI
00401ECC  |.  8BC0          MOV EAX,EAX
00401ECE  |.  8BDB          MOV EBX,EBX
00401ED0  |.  8BC9          MOV ECX,ECX
00401ED2  |.  8BD2          MOV EDX,EDX
00401ED4  |.  8BC0          MOV EAX,EAX
00401ED6  |.  8BDB          MOV EBX,EBX
00401ED8  |.  8BC9          MOV ECX,ECX
00401EDA  |.  8BD2          MOV EDX,EDX
00401EDC  |.  8BC0          MOV EAX,EAX
00401EDE  |.  8BDB          MOV EBX,EBX
00401EE0  |.  8BC9          MOV ECX,ECX
00401EE2  |.  DBD2          FCMOVNBE ST,ST(2)
00401EE4  |.  0F31          RDTSC
00401EE6  |.  895424 10     MOV DWORD PTR SS:[ESP+0x10],EDX
00401EEA  |.  894424 14     MOV DWORD PTR SS:[ESP+0x14],EAX
00401EEE  |.  8B4424 10     MOV EAX,DWORD PTR SS:[ESP+0x10]
00401EF2  |.  6A 01         PUSH 0x1
00401EF4  |.  6A 00         PUSH 0x0
00401EF6  |.  6A 00         PUSH 0x0
00401EF8  |.  50            PUSH EAX
00401EF9  |.  E8 72280000   CALL 8.00404770
00401EFE  |.  8B4C24 14     MOV ECX,DWORD PTR SS:[ESP+0x14]
00401F02  |.  33F6          XOR ESI,ESI
00401F04  |.  03C1          ADD EAX,ECX
00401F06  |.  13D6          ADC EDX,ESI
00401F08  |.  894424 30     MOV DWORD PTR SS:[ESP+0x30],EAX
00401F0C  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+0x8]
00401F0F  |.  BB 46514000   MOV EBX,8.00405146                              ;  ASCII "cdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
00401F14  |.  2BD8          SUB EBX,EAX
00401F16  |.  895C24 18     MOV DWORD PTR SS:[ESP+0x18],EBX
00401F1A  |.  BB F2B69900   MOV EBX,8.0099B6F2
00401F1F  |.  2BD8          SUB EBX,EAX
00401F21  |.  895C24 1C     MOV DWORD PTR SS:[ESP+0x1C],EBX
00401F25  |.  BB 47514000   MOV EBX,8.00405147                              ;  ASCII "defghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
00401F2A  |.  2BD8          SUB EBX,EAX
00401F2C  |.  895C24 20     MOV DWORD PTR SS:[ESP+0x20],EBX
00401F30  |.  BB F3B69900   MOV EBX,8.0099B6F3
00401F35  |.  2BD8          SUB EBX,EAX
00401F37  |.  895C24 24     MOV DWORD PTR SS:[ESP+0x24],EBX
00401F3B  |.  BB 48514000   MOV EBX,8.00405148                              ;  ASCII "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
00401F40  |.  2BD8          SUB EBX,EAX
00401F42  |.  895424 34     MOV DWORD PTR SS:[ESP+0x34],EDX
00401F46  |.  895C24 28     MOV DWORD PTR SS:[ESP+0x28],EBX
00401F4A  |.  B9 44514000   MOV ECX,8.00405144                              ;  ASCII "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
00401F4F  |.  BE F0B69900   MOV ESI,8.0099B6F0
00401F54  |.  BF 45514000   MOV EDI,8.00405145                              ;  ASCII "bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
00401F59  |.  BA F1B69900   MOV EDX,8.0099B6F1
00401F5E  |.  2BD0          SUB EDX,EAX
00401F60  |.  BB F4B69900   MOV EBX,8.0099B6F4
00401F65  |.  2BC8          SUB ECX,EAX
00401F67  |.  2BF0          SUB ESI,EAX
00401F69  |.  2BF8          SUB EDI,EAX
00401F6B  |.  2BD8          SUB EBX,EAX
00401F6D  |.  895424 10     MOV DWORD PTR SS:[ESP+0x10],EDX
00401F71  |.  895C24 2C     MOV DWORD PTR SS:[ESP+0x2C],EBX
00401F75  |.  C74424 14 040>MOV DWORD PTR SS:[ESP+0x14],0x4
00401F7D  |.  EB 05         JMP X8.00401F84
00401F7F  |   90            NOP
00401F80  |>  8B5424 10     MOV EDX,DWORD PTR SS:[ESP+0x10]
00401F84  |>  0FB61C01      MOVZX EBX,BYTE PTR DS:[ECX+EAX]
00401F88  |.  3218          XOR BL,BYTE PTR DS:[EAX]
00401F8A  |.  83C0 05       ADD EAX,0x5
00401F8D  |.  885C06 FB     MOV BYTE PTR DS:[ESI+EAU-0x5],BL
00401F91  |.  0FB65C07 FB   MOVZX EBX,BYTE PTR DS:[EDI+EAU-0x5]
00401F96  |.  3258 FC       XOR BL,BYTE PTR DS:[EAX-0x4]
00401F99  |.  885C02 FB     MOV BYTE PTR DS:[EDX+EAU-0x5],BL
00401F9D  |.  8B5424 18     MOV EDX,DWORD PTR SS:[ESP+0x18]
00401FA1  |.  0FB65402 FB   MOVZX EDX,BYTE PTR DS:[EDX+EAU-0x5]
00401FA6  |.  3250 FD       XOR DL,BYTE PTR DS:[EAX-0x3]
00401FA9  |.  8B5C24 1C     MOV EBX,DWORD PTR SS:[ESP+0x1C]
00401FAD  |.  885403 FB     MOV BYTE PTR DS:[EBX+EAU-0x5],DL
00401FB1  |.  8B5424 20     MOV EDX,DWORD PTR SS:[ESP+0x20]
00401FB5  |.  0FB65402 FB   MOVZX EDX,BYTE PTR DS:[EDX+EAU-0x5]
00401FBA  |.  3250 FE       XOR DL,BYTE PTR DS:[EAX-0x2]
00401FBD  |.  8B5C24 24     MOV EBX,DWORD PTR SS:[ESP+0x24]
00401FC1  |.  885403 FB     MOV BYTE PTR DS:[EBX+EAU-0x5],DL
00401FC5  |.  8B5424 28     MOV EDX,DWORD PTR SS:[ESP+0x28]
00401FC9  |.  0FB65402 FB   MOVZX EDX,BYTE PTR DS:[EDX+EAU-0x5]
00401FCE  |.  3250 FF       XOR DL,BYTE PTR DS:[EAX-0x1]
00401FD1  |.  836C24 14 01  SUB DWORD PTR SS:[ESP+0x14],0x1
00401FD6  |.  8B5C24 2C     MOV EBX,DWORD PTR SS:[ESP+0x2C]
00401FDA  |.  885403 FB     MOV BYTE PTR DS:[EBX+EAU-0x5],DL
00401FDE  |.^ 75 A0         JNZ X8.00401F80
00401FE0  |.  68 20604000   PUSH 8.00406020                                 ;  ASCII "98765432109876543210123"
00401FE5  |.  68 F0B69900   PUSH 8.0099B6F0
00401FEA  |.  E8 B11E0000   CALL 8.00403EA0
00401FEF  |.  83C4 08       ADD ESP,0x8
00401FF2  |.  8BF0          MOV ESI,EAX
00401FF4  |.  0F31          RDTSC
00401FF6  |.  895424 14     MOV DWORD PTR SS:[ESP+0x14],EDX
00401FFA  |.  894424 10     MOV DWORD PTR SS:[ESP+0x10],EAX
00401FFE  |.  B9 38604000   MOV ECX,8.00406038                              ;  ASCII "1549780652036258484424751705102781884386113"
00402003  |.  8BC6          MOV EAX,ESI
00402005  |>  8A10          /MOV DL,BYTE PTR DS:[EAX]
00402007  |.  3A11          |CMP DL,BYTE PTR DS:[ECX]
00402009  |.  75 1A         |JNZ X8.00402025
0040200B  |.  84D2          |TEST DL,DL
0040200D  |.  74 12         |JE X8.00402021
0040200F  |.  8A50 01       |MOV DL,BYTE PTR DS:[EAX+0x1]
00402012  |.  3A51 01       |CMP DL,BYTE PTR DS:[ECX+0x1]
00402015  |.  75 0E         |JNZ X8.00402025
00402017  |.  83C0 02       |ADD EAX,0x2
0040201A  |.  83C1 02       |ADD ECX,0x2
0040201D  |.  84D2          |TEST DL,DL
0040201F  |.^ 75 E4         \JNZ X8.00402005
00402021  |>  33C0          XOR EAX,EAX
00402023  |.  EB 05         JMP X8.0040202A
00402025  |>  1BC0          SBB EAX,EAX
00402027  |.  83D8 FF       SBB EAX,-0x1
0040202A  |>  85C0          TEST EAX,EAX
0040202C  |.  75 42         JNZ X8.00402070
0040202E  |.  6A 01         PUSH 0x1
00402030  |.  50            PUSH EAX
00402031  |.  50            PUSH EAX
00402032  |.  8B4424 20     MOV EAX,DWORD PTR SS:[ESP+0x20]
00402036  |.  50            PUSH EAX
00402037  |.  E8 34270000   CALL 8.00404770
0040203C  |.  8B4C24 10     MOV ECX,DWORD PTR SS:[ESP+0x10]
00402040  |.  33FF          XOR EDI,EDI
00402042  |.  03C1          ADD EAX,ECX
00402044  |.  13D7          ADC EDX,EDI
00402046  |.  2B4424 30     SUB EAX,DWORD PTR SS:[ESP+0x30]
0040204A  |.  1B5424 34     SBB EDX,DWORD PTR SS:[ESP+0x34]
0040204E  |.  85D2          TEST EDX,EDX
00402050  |.  77 1E         JA X8.00402070
00402052  |.  72 07         JB X8.0040205B
00402054  |.  3D 38A28700   CMP EAX,8.0087A238
00402059  |.  73 15         JNB X8.00402070
0040205B  |>  56            PUSH ESI
0040205C  |.  E8 D11F0000   CALL <JMP.&MSVCR80.??3@YAXPAX@Z>
00402061  |.  83C4 04       ADD ESP,0x4
00402064  |.  B8 01000000   MOV EAX,0x1
00402069  |.  5F            POP EDI
0040206A  |.  5E            POP ESI
0040206B  |.  5B            POP EBX
0040206C  |.  8BE5          MOV ESP,EBP
0040206E  |.  5D            POP EBP
0040206F  |.  C3            RETN
00402070  |>  56            PUSH ESI
00402071  |.  E8 BC1F0000   CALL <JMP.&MSVCR80.??3@YAXPAX@Z>
00402076  |.  83C4 04       ADD ESP,0x4
00402079  |.  5F            POP EDI
0040207A  |.  5E            POP ESI
0040207B  |.  33C0          XOR EAX,EAX
0040207D  |.  5B            POP EBX
0040207E  |.  8BE5          MOV ESP,EBP
00402080  |.  5D            POP EBP
00402081  \.  C3            RETN
表A:
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz

00405144  61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70  abcdefghijklmnop
00405154  71 72 73 74 75 76 77 78 79 7A 61 62 63 64 65 66  qrstuvwxyzabcdef
00405164  67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76  ghijklmnopqrstuv
00405174  77 78 79 7A                                      wxyz

//密文与表A异或20字节,变成密文2:(假设输入“12345678”)

0099B6F0  B6 0F 9B 83 CB 9A 67 68 69 6A 6B 6C 6D 6E 6F 70  ?泝藲ghijklmnop
0099B700  71 72 73 74                                      qrst
00401FC1  |.  885403 FB     MOV BYTE PTR DS:[EBX+EAU-0x5],DL                ;  存入地址
00401FC5  |.  8B5424 28     MOV EDX,DWORD PTR SS:[ESP+0x28]
00401FC9  |.  0FB65402 FB   MOVZX EDX,BYTE PTR DS:[EDX+EAU-0x5]             ;  逐位读取表A
00401FCE  |.  3250 FF       XOR DL,BYTE PTR DS:[EAX-0x1]                    ;  逐位与密文异或
00401FD1  |.  836C24 14 01  SUB DWORD PTR SS:[ESP+0x14],0x1                 ;  4次,计算20字节
00401FD6  |.  8B5C24 2C     MOV EBX,DWORD PTR SS:[ESP+0x2C]
00401FDA  |.  885403 FB     MOV BYTE PTR DS:[EBX+EAU-0x5],DL                ;  存入地址
00401FDE  |.^ 75 A0         JNZ X8.00401F80                                 ;  循环4次,每次5字节,合计20字节
00401FE0  |.  68 20604000   PUSH 8.00406020                                 ;  ASCII "98765432109876543210123"
00401FE5  |.  68 F0B69900   PUSH 8.0099B6F0                                 ;  ASCII "15691529100101820131"
00401FEA  |.  E8 B11E0000   CALL 8.00403EA0                                 ;  大数乘法,将密文2进行乘法
00401FEF  |.  83C4 08       ADD ESP,0x8
00401FF2  |.  8BF0          MOV ESI,EAX
00401FF4  |.  0F31          RDTSC
00401FF6  |.  895424 14     MOV DWORD PTR SS:[ESP+0x14],EDX
00401FFA  |.  894424 10     MOV DWORD PTR SS:[ESP+0x10],EAX
00401FFE  |.  B9 38604000   MOV ECX,8.00406038                              ;  ASCII "1549780652036258484424751705102781884386113"

//1549780652036258484424751705102781884386113 / 98765432109876543210123 = 15691529100101820131
//也就是说倒过来要求密文1前20字节为:(21、22、62、63字节密文已经在上文推理出)
//“PWU]TSUQXZ[]]_WBAC@E”
//进行穷举注册码明文前28位:(结果已剔除特殊符号)

第 1 组注册码: UFdV
第 2 组注册码: XVRT
第 3 组注册码: VVFY
第 4 组注册码: Wltd
第 5 组注册码: XV9X
第 6 组注册码: QkFD
第 7 组注册码: QEUt

//即注册码前28位:UFdVXVRTVVFYWltdXV9XQkFDQEUt

signed int __cdecl sub_401EC0(int a1)
{
  unsigned __int64 v1; // rax@1
  int v2; // eax@1
  char *v3; // edx@1
  char v4; // bl@3
  bool v5; // zf@3
  const char *v6; // esi@4
  signed int result; // eax@6
  unsigned __int64 v8; // [sp+10h] [bp-28h]@4
  signed int v9; // [sp+14h] [bp-24h]@1
  unsigned __int64 v10; // [sp+30h] [bp-8h]@1

  v1 = __rdtsc();
  v10 = (unsigned int)v1 + ((unsigned __int64)HIDWORD(v1) << 32);
  v2 = a1;
  v3 = (char *)&unk_99B6F1 - a1;
  v9 = 4;
  while ( 1 )
  {
    v4 = *(_BYTE *)v2 ^ *((_BYTE *)&unk_405144 + v2 - a1);
    v2 += 5;
    *((_BYTE *)&unk_99B6F0 + v2 - a1 - 5) = v4;
    v3[v2 - 5] = *(_BYTE *)(v2 - 4) ^ *((_BYTE *)&unk_405145 + v2 - a1 - 5);
    *((_BYTE *)&unk_99B6F2 + v2 - a1 - 5) = *(_BYTE *)(v2 - 3) ^ *(&aCdefghijklmnop[v2 - 5] - a1);
    *((_BYTE *)&unk_99B6F3 + v2 - a1 - 5) = *(_BYTE *)(v2 - 2) ^ *(_BYTE *)(4215111 - a1 + v2 - 5);
    v5 = v9-- == 1;
    *(&byte_99B6F4[v2 - 5] - a1) = *(_BYTE *)(v2 - 1) ^ *(_BYTE *)(4215112 - a1 + v2 - 5);
    if ( v5 )
      break;
    v3 = (char *)&unk_99B6F1 - a1;
  }
  v6 = (const char *)sub_403EA0(&unk_99B6F0, a98765432109876);
  v8 = __rdtsc();
  if ( !strcmp(v6, a15497806520362)
    && (unsigned int)v8 + ((unsigned __int64)HIDWORD(v8) << 32) - v10 < (unsigned int)&unk_87A238 )
  {
    sub_404032(v6);
    result = 1;
  }
  else
  {
    sub_404032(v6);
    result = 0;
  }
  return result;


五、算法流程二


004025E2    8D8D F0FEFFFF   LEA ECX,DWORD PTR SS:[EBP-0x110]                ; 取回密文地址
004025E8    51              PUSH ECX
004025E9    E8 D2F8FFFF     CALL 8.00401EC0                                 ; 子算法流程跟进,大数乘法推理出密文1前20字节
004025EE    83C4 04         ADD ESP,0x4                                     ; 推理结果:密文1前20字节“PWU]TSUQXZ[]]_WBAC@E”
004025F1    85C0            TEST EAX,EAX                                    ; 穷举注册码前28位:UFdVXVRTVVFYWltdXV9XQkFDQEUt
004025F3    75 07           JNZ X8.004025FC                                 ; 必须跳
004025F5    33C0            XOR EAX,EAX
004025F7    E9 F0000000     JMP 8.004026EC
004025FC    C705 ECB69900 0>MOV DWORD PTR DS:[0x99B6EC],0x1                 ; 全局变量置1,线程1销毁上述算法代码
00402606    A1 ECB69900     MOV EAX,DWORD PTR DS:[0x99B6EC]
0040260B    83F8 00         CMP EAX,0x0
0040260E    74 02           JE X8.00402612
00402610  ^ EB F4           JMP X8.00402606
00402612    E8 D9010000     CALL <8.checkself>                              ; 待线程1销毁代码后,在此处下断

0040261E    6A 01           PUSH 0x1
00402620    FF15 04504000   CALL DWORD PTR DS:[<&KERNEL32.ExitProcess>]     ; kernel32.ExitProcess
00402626    C705 ECB69900 0>MOV DWORD PTR DS:[0x99B6EC],0x2                 ; 全局变量写2,跟进线程402970
00402630    A1 ECB69900     MOV EAX,DWORD PTR DS:[0x99B6EC]
00402635    83F8 00         CMP EAX,0x0
00402638    74 02           JE X8.0040263C
0040263A  ^ EB F4           JMP X8.00402630
0040263C    68 EA264000     PUSH 8.004026EA

0040263C   > \8BC0          MOV EAX,EAX                                     ;  待线程2运行完,在此断点就能断下
0040263E   .  8BDB          MOV EBX,EBX
00402640   .  8BFF          MOV EDI,EDI
00402642   .  8D85 F0FEFFFF LEA EAX,DWORD PTR SS:[EBP-0x110]                ;  密文地址
00402648   .  50            PUSH EAX
00402649   .  E8 42FAFFFF   CALL 8.00402090

0040212D  |.  68 64604000   PUSH 8.00406064                             ;  ASCII "9753124680975312468097531246809753124680"
00402132  |.  56            PUSH ESI                                    ;  乘法结果
00402133  |.  E8 881C0000   CALL 8.00403DC0
00402138  |.  83C4 10       ADD ESP,0x10
0040213B  |.  B9 90644000   MOV ECX,8.00406490   ;  ASCII "13095069099216326605010245808779535277211541324456558063162414338128147458401"

0012FBDC   00406064  ASCII "9753124680975312468097531246809753124680"
0012FBE0   0099B707  8.0099B707
0012FBE4   0099B708  ASCII "100000000000000000000000000000000000000000000000000000000000000000000000000000"

signed int __cdecl sub_402090(int a1)
{
  unsigned __int64 v1; // rax@1
  unsigned __int64 v2; // kr00_8@1
  signed int v3; // eax@1
  char v4; // dl@2
  const char *v5; // esi@3
  unsigned __int64 v7; // ST20_8@6

  v1 = __rdtsc();
  v2 = ((unsigned __int64)HIDWORD(v1) << 32) + (unsigned int)v1;
  v3 = 0;
  do
  {
    v4 = byte_405144[v3] ^ *(_BYTE *)(a1 + v3 + 22);
    v3 += 3;
    byte_99B705[v3] = v4;
    byte_99B706[v3] = *((_BYTE *)&ExceptionInfo.ContextRecord + v3 + 2) ^ *(_BYTE *)(a1 + v3 + 20);
    byte_99B707[v3] = *((_BYTE *)&ExceptionInfo.ContextRecord + v3 + 3) ^ *(_BYTE *)(a1 + v3 + 21);
  }
  while ( v3 < 39 );
  v5 = (const char *)sub_403EA0(&unk_99B708, &unk_99B708);
  sub_403DC0(v5, a97531246809753);
  if ( strcmp(v5, a13095069099216) )
  {
    sub_404032(v5);
    return 0;
  }
  sub_404032(v5);
  v7 = __rdtsc();
  if ( (unsigned int)v7 + ((unsigned __int64)HIDWORD(v7) << 32) - v2 >= 0x14B230CE38i64 )
    return 0;
  return 1;
}

//也就是作者希望我们能够求解这个大数的开根号结果
//13095069099216326605010245808779535277211541324456558063162414338128147458401^0.5 =
//114433688655117320765854989491151409201
//算出密文23-61字节:(21、22、62、63字节密文已经在上文推理出)
//PSWPVUQPQ\^Y\_XCCBDB@NBL@BXVZUTSV\YSY\\
//穷举注册码第29-84位穷举:(已剔除特殊符号)

第 8 组注册码: LVBT
第 9 组注册码: V1BW
第 10 组注册码: VVFQ
第 11 组注册码: UVxe
第 12 组注册码: WVxf
第 13 组注册码: WEND
第 14 组注册码: QkRC
第 15 组注册码: QE5C
第 16 组注册码: TEBC
第 17 组注册码: WFZa
第 18 组注册码: VVRT
第 19 组注册码: VlxZ
第 20 组注册码: U1lc
第 21 组注册码: XC0t

//即注册码前84位:UFdVXVRTVVFYWltdXV9XQkFDQEUtLVBTV1BWVVFQUVxeWVxfWENDQkRCQE5CTEBCWFZaVVRTVlxZU1lcXC0t


六、算法流程三(本题最难的部分)


004025DC   > \8BC0          MOV EAX,EAX                                 ;  线程1修改完后,此处重新下断点
004025DE   .  8BFF          MOV EDI,EDI
004025E0   .  8BDB          MOV EBX,EBX
004025E2   .  8D8D F0FEFFFF LEA ECX,DWORD PTR SS:[EBP-0x110]            ;  取回密文地址
004025E8   .  51            PUSH ECX
004025E9   .  E8 D2F8FFFF   CALL 8.00401EC0                             ;  子算法流程跟进,大数乘法推理出密文1前20字节
004025EE   .  83C4 04       ADD ESP,0x4                                 ;  推理结果:密文1前20字节“PWU]TSUQXZ[]]_WBAC@E”
004025F1   .  85C0          TEST EAX,EAX                                ;  穷举注册码前28位:UFdVXVRTVVFYWltdXV9XQkFDQEUt
004025F3   .  75 07         JNZ X8.004025FC                             ;  必须跳
004025F5   .  33C0          XOR EAX,EAX
004025F7   .  E9 F0000000   JMP 8.004026EC
004025FC   >  C705 ECB69900>MOV DWORD PTR DS:[0x99B6EC],0x1             ;  全局变量置1,线程1销毁上述算法代码
00402606   >  A1 ECB69900   MOV EAX,DWORD PTR DS:[0x99B6EC]
0040260B   .  83F8 00       CMP EAX,0x0
0040260E   .  74 02         JE X8.00402612
00402610   .^ EB F4         JMP X8.00402606
00402612   >  E8 D9010000   CALL <8.checkself>                          ;  待线程1销毁代码后,在此处下断
00402617   .  0FB6D0        MOVZX EDX,AL
0040261A   .  85D2          TEST EDX,EDX
0040261C   .  75 08         JNZ X8.00402626
0040261E   .  6A 01         PUSH 0x1                                    ; /ExitCode = 0x1
00402620   .  FF15 04504000 CALL DWORD PTR DS:[<&KERNEL32.ExitProcess>] ; \ExitProcess
00402626   >  C705 ECB69900>MOV DWORD PTR DS:[0x99B6EC],0x2             ;  全局变量写2,跟进线程402970
00402630   >  A1 ECB69900   MOV EAX,DWORD PTR DS:[0x99B6EC]
00402635   .  83F8 00       CMP EAX,0x0
00402638   .  74 02         JE X8.0040263C
0040263A   .^ EB F4         JMP X8.00402630
0040263C   >  68 EA264000   PUSH 8.004026EA                             ;  待线程2运行完,在此断点就能断下
00402641   .  C3            RETN                                        ;  RET 用作跳转到 004026EA
00402642   .  8D85 F0FEFFFF LEA EAX,DWORD PTR SS:[EBP-0x110]            ;  密文地址
00402648   .  50            PUSH EAX
00402649   .  E8 42FAFFFF   CALL 8.00402090                             ;  子算法程序2 要求对一个大数开方
0040264E   .  83C4 04       ADD ESP,0x4                                 ;  算出密文22-63字节:PSWPVUQPQ\^Y\_XCCBDB@NBL@BXVZUTSV\YSY\\
00402651   .  85C0          TEST EAX,EAX
00402653   .  75 07         JNZ X8.0040265C
00402655   .  33C0          XOR EAX,EAX
00402657   .  E9 90000000   JMP 8.004026EC
0040265C   >  C705 ECB69900>MOV DWORD PTR DS:[0x99B6EC],0x2             ;  全局变量2,回到线程2下断
00402666   >  A1 ECB69900   MOV EAX,DWORD PTR DS:[0x99B6EC]
0040266B   .  83F8 00       CMP EAX,0x0
0040266E   .  74 02         JE X8.00402672
00402670   .^ EB F4         JMP X8.00402666
00402672   >  E8 79010000   CALL <8.checkself>
00402677   .  0FB6C8        MOVZX ECX,AL
0040267A   .  85C9          TEST ECX,ECX
0040267C   .  75 08         JNZ X8.00402686
0040267E   .  6A 01         PUSH 0x1                                    ; /ExitCode = 0x1
00402680   .  FF15 04504000 CALL DWORD PTR DS:[<&KERNEL32.ExitProcess>] ; \ExitProcess
00402686   >  C705 ECB69900>MOV DWORD PTR DS:[0x99B6EC],0x3             ;  全局变量3,跟踪线程3,402A90
00402690   >  A1 ECB69900   MOV EAX,DWORD PTR DS:[0x99B6EC]
00402695   .  83F8 00       CMP EAX,0x0
00402698   .  74 02         JE X8.0040269C
0040269A   .^ EB F4         JMP X8.00402690
0040269C   >  8BFF          MOV EDI,EDI                                 ;  线程3结束时,此处也就可以断下
0040269E   .  8BC0          MOV EAX,EAX
004026A0   .  8BDB          MOV EBX,EBX
004026A2   .  8D95 F0FEFFFF LEA EDX,DWORD PTR SS:[EBP-0x110]            ;  密文地址
004026A8   .  52            PUSH EDX
004026A9   .  E8 22FBFFFF   CALL 8.004021D0                             ;  子算法流程3,跟进

//断4022C5

    v7 = *(&v26 + v6);                          // 取转换后的密文
    if ( v7 < 0 || v7 > 9 )                     // 如果<0 或 >9 则
      v8 = v7 + 0x37;                           // hash+0x37
    else
      v8 = v7 + 0x30;                           // 否则 hash+0x30
    *(&v26 + v6) = v8;                          // 更新
    v9 = *(&v27 + v6);
    if ( v9 < 0 || v9 > 9 )                     // 以下同理,都只取末尾,因此还要 &0xFF

0012FBCC  31 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30  1000000000000000
0012FBDC  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30  0000000000000000
0012FBEC  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30  0000000000000000
0012FBFC  30 30 30 30 30 30                                000000

100000000000000000000000000000000000000000000000000000 --> 转16进制
10B46C6CDD6E3E0828F4DB456FF0C8EA0000000000000

15691529100101820131 --> 转十进制
101108129035547400339761

114433688655117320765854989491151409201 --> 转十进制
6160860754500767776635611375064997739043525121
004021D0  /$  55            PUSH EBP
004021D1  |.  8BEC          MOV EBP,ESP
004021D3  |.  83E4 F8       AND ESP,0xFFFFFFF8
004021D6  |.  81EC F4020000 SUB ESP,0x2F4
004021DC  |.  A1 00604000   MOV EAX,DWORD PTR DS:[0x406000]
004021E1  |.  33C4          XOR EAX,ESP
004021E3  |.  898424 F00200>MOV DWORD PTR SS:[ESP+0x2F0],EAX
004021EA  |.  53            PUSH EBX
004021EB  |.  56            PUSH ESI
004021EC  |.  57            PUSH EDI
004021ED  |.  8BC0          MOV EAX,EAX
004021EF  |.  8BDB          MOV EBX,EBX
004021F1  |.  8BC9          MOV ECX,ECX
004021F3  |.  8BD2          MOV EDX,EDX
004021F5  |.  8BC0          MOV EAX,EAX
004021F7  |.  8BDB          MOV EBX,EBX
004021F9  |.  8BC9          MOV ECX,ECX
004021FB  |.  8BD2          MOV EDX,EDX
004021FD  |.  8BC0          MOV EAX,EAX
004021FF  |.  8BDB          MOV EBX,EBX
00402201  |.  8BC9          MOV ECX,ECX
00402203  |.  8BD2          MOV EDX,EDX
00402205  |.  0F31          RDTSC
00402207  |.  895424 10     MOV DWORD PTR SS:[ESP+0x10],EDX
0040220B  |.  894424 14     MOV DWORD PTR SS:[ESP+0x14],EAX
0040220F  |.  8B4424 10     MOV EAX,DWORD PTR SS:[ESP+0x10]
00402213  |.  6A 01         PUSH 0x1
00402215  |.  6A 00         PUSH 0x0
00402217  |.  6A 00         PUSH 0x0
00402219  |.  50            PUSH EAX
0040221A  |.  E8 51250000   CALL 8.00404770
0040221F  |.  8B4C24 14     MOV ECX,DWORD PTR SS:[ESP+0x14]
00402223  |.  33F6          XOR ESI,ESI
00402225  |.  03C1          ADD EAX,ECX
00402227  |.  13D6          ADC EDX,ESI
00402229  |.  894424 18     MOV DWORD PTR SS:[ESP+0x18],EAX
0040222D  |.  8D8424 180200>LEA EAX,DWORD PTR SS:[ESP+0x218]
00402234  |.  895424 1C     MOV DWORD PTR SS:[ESP+0x1C],EDX
00402238  |.  E8 83EEFFFF   CALL 8.004010C0
0040223D  |.  6A 37         PUSH 0x37                                ; /n = 37 (55.)
0040223F  |.  8D9424 C90200>LEA EDX,DWORD PTR SS:[ESP+0x2C9]         ; |
00402246  |.  56            PUSH ESI                                 ; |c
00402247  |.  52            PUSH EDX                                 ; |s
00402248  |.  C68424 D00200>MOV BYTE PTR SS:[ESP+0x2D0],0x0          ; |
00402250  |.  E8 0B250000   CALL <JMP.&MSVCR80.memset>               ; \55字节内存
00402255  |.  8B7D 08       MOV EDI,DWORD PTR SS:[EBP+0x8]           ;  取密文地址
00402258  |.  83C4 0C       ADD ESP,0xC
0040225B  |.  83C7 3F       ADD EDI,0x3F
0040225E  |.  8D8C24 C50200>LEA ECX,DWORD PTR SS:[ESP+0x2C5]
00402265  |.  BB 1B000000   MOV EBX,0x1B                             ;  循环27次,生成54字节
0040226A  |.  8D9B 00000000 LEA EBX,DWORD PTR DS:[EBX]
00402270  |>  0FBE37        /MOVSX ESI,BYTE PTR DS:[EDI]             ;  从第64字节开始取密文转为16进制,拆分
00402273  |.  8BC6          |MOV EAX,ESI
00402275  |.  99            |CDQ
00402276  |.  83E2 0F       |AND EDX,0xF
00402279  |.  03C2          |ADD EAX,EDX
0040227B  |.  C1F8 04       |SAR EAX,0x4                             ;  /16
0040227E  |.  8841 FF       |MOV BYTE PTR DS:[ECX-0x1],AL            ;  商保存
00402281  |.  8BC6          |MOV EAX,ESI
00402283  |.  25 0F000080   |AND EAX,0x8000000F
00402288  |.  79 05         |JNS X8.0040228F
0040228A  |.  48            |DEC EAX
0040228B  |.  83C8 F0       |OR EAX,0xFFFFFFF0
0040228E  |.  40            |INC EAX
0040228F  |>  8801          |MOV BYTE PTR DS:[ECX],AL                ;  余数保存
00402291  |.  83C7 01       |ADD EDI,0x1
00402294  |.  83C1 02       |ADD ECX,0x2
00402297  |.  83EB 01       |SUB EBX,0x1
0040229A  |.^ 75 D4         \JNZ X8.00402270
0040229C  |.  33C9          XOR ECX,ECX
0040229E  |.  8BFF          MOV EDI,EDI
004022A0  |>  8A840C C40200>/MOV AL,BYTE PTR SS:[ESP+ECX+0x2C4]
004022A7  |.  84C0          |TEST AL,AL
004022A9  |.  7C 08         |JL X8.004022B3                          ;  < 0
004022AB  |.  3C 09         |CMP AL,0x9
004022AD  |.  7F 04         |JG X8.004022B3                          ;  > 9
004022AF  |.  04 30         |ADD AL,0x30                             ;  +0x30
004022B1  |.  EB 02         |JMP X8.004022B5
004022B3  |>  04 37         |ADD AL,0x37                             ;  +0x37
004022B5  |>  88840C C40200>|MOV BYTE PTR SS:[ESP+ECX+0x2C4],AL      ;  结果存回地址
004022BC  |.  8A840C C50200>|MOV AL,BYTE PTR SS:[ESP+ECX+0x2C5]      ;  取下1个字节密文
004022C3  |.  84C0          |TEST AL,AL
004022C5  |.  7C 08         |JL X8.004022CF
004022C7  |.  3C 09         |CMP AL,0x9
004022C9  |.  7F 04         |JG X8.004022CF
004022CB  |.  04 30         |ADD AL,0x30
004022CD  |.  EB 02         |JMP X8.004022D1
004022CF  |>  04 37         |ADD AL,0x37
004022D1  |>  88840C C50200>|MOV BYTE PTR SS:[ESP+ECX+0x2C5],AL      ;  结果存回地址
004022D8  |.  8A840C C60200>|MOV AL,BYTE PTR SS:[ESP+ECX+0x2C6]      ;  取下1个字节密文
004022DF  |.  84C0          |TEST AL,AL
004022E1  |.  7C 08         |JL X8.004022EB
004022E3  |.  3C 09         |CMP AL,0x9
004022E5  |.  7F 04         |JG X8.004022EB
004022E7  |.  04 30         |ADD AL,0x30
004022E9  |.  EB 02         |JMP X8.004022ED
004022EB  |>  04 37         |ADD AL,0x37
004022ED  |>  88840C C60200>|MOV BYTE PTR SS:[ESP+ECX+0x2C6],AL
004022F4  |.  8A840C C70200>|MOV AL,BYTE PTR SS:[ESP+ECX+0x2C7]      ;  取下1个字节密文
004022FB  |.  84C0          |TEST AL,AL
004022FD  |.  7C 08         |JL X8.00402307
004022FF  |.  3C 09         |CMP AL,0x9
00402301  |.  7F 04         |JG X8.00402307
00402303  |.  04 30         |ADD AL,0x30
00402305  |.  EB 02         |JMP X8.00402309
00402307  |>  04 37         |ADD AL,0x37
00402309  |>  88840C C70200>|MOV BYTE PTR SS:[ESP+ECX+0x2C7],AL      ;  结果存回地址
00402310  |.  8A840C C80200>|MOV AL,BYTE PTR SS:[ESP+ECX+0x2C8]      ;  取下1个字节密文
00402317  |.  84C0          |TEST AL,AL
00402319  |.  7C 08         |JL X8.00402323
0040231B  |.  3C 09         |CMP AL,0x9
0040231D  |.  7F 04         |JG X8.00402323
0040231F  |.  04 30         |ADD AL,0x30
00402321  |.  EB 02         |JMP X8.00402325
00402323  |>  04 37         |ADD AL,0x37
00402325  |>  88840C C80200>|MOV BYTE PTR SS:[ESP+ECX+0x2C8],AL      ;  结果存回地址
0040232C  |.  8A840C C90200>|MOV AL,BYTE PTR SS:[ESP+ECX+0x2C9]      ;  取下1个字节密文
00402333  |.  84C0          |TEST AL,AL
00402335  |.  7C 08         |JL X8.0040233F
00402337  |.  3C 09         |CMP AL,0x9
00402339  |.  7F 04         |JG X8.0040233F
0040233B  |.  04 30         |ADD AL,0x30
0040233D  |.  EB 02         |JMP X8.00402341
0040233F  |>  04 37         |ADD AL,0x37
00402341  |>  88840C C90200>|MOV BYTE PTR SS:[ESP+ECX+0x2C9],AL      ;  结果存回地址
00402348  |.  83C1 06       |ADD ECX,0x6                             ;  步长6
0040234B  |.  83F9 36       |CMP ECX,0x36
0040234E  |.^ 0F8C 4CFFFFFF \JL 8.004022A0                           ;  处理54字节
00402354  |.  6A 10         PUSH 0x10                                ;  0x10
00402356  |.  8D8C24 C80200>LEA ECX,DWORD PTR SS:[ESP+0x2C8]         ;  密文转换后的内容
0040235D  |.  51            PUSH ECX
0040235E  |.  8D8424 200200>LEA EAX,DWORD PTR SS:[ESP+0x220]
00402365  |.  E8 E6F8FFFF   CALL 8.00401C50                          ;  将字符串转十六进制,注意存放内存顺序
0040236A  |.  8D8424 C80000>LEA EAX,DWORD PTR SS:[ESP+0xC8]
00402371  |.  E8 4AEDFFFF   CALL 8.004010C0
00402376  |.  6A 0A         PUSH 0xA
00402378  |.  68 F0B69900   PUSH 8.0099B6F0                          ;  ASCII "15691529100101820131"
0040237D  |.  E8 CEF8FFFF   CALL 8.00401C50                          ;  将字符串转十进制
00402382  |.  8D8424 700100>LEA EAX,DWORD PTR SS:[ESP+0x170]
00402389  |.  E8 32EDFFFF   CALL 8.004010C0
0040238E  |.  6A 0A         PUSH 0xA
00402390  |.  68 08B79900   PUSH 8.0099B708                          ;  ASCII "114433688655117320765854989491151409201"
00402395  |.  E8 B6F8FFFF   CALL 8.00401C50                          ;  将字符串转十进制
0040239A  |.  8D9424 700100>LEA EDX,DWORD PTR SS:[ESP+0x170]
004023A1  |.  52            PUSH EDX                                 ;  56172073862a662a8d6bb1a135999031
004023A2  |.  8D4424 24     LEA EAX,DWORD PTR SS:[ESP+0x24]
004023A6  |.  50            PUSH EAX
004023A7  |.  8D9424 D00000>LEA EDX,DWORD PTR SS:[ESP+0xD0]          ;  d9c382944a461ee3
004023AE  |.  8D8424 200200>LEA EAX,DWORD PTR SS:[ESP+0x220]         ;  123456789abcdef123456789abcdef123456789abcdef123456789
004023B5  |.  E8 D6F6FFFF   CALL 8.00401A90                          ;  最后一个子程序算法
004023BA  |.  33C0          XOR EAX,EAX
004023BC  |.  837C24 24 04  CMP DWORD PTR SS:[ESP+0x24],0x4
004023C1  |.  75 69         JNZ X8.0040242C
004023C3  |>  8B4C04 28     /MOV ECX,DWORD PTR SS:[ESP+EAX+0x28]
004023C7  |.  3B88 E0644000 |CMP ECX,DWORD PTR DS:[EAX+0x4064E0]
004023CD  |.  75 5B         |JNZ X8.0040242A
004023CF  |.  83C0 04       |ADD EAX,0x4
004023D2  |.  83F8 10       |CMP EAX,0x10                            ;  比较4次,每次4字节
004023D5  |.^ 7C EC         \JL X8.004023C3
004023D7  |.  0F31          RDTSC

//中间有些格式转换

按十六进制拆分剩余密文,字节数*2

    v7 = *(&v26 + v6);                          // 取转换后的密文
    if ( v7 < 0 || v7 > 9 )                     // 如果<0 或 >9 则
      v8 = v7 + 0x37;                           // hash+0x37
    else
      v8 = v7 + 0x30;                           // 否则 hash+0x30
    *(&v26 + v6) = v8;                          // 更新
    v9 = *(&v27 + v6);
    if ( v9 < 0 || v9 > 9 )                     // 以下同理,都只取末尾,因此还要 &0xFF

//401C50 对加密后的HASH进行格式处理
 // 如果 HASH < 0x30 或者 > 0x39 (非数字)则
 //   再如果 HASH < 0x41 或者 > 0x46 (也非A-F)则
 //     再如果 HASH < 0x61 或者 > 0x66 (也非a-f)则
 //       置0
 //     否则
 //       HASH-0x57
 //   否则
 //     HASH-0x37
 // 否则
 //   HASH-0x30

// 并逐位联合,把所见字符 0-9 a-f A-F 当做十六进制数来看待,地址存放顺序注意了!

//最后CALL 401A90出来在4023C7处比较密文是否如下:

004064E0  63 1F 97 04 A7 49 1E 88 CC 4B 49 28 1C 34 E5 35  c?執KI(4?

//跟到如下关键算法

00401A96   .  53            PUSH EBX
00401A97   .  55            PUSH EBP
00401A98   .  8BAC24 080200>MOV EBP,DWORD PTR SS:[ESP+0x208]
00401A9F   .  56            PUSH ESI
00401AA0   .  8BF0          MOV ESI,EAX
00401AA2   .  57            PUSH EDI
00401AA3   .  8BC5          MOV EAX,EBP
00401AA5   .  E8 16F6FFFF   CALL 8.004010C0
00401AAA   .  8D4424 10     LEA EAX,DWORD PTR SS:[ESP+0x10]
00401AAE   .  E8 0DF6FFFF   CALL 8.004010C0
00401AB3   .  8D8424 B80000>LEA EAX,DWORD PTR SS:[ESP+0xB8]
00401ABA   .  E8 01F6FFFF   CALL 8.004010C0
00401ABF   .  B8 01000000   MOV EAX,0x1
00401AC4   .  8945 04       MOV DWORD PTR SS:[EBP+0x4],EAX
00401AC7   .  8945 08       MOV DWORD PTR SS:[EBP+0x8],EAX
00401ACA   .  33C0          XOR EAX,EAX
00401ACC   .  8D7D 0C       LEA EDI,DWORD PTR SS:[EBP+0xC]
00401ACF   .  B9 27000000   MOV ECX,0x27
00401AD4   .  F3:AB         REP STOS DWORD PTR ES:[EDI]
00401AD6   .  8B46 04       MOV EAX,DWORD PTR DS:[ESI+0x4]
00401AD9   .  83C6 08       ADD ESI,0x8
00401ADC   .  B9 28000000   MOV ECX,0x28                             ;  循环次数
00401AE1   .  8D7C24 18     LEA EDI,DWORD PTR SS:[ESP+0x18]
00401AE5   .  894424 14     MOV DWORD PTR SS:[ESP+0x14],EAX
00401AE9   .  F3:A5         REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>;  复制 hash_hex 到 12F740
00401AEB   .  8B4A 04       MOV ECX,DWORD PTR DS:[EDX+0x4]
00401AEE   .  898C24 BC0000>MOV DWORD PTR SS:[ESP+0xBC],ECX
00401AF5   .  8D72 08       LEA ESI,DWORD PTR DS:[EDX+0x8]
00401AF8   .  8DBC24 C00000>LEA EDI,DWORD PTR SS:[ESP+0xC0]
00401AFF   >  B9 28000000   MOV ECX,0x28
00401B04   .  F3:A5         REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>;  复制 a_int 到 12F7E8
00401B06   .  EB 08         JMP X8.00401B10
00401B08   .  8DA424 000000>LEA ESP,DWORD PTR SS:[ESP]
00401B0F   .  90            NOP
00401B10   >  83BC24 BC0000>CMP DWORD PTR SS:[ESP+0xBC],0x1
00401B18   .  8B8424 C00000>MOV EAX,DWORD PTR SS:[ESP+0xC0]          ;  读取a_int
00401B1F   .  75 08         JNZ X8.00401B29
00401B21   .  85C0          TEST EAX,EAX
00401B23   .  0F84 15010000 JE 8.00401C3E
00401B29   >  A8 01         TEST AL,0x1
00401B2B   .  8D9C24 600100>LEA EBX,DWORD PTR SS:[ESP+0x160]
00401B32   .  8D9424 B80000>LEA EDX,DWORD PTR SS:[ESP+0xB8]
00401B39   .  0F84 89000000 JE 8.00401BC8
00401B3F   .  E8 9CF9FFFF   CALL 8.004014E0                          ;  一些复制拷贝,a_int -1
00401B44   .  8B50 04       MOV EDX,DWORD PTR DS:[EAX+0x4]
00401B47   .  8D70 08       LEA ESI,DWORD PTR DS:[EAX+0x8]
00401B4A   .  899424 BC0000>MOV DWORD PTR SS:[ESP+0xBC],EDX
00401B51   .  B9 28000000   MOV ECX,0x28
00401B56   .  8DBC24 C00000>LEA EDI,DWORD PTR SS:[ESP+0xC0]
00401B5D   .  8D4424 10     LEA EAX,DWORD PTR SS:[ESP+0x10]
00401B61   .  F3:A5         REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>;  更新
00401B63   .  50            PUSH EAX                                 ;  hash_int
00401B64   .  8D8C24 640100>LEA ECX,DWORD PTR SS:[ESP+0x164]
00401B6B   .  51            PUSH ECX                                 ;  a_int
00401B6C   .  55            PUSH EBP
00401B6D   .  E8 1EFAFFFF   CALL <8.big_mul>                         ;  大数乘法
00401B72   .  8B50 04       MOV EDX,DWORD PTR DS:[EAX+0x4]
00401B75   .  8955 04       MOV DWORD PTR SS:[EBP+0x4],EDX
00401B78   .  8D4D 08       LEA ECX,DWORD PTR SS:[EBP+0x8]
00401B7B   .  2BC5          SUB EAX,EBP
00401B7D   .  BA 28000000   MOV EDX,0x28
00401B82   >  8B3408        MOV ESI,DWORD PTR DS:[EAX+ECX]
00401B85   .  8931          MOV DWORD PTR DS:[ECX],ESI
00401B87   .  83C1 04       ADD ECX,0x4
00401B8A   .  83EA 01       SUB EDX,0x1
00401B8D   .^ 75 F3         JNZ X8.00401B82
00401B8F   .  8B8424 140200>MOV EAX,DWORD PTR SS:[ESP+0x214]
00401B96   .  50            PUSH EAX                                 ;  int_b
00401B97   .  8D8C24 640100>LEA ECX,DWORD PTR SS:[ESP+0x164]
00401B9E   .  51            PUSH ECX                                 ;  上一轮计算的结果
00401B9F   .  8BD5          MOV EDX,EBP
00401BA1   .  E8 AAFCFFFF   CALL 8.00401850                          ;  巨复杂大数算法,应该是自定义求余数
00401BA6   .  8B50 04       MOV EDX,DWORD PTR DS:[EAX+0x4]
00401BA9   .  8955 04       MOV DWORD PTR SS:[EBP+0x4],EDX
00401BAC   .  8D4D 08       LEA ECX,DWORD PTR SS:[EBP+0x8]           ;  hash_hex
00401BAF   .  2BC5          SUB EAX,EBP
00401BB1   .  BA 28000000   MOV EDX,0x28
00401BB6   >  8B3408        MOV ESI,DWORD PTR DS:[EAX+ECX]
00401BB9   .  8931          MOV DWORD PTR DS:[ECX],ESI
00401BBB   .  83C1 04       ADD ECX,0x4
00401BBE   .  83EA 01       SUB EDX,0x1
00401BC1   .^ 75 F3         JNZ X8.00401BB6
00401BC3   .^ E9 48FFFFFF   JMP 8.00401B10
00401BC8   >  E8 E3FBFFFF   CALL 8.004017B0                          ;  a_int 高位 / 2;(a_int 低位 -1) / 2
00401BCD   .  8B48 04       MOV ECX,DWORD PTR DS:[EAX+0x4]           ;  不深究,拿来用 a_int
00401BD0   .  898C24 BC0000>MOV DWORD PTR SS:[ESP+0xBC],ECX
00401BD7   .  8D5424 10     LEA EDX,DWORD PTR SS:[ESP+0x10]
00401BDB   .  8D70 08       LEA ESI,DWORD PTR DS:[EAX+0x8]
00401BDE   .  52            PUSH EDX
00401BDF   .  B9 28000000   MOV ECX,0x28
00401BE4   .  8DBC24 C40000>LEA EDI,DWORD PTR SS:[ESP+0xC4]
00401BEB   .  8D8424 640100>LEA EAX,DWORD PTR SS:[ESP+0x164]
00401BF2   .  F3:A5         REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>;  更新a_int
00401BF4   .  50            PUSH EAX
00401BF5   .  8BCA          MOV ECX,EDX
00401BF7   .  51            PUSH ECX
00401BF8   .  E8 93F9FFFF   CALL <8.big_mul>
00401BFD   .  8B50 04       MOV EDX,DWORD PTR DS:[EAX+0x4]
00401C00   .  8D70 08       LEA ESI,DWORD PTR DS:[EAX+0x8]
00401C03   .  8B8424 140200>MOV EAX,DWORD PTR SS:[ESP+0x214]
00401C0A   .  895424 14     MOV DWORD PTR SS:[ESP+0x14],EDX
00401C0E   .  B9 28000000   MOV ECX,0x28
00401C13   .  8D7C24 18     LEA EDI,DWORD PTR SS:[ESP+0x18]
00401C17   .  F3:A5         REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
00401C19   .  50            PUSH EAX
00401C1A   .  8D8C24 640100>LEA ECX,DWORD PTR SS:[ESP+0x164]
00401C21   .  51            PUSH ECX
00401C22   .  8D5424 18     LEA EDX,DWORD PTR SS:[ESP+0x18]          ;  拿上面的乘方结果除以b_int
00401C26   .  E8 25FCFFFF   CALL 8.00401850                          ;  巨复杂大数算法,应该是自定义求余
00401C2B   .  8B50 04       MOV EDX,DWORD PTR DS:[EAX+0x4]
00401C2E   .  895424 14     MOV DWORD PTR SS:[ESP+0x14],EDX
00401C32   .  8D70 08       LEA ESI,DWORD PTR DS:[EAX+0x8]
00401C35   .  8D7C24 18     LEA EDI,DWORD PTR SS:[ESP+0x18]
00401C39   .^ E9 C1FEFFFF   JMP 8.00401AFF
00401C3E   >  5F            POP EDI
00401C3F   .  5E            POP ESI
00401C40   .  8BC5          MOV EAX,EBP
00401C42   .  5D            POP EBP
00401C43   .  5B            POP EBX
00401C44   .  81C4 FC010000 ADD ESP,0x1FC
00401C4A   .  C2 0800       RETN 0x8
00401850  /$  81EC 5C010000 SUB ESP,0x15C
00401856  |.  53            PUSH EBX
00401857  |.  55            PUSH EBP
00401858  |.  8BAC24 680100>MOV EBP,DWORD PTR SS:[ESP+0x168]
0040185F  |.  56            PUSH ESI
00401860  |.  57            PUSH EDI
00401861  |.  8BC5          MOV EAX,EBP
00401863  |.  E8 58F8FFFF   CALL 8.004010C0
00401868  |.  8D4424 18     LEA EAX,DWORD PTR SS:[ESP+0x18]
0040186C  |.  E8 4FF8FFFF   CALL 8.004010C0
00401871  |.  8B42 04       MOV EAX,DWORD PTR DS:[EDX+0x4]
00401874  |.  8BCA          MOV ECX,EDX
00401876  |.  8945 04       MOV DWORD PTR SS:[EBP+0x4],EAX
00401879  |.  8D45 08       LEA EAX,DWORD PTR SS:[EBP+0x8]
0040187C  |.  2BCD          SUB ECX,EBP
0040187E  |.  BA 28000000   MOV EDX,0x28
00401883  |>  8B3401        /MOV ESI,DWORD PTR DS:[ECX+EAX]          ;  上一轮hash_hex*0x1的乘法结果
00401886  |.  8930          |MOV DWORD PTR DS:[EAX],ESI
00401888  |.  83C0 04       |ADD EAX,0x4
0040188B  |.  83EA 01       |SUB EDX,0x1
0040188E  |.^ 75 F3         \JNZ X8.00401883                         ;  先复制到12F890
00401890  |.  8BBC24 740100>MOV EDI,DWORD PTR SS:[ESP+0x174]
00401897  |.  8BC7          MOV EAX,EDI
00401899  |.  8BD5          MOV EDX,EBP
0040189B  |.  E8 D0F8FFFF   CALL 8.00401170                          ;  不重要
004018A0  |.  85C0          TEST EAX,EAX
004018A2  |.  0F8E 8A010000 JLE 8.00401A32
004018A8  |.  EB 06         JMP X8.004018B0
004018AA  |   8D9B 00000000 LEA EBX,DWORD PTR DS:[EBX]
004018B0  |>  8B75 04       /MOV ESI,DWORD PTR SS:[EBP+0x4]
004018B3  |.  8B4F 04       |MOV ECX,DWORD PTR DS:[EDI+0x4]
004018B6  |.  8B548F 04     |MOV EDX,DWORD PTR DS:[EDI+ECX*4+0x4]    ;  b_int 数值从高到低
004018BA  |.  8B44B5 04     |MOV EAX,DWORD PTR SS:[EBP+ESI*4+0x4]    ;  上轮计算结果 hash_hex 从数值高位往低位 / 第2轮从低到高
004018BE  |.  3BC2          |CMP EAX,EDX
004018C0  |.  895424 14     |MOV DWORD PTR SS:[ESP+0x14],EDX
004018C4  |.  76 13         |JBE X8.004018D9                         ;  比较被除数是否小于除数,如果小的话向后借位,否则就直接除
004018C6  |.  2BF1          |SUB ESI,ECX
004018C8  |.  8B4C8F 04     |MOV ECX,DWORD PTR DS:[EDI+ECX*4+0x4]    ;  b_int 数值从高到低
004018CC  |.  83C1 01       |ADD ECX,0x1                             ;  ecx+1
004018CF  |.  33D2          |XOR EDX,EDX
004018D1  |.  F7F1          |DIV ECX
004018D3  |.  8BDE          |MOV EBX,ESI
004018D5  |.  33D2          |XOR EDX,EDX
004018D7  |.  EB 46         |JMP X8.0040191F
004018D9  |>  3BF1          |CMP ESI,ECX
004018DB  |.  0F8E 23010000 |JLE 8.00401A04
004018E1  |.  6A 01         |PUSH 0x1                                ;  01
004018E3  |.  6A 00         |PUSH 0x0
004018E5  |.  8BDE          |MOV EBX,ESI
004018E7  |.  6A 00         |PUSH 0x0
004018E9  |.  2BD9          |SUB EBX,ECX
004018EB  |.  50            |PUSH EAX
004018EC  |.  83EB 01       |SUB EBX,0x1
004018EF  |.  E8 7C2E0000   |CALL <8.normal_mul>                     ;  乘法*1
004018F4  |.  8B4CB5 00     |MOV ECX,DWORD PTR SS:[EBP+ESI*4]        ;  上轮计算结果 hash_hex
004018F8  |.  33F6          |XOR ESI,ESI
004018FA  |.  03C1          |ADD EAX,ECX
004018FC  |.  8B4F 04       |MOV ECX,DWORD PTR DS:[EDI+0x4]
004018FF  |.  13D6          |ADC EDX,ESI
00401901  |.  837C8F 04 FF  |CMP DWORD PTR DS:[EDI+ECX*4+0x4],-0x1
00401906  |.  75 06         |JNZ X8.0040190E
00401908  |.  8BC2          |MOV EAX,EDX
0040190A  |.  33D2          |XOR EDX,EDX
0040190C  |.  EB 11         |JMP X8.0040191F
0040190E  |>  8B4C24 14     |MOV ECX,DWORD PTR SS:[ESP+0x14]         ;  b_int 数值由高到低
00401912  |.  6A 00         |PUSH 0x0
00401914  |.  83C1 01       |ADD ECX,0x1                             ;  b_int+0x1
00401917  |.  51            |PUSH ECX
00401918  |.  52            |PUSH EDX                                ;  除数
00401919  |.  50            |PUSH EAX                                ;  被除数
0040191A  |.  E8 412F0000   |CALL <8.normal_div>                     ;  跟进看看,可能是个除法
0040191F  |>  85D2          |TEST EDX,EDX                            ;  上次乘法结果hash_hex数值最高组(32bit) / (int_b+1)的商
00401921  |.  77 05         |JA X8.00401928
00401923  |.  83F8 FF       |CMP EAX,-0x1                            ;  上次乘法结果hash_hex数值最高组连次高组(即取64bit) /(int_b+1)的商
00401926  |.  76 0B         |JBE X8.00401933
00401928  |>  BE 02000000   |MOV ESI,0x2
0040192D  |.  895424 24     |MOV DWORD PTR SS:[ESP+0x24],EDX
00401931  |.  EB 05         |JMP X8.00401938
00401933  |>  BE 01000000   |MOV ESI,0x1
00401938  |>  8B9424 740100>|MOV EDX,DWORD PTR SS:[ESP+0x174]
0040193F  |.  894424 20     |MOV DWORD PTR SS:[ESP+0x20],EAX
00401943  |.  B9 28000000   |MOV ECX,0x28
00401948  |.  2BCE          |SUB ECX,ESI
0040194A  |.  33C0          |XOR EAX,EAX
0040194C  |.  897424 1C     |MOV DWORD PTR SS:[ESP+0x1C],ESI
00401950  |.  8D7CB4 20     |LEA EDI,DWORD PTR SS:[ESP+ESI*4+0x20]
00401954  |.  F3:AB         |REP STOS DWORD PTR ES:[EDI]
00401956  |.  52            |PUSH EDX                                ;  b_int 乘数
00401957  |.  8D8424 C40000>|LEA EAX,DWORD PTR SS:[ESP+0xC4]
0040195E  |.  50            |PUSH EAX                                ;  hash_hex
0040195F  |.  8D4C24 20     |LEA ECX,DWORD PTR SS:[ESP+0x20]
00401963  |.  51            |PUSH ECX                                ;  乘数,上个步骤除法的商
00401964  |.  E8 27FCFFFF   |CALL <8.big_mul>                        ;  用商乘回b_int
00401969  |.  8B50 04       |MOV EDX,DWORD PTR DS:[EAX+0x4]
0040196C  |.  8D70 08       |LEA ESI,DWORD PTR DS:[EAX+0x8]
0040196F  |.  895424 1C     |MOV DWORD PTR SS:[ESP+0x1C],EDX
00401973  |.  B9 28000000   |MOV ECX,0x28
00401978  |.  8D7C24 20     |LEA EDI,DWORD PTR SS:[ESP+0x20]
0040197C  |.  F3:A5         |REP MOVS DWORD PTR ES:[EDI],DWORD PTR D>
0040197E  |.  8B4424 1C     |MOV EAX,DWORD PTR SS:[ESP+0x1C]
00401982  |.  03C3          |ADD EAX,EBX
00401984  |.  894424 1C     |MOV DWORD PTR SS:[ESP+0x1C],EAX
00401988  |.  83C0 FF       |ADD EAX,-0x1
0040198B  |.  3BC3          |CMP EAX,EBX
0040198D  |.  7C 18         |JL X8.004019A7
0040198F  |.  8BC8          |MOV ECX,EAX
00401991  |.  2BCB          |SUB ECX,EBX
00401993  |.  8D4C8C 20     |LEA ECX,DWORD PTR SS:[ESP+ECX*4+0x20]
00401997  |>  8B11          |/MOV EDX,DWORD PTR DS:[ECX]
00401999  |.  895484 20     ||MOV DWORD PTR SS:[ESP+EAX*4+0x20],EDX
0040199D  |.  83E8 01       ||SUB EAX,0x1
004019A0  |.  83E9 04       ||SUB ECX,0x4
004019A3  |.  3BC3          ||CMP EAX,EBX
004019A5  |.^ 7D F0         |\JGE X8.00401997
004019A7  |>  85DB          |TEST EBX,EBX
004019A9  |.  7E 0A         |JLE X8.004019B5
004019AB  |.  8BCB          |MOV ECX,EBX
004019AD  |.  33C0          |XOR EAX,EAX
004019AF  |.  8D7C24 20     |LEA EDI,DWORD PTR SS:[ESP+0x20]
004019B3  |.  F3:AB         |REP STOS DWORD PTR ES:[EDI]
004019B5  |>  8D8424 C00000>|LEA EAX,DWORD PTR SS:[ESP+0xC0]         ;  减数
004019BC  |.  50            |PUSH EAX                                ;  回乘的结果压栈
004019BD  |.  8D4424 1C     |LEA EAX,DWORD PTR SS:[ESP+0x1C]
004019C1  |.  8BD5          |MOV EDX,EBP                             ;  被减数
004019C3  |.  E8 98F9FFFF   |CALL <8.big_sub>                        ;  大数减法,用hash_hex-回乘结果得到未除尽部分
004019C8  |.  8B48 04       |MOV ECX,DWORD PTR DS:[EAX+0x4]
004019CB  |.  894D 04       |MOV DWORD PTR SS:[EBP+0x4],ECX
004019CE  |.  8D4D 08       |LEA ECX,DWORD PTR SS:[EBP+0x8]          ;  hash_hex
004019D1  |.  2BC5          |SUB EAX,EBP
004019D3  |.  BA 28000000   |MOV EDX,0x28
004019D8  |>  8B3408        |/MOV ESI,DWORD PTR DS:[EAX+ECX]
004019DB  |.  8931          ||MOV DWORD PTR DS:[ECX],ESI             ;  减法结果更新到12F890
004019DD  |.  83C1 04       ||ADD ECX,0x4
004019E0  |.  83EA 01       ||SUB EDX,0x1
004019E3  |.^ 75 F3         |\JNZ X8.004019D8
004019E5  |.  8B8424 740100>|MOV EAX,DWORD PTR SS:[ESP+0x174]
004019EC  |.  8BD5          |MOV EDX,EBP
004019EE  |.  E8 7DF7FFFF   |CALL 8.00401170
004019F3  |.  85C0          |TEST EAX,EAX
004019F5  |.  8BBC24 740100>|MOV EDI,DWORD PTR SS:[ESP+0x174]
004019FC  |.^ 0F8F AEFEFFFF \JG 8.004018B0
00401A02  |.  EB 2E         JMP X8.00401A32
00401A04  |>  8D9424 C00000>LEA EDX,DWORD PTR SS:[ESP+0xC0]
00401A0B  |.  52            PUSH EDX
00401A0C  |.  8BC7          MOV EAX,EDI
00401A0E  |.  8BD5          MOV EDX,EBP
00401A10  |.  E8 4BF9FFFF   CALL <8.big_sub>
00401A15  |.  8B48 04       MOV ECX,DWORD PTR DS:[EAX+0x4]
00401A18  |.  894D 04       MOV DWORD PTR SS:[EBP+0x4],ECX
00401A1B  |.  8D4D 08       LEA ECX,DWORD PTR SS:[EBP+0x8]
00401A1E  |.  2BC5          SUB EAX,EBP
00401A20  |.  BA 28000000   MOV EDX,0x28
00401A25  |>  8B3408        /MOV ESI,DWORD PTR DS:[EAX+ECX]
00401A28  |.  8931          |MOV DWORD PTR DS:[ECX],ESI
00401A2A  |.  83C1 04       |ADD ECX,0x4
00401A2D  |.  83EA 01       |SUB EDX,0x1
00401A30  |.^ 75 F3         \JNZ X8.00401A25
00401A32  |>  8B45 04       MOV EAX,DWORD PTR SS:[EBP+0x4]
00401A35  |.  8B4F 04       MOV ECX,DWORD PTR DS:[EDI+0x4]
00401A38  |.  3BC1          CMP EAX,ECX
00401A3A  |.  7F 43         JG X8.00401A7F
00401A3C  |.  7C 41         JL X8.00401A7F
00401A3E  |.  8D48 FF       LEA ECX,DWORD PTR DS:[EAX-0x1]
00401A41  |.  85C9          TEST ECX,ECX
00401A43  |.  7C 20         JL X8.00401A65
00401A45  |.  8BDD          MOV EBX,EBP
00401A47  |.  8D448F 08     LEA EAX,DWORD PTR DS:[EDI+ECX*4+0x8]
00401A4B  |.  2BDF          SUB EBX,EDI
00401A4D  |.  8D49 00       LEA ECX,DWORD PTR DS:[ECX]
00401A50  |>  8B1403        /MOV EDX,DWORD PTR DS:[EBX+EAX]
00401A53  |.  8B30          |MOV ESI,DWORD PTR DS:[EAX]
00401A55  |.  3BD6          |CMP EDX,ESI
00401A57  |.  77 26         |JA X8.00401A7F
00401A59  |.  72 24         |JB X8.00401A7F
00401A5B  |.  83E9 01       |SUB ECX,0x1
00401A5E  |.  83E8 04       |SUB EAX,0x4
00401A61  |.  85C9          |TEST ECX,ECX
00401A63  |.^ 7D EB         \JGE X8.00401A50
00401A65  |>  8D7D 0C       LEA EDI,DWORD PTR SS:[EBP+0xC]
00401A68  |.  B9 27000000   MOV ECX,0x27
00401A6D  |.  33C0          XOR EAX,EAX
00401A6F  |.  C745 04 01000>MOV DWORD PTR SS:[EBP+0x4],0x1
00401A76  |.  C745 08 00000>MOV DWORD PTR SS:[EBP+0x8],0x0
00401A7D  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
00401A7F  |>  5F            POP EDI
00401A80  |.  5E            POP ESI
00401A81  |.  8BC5          MOV EAX,EBP
00401A83  |.  5D            POP EBP
00401A84  |.  5B            POP EBX
00401A85  |.  81C4 5C010000 ADD ESP,0x15C
00401A8B  \.  C2 0800       RETN 0x8

//原来作者利用大数运算,实现了一个RSA算法,其中包含了很多大数计算的技巧,比如除法取余数的除首法,RSA的指数二分法等等

//公钥:0xD9C382944A461EE3

//模数:0x56172073862A662A8D6BB1A135999031

//使用RSATOOL分解模数,并求出私钥:0x4A064A97921BDF9E3F354E9020AE054F

//你会发现输入的明文位数大于模数,求解这样的算法必须RSA使用私钥先解出最小合规原文:

//这里解出最小原文:0x2a1eb3c9579dfa307cf5b6c8730114db

//然后按模数的倍数+最小原文,罗列符合算法的明文,这个倍数不一定的,可大可小,平均几十万组里头就会有一组符合的明文

//暂不算上前面的符号byte转换出现的bug,倍数范围可以从0x0-0x2F93F3215105FF88115DE54,平均0x80000次就会出现一组

//因此光组合倍数就能出现无数种解,另外前文中的hash生成算法也存在多解(即最终参加RSA运算之前的转换过程)

//所以本题算法存在严重bug


七、python Keygen 编写


//python 按每4个明文字符组成片段穷举RSA倍数之后的数据,脑洞大开,我就创建了彩虹表进行检索,速度大大提高。

//这份彩虹表检索只匹中一组答案即返回,不再匹中多解的情况(可以有不同的4个明文字符组合,其转换的3个字节密文相同)

//另外,我不知不觉中就把作者全部算法都逆完了,连BASE64、RSA、二分法、符号数bug等都自己写了,你说悲剧不悲剧?

//你可以修改这句range范围,找出这个范围之内的所有符合的RSA明文解,但是我这里只显示答案,你可以改下源码就可以了


for m1 in range(0x0, 0x200000)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Ctf.pediy.com ctf2017 crackme 8 keygen
# python 3.6.0 32bit
# written by 爱琴海
# 2017/06/17

import time
import pickle
import os

class ExitFor1(Exception): pass
class ExitFor2(Exception): pass

def Main():

    All_key = ''

    sk = [0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46,
          0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,
          0x57,0x58,0x59,0x5a,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,
          0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a]

    #————————————————第一段注册码计算——————————————————

    a = 1549780652036258484424751705102781884386113
    b = 98765432109876543210123
    c = 15691529100101820131
    # print (b*c)
    d = '15691529100101820131'
    e = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'
    # 密文1前20字节推出
    f = Xor_str(d, e)
    # 加上已推出的21、22字节
    f = f + '--'
    # print (f)
    # 先穷举输入28位,每4位1组明文,7个循环
    # 该变量用来保存穷举到的字符串
    Sn_ming_1_28 = ''
    for n1 in range(0, 7):
        # 7个循环,3位1组密文1
        dest_str = f[3 * n1:3 * n1 + 3]
        # print (dest_str)
        for x1 in range(0x0, len(sk)):
            sn_x1 = sk[x1]
            for x2 in range(0x0, len(sk)):
                sn_x2 = sk[x2]
                if Hash_x1(sn_x1, sn_x2) == ord(dest_str[0]):
                    for x3 in range(0x0, len(sk)):
                        sn_x3 = sk[x3]
                        if Hash_x2(sn_x2, sn_x3) == ord(dest_str[1]):
                            for x4 in range(0x0, len(sk)):
                                sn_x4 = sk[x4]
                                if Hash_x3(sn_x3, sn_x4) == ord(dest_str[2]):
                                    Sn_ming_1_28 = chr(sn_x1) + chr(sn_x2) + chr(sn_x3) + chr(sn_x4)
                                    #print ('第 %d 组注册码:' % (n1+1),Sn_ming_1_28)
                                    All_key = All_key + Sn_ming_1_28

    # ————————————————第二段注册码计算——————————————————

    g = '114433688655117320765854989491151409201'
    # 密文23-63字节推出,但为了凑整3字节一组,需要往前面联接一些字符,应该从密文第22-63字节凑成14组
    f = Xor_str(g, e)
    f = '-' + f + '--'
    # print (f)
    # 穷举输入29-84位,每4位1组明文,14个循环
    # 该变量用来保存穷举到的字符串
    Sn_ming_29_84 = ''
    for n1 in range(0, 14):
        # 14个循环,3位1组密文1
        dest_str = f[3 * n1:3 * n1 + 3]
        # print (dest_str)
        for x1 in range(0x0, len(sk)):
            sn_x1 = sk[x1]
            for x2 in range(0x0, len(sk)):
                sn_x2 = sk[x2]
                # print (Hash_x1(sn_x1,sn_x2))
                # print (ord(dest_str[0]))
                if Hash_x1(sn_x1, sn_x2) == ord(dest_str[0]):
                    for x3 in range(0x0, len(sk)):
                        sn_x3 = sk[x3]
                        if Hash_x2(sn_x2, sn_x3) == ord(dest_str[1]):
                            for x4 in range(0x0, len(sk)):
                                sn_x4 = sk[x4]
                                if Hash_x3(sn_x3, sn_x4) == ord(dest_str[2]):
                                    Sn_ming_29_84 = chr(sn_x1) + chr(sn_x2) + chr(sn_x3) + chr(sn_x4)
                                    #print ('第 %d 组注册码:' % (n1+8),Sn_ming_29_84)
                                    All_key = All_key + Sn_ming_29_84

    # ————————————————第三段注册码计算——————————————————

    start_time = time.clock()
    Yu_shu = rsa_decrypt(0x35E5341C28494BCC881E49A704971F63)
    # RSA解密后的的余数(后续翻倍穷举用)
    # 0x2a1eb3c9579dfa307cf5b6c8730114db
    Cheng_shu = 0x56172073862A662A8D6BB1A135999031
    # 乘数
    # 9次循环
    # python 计算效率低,为解决片段穷举时间问题,运行初始建立彩虹表,直接检索,内存要大
    dict = {}
    if os.path.exists('cm8.pkl') == True:
        print('发现本地彩虹表,正在加载,请耐心等待......')
        Caihongbiao = open('cm8.pkl', 'rb')
        dict = pickle.load(Caihongbiao)
        Caihongbiao.close()
        print('彩虹表加载完成!')
    else:
        print('本地不存在彩虹表,重新生成,请耐心等待......')
        for x1 in range(0x0, len(sk)):
            sn_x1 = sk[x1]
            for x2 in range(0x0, len(sk)):
                sn_x2 = sk[x2]
                for x3 in range(0x0, len(sk)):
                    sn_x3 = sk[x3]
                    for x4 in range(0x0, len(sk)):
                        sn_x4 = sk[x4]
                        sn_a1 = Hash_x1(sn_x1, sn_x2)
                        sn_b1 = Hash_x2(sn_x2, sn_x3)
                        sn_c1 = Hash_x3(sn_x3, sn_x4)
                        if sn_a1 != 0x0 and sn_b1 != 0x0 and sn_c1 != 0x0:
                            # if sn_a1 < 0x80 and sn_b1 < 0x80 and sn_c1 < 0x80:
                            Hash_been43 = '%06x' % ((sn_a1 << 16) + (sn_b1 << 8) + sn_c1)
                            Key = ('%06x' % Hash_before_rsa1(Hash_been43))
                            Answer = chr(sn_x1) + chr(sn_x2) + chr(sn_x3) + chr(sn_x4)
                            dict[Key] = Answer
                            # 建立彩虹表
        # 彩虹表保存本地
        Caihongbiao = open('cm8.pkl', 'wb')
        pickle.dump(dict, Caihongbiao)
        Caihongbiao.close()
        print('建立彩虹表完成,用时: %.3f 秒' % (time.clock() - start_time))

    start_time = time.clock()

    for m1 in range(0x0, 0x200000):
    #for m1 in range(0xEEF9A874A25105A3CB530E, 0xEEF9A874A25105A3DB530E):
        # m1为倍数,RSA解密结果作余数,加上m1与模的乘积,逆算符合公式
        # 可以尝试改变m1的范围进行穷举,可以得到许许多多的答案,建议每次不要选取过大范围
        # 9个循环,3位1组密文1
        try:
            Hash_hex = Cheng_shu * m1 + Yu_shu
            Hash_hex_str = '%054x' % Hash_hex
            # Hash_hex_str = '506d00602503004d7656057a664674506d00602503004d7656057a'
            # Hash_hex_str = '506D00602503004D76560583F850B2F66F9589885B092130456132'
            Last_answer = ''
            #print('现在穷举: ',Hash_hex_str)
            for n2 in range(0, len(Hash_hex_str) // 6):
                dest_str = Hash_hex_str[6 * n2:6 * n2 + 6]
                # print (dest_str)
                # 进制和格式转换后的需要相等的9个目标分组(6位,看做3字节)
                try:
                    # print (Hash_been43)
                    # print('验证: %x' % (Hash_before_rsa1(Hash_been43)))
                    if dict.get(dest_str) == None:
                        # 没找到,需要检查是否这组无解
                        #print ('这组hash没有合规解,准备下一组hash......')
                        raise ExitFor2()
                    else:
                        Last_answer = Last_answer + dict[dest_str]
                        if n2 == len(Hash_hex_str) // 6 - 1:
                            All_key1 = All_key + Last_answer
                            print('可用注册码:', All_key1)
                        raise ExitFor1()
                except ExitFor1:
                    pass
        except ExitFor2:
            pass
    # ——————————————————————————————————————————
    dict.clear()
    # 回收内存
    print('穷举结束,第三阶段穷举用时: %.3f 秒' % (time.clock() - start_time))
    return

def Check_hex(hex1):
    if hex1 > 0x9:
        hex1 = (hex1 + 0x37) & 0xff
    else:
        hex1 = hex1 + 0x30
    return hex1

def Turn_hex(hash_ming_hex):
    # 拆分后的54字节
    # 自定义16进制转化,假定输入的都是偶数位数,这里不做过多检查
    if hash_ming_hex <= 0x39 and hash_ming_hex >= 0x30:
        hash_ming_hex = hash_ming_hex - 0x30
    elif hash_ming_hex <= 0x46 and hash_ming_hex >= 0x41:
        hash_ming_hex = hash_ming_hex - 0x37
    elif hash_ming_hex <= 0x66 and hash_ming_hex >= 0x61:
        hash_ming_hex = hash_ming_hex - 0x57
    else:
        hash_ming_hex = 0x0
    return hash_ming_hex

def Xor_str(xor1,xor2):
    #返回字符串异或,按较短字符串截取
    xor3 = ''
    n = len(xor1)
    if n > len(xor2): n = len(xor2)
    for i in range(0,n):
        xor3 += chr(ord(xor1[i]) ^ ord(xor2[i]))
    return xor3

def Check_str12(str_x):
    #对每组1、2位输入字符ASCII做检查和替换
    if str_x == 0x2B:
        str_temp = 0x3E
    elif str_x == 0x2F:
        str_temp = 0x3F
    elif str_x <= 0x39:
        str_temp = str_x + 0x4
    elif str_x == 0x3D:
        str_temp = 0x40
    elif str_x <= 0x5A:
        str_temp = str_x - 0x41
    elif str_x > 0x7A:
        str_temp = 0x40
    else:
        str_temp = str_x - 0x47
    return str_temp

def Check_str34(str_y):
    #对每组3、4位输入字符格式做检查和替换
    if str_y == 0x2B:
        str_temp = 0x3E
    elif str_y == 0x2F:
        str_temp = 0x3F
    elif str_y <= 0x39:
        str_temp = str_y + 0x4
    elif str_y == 0x3D:
        str_temp = 0x0
    elif str_y <= 0x5A:
        str_temp = str_y - 0x41
    elif str_y > 0x7A:
        str_temp = 0x40
    else:
        str_temp = str_y - 0x47
    return str_temp

def Hash_x1(x1,x2):
    #返回每组第1、2位明文计算的密文1
    x1_temp = Check_str12(x1)
    x2_temp = Check_str12(x2)
    return ((x1_temp << 2) + (x2_temp >> 4)) & 0xFF

def Hash_x2(x2,x3):
    #返回每组第2、3位明文计算的密文1
    x2_temp = Check_str12(x2)
    x3_temp = Check_str34(x3)
    if x3_temp == 0x0:
        return 0x0
    else:
        return ((x2_temp << 4) + (x3_temp >> 2)) & 0xFF

def Hash_x3(x3,x4):
    #返回每组第3、4位明文计算的密文1
    x3_temp = Check_str34(x3)
    x4_temp = Check_str34(x4)
    if x3_temp == 0x0 or x4_temp == 0x0:
        return 0x0
    else:
        return ((x3_temp << 6) + x4_temp) & 0xFF

#RSA加密算法,e为公钥,N为模数
def rsa_encrypt(original):
    e=0xD9C382944A461EE3
    N=0x56172073862A662A8D6BB1A135999031
    return quick_ming_mod(original,e,N)

#RSA解密算法,D为私钥,N为模数
def rsa_decrypt(encrypted):
    D=0x4A064A97921BDF9E3F354E9020AE054F
    N=0x56172073862A662A8D6BB1A135999031
    return quick_ming_mod(encrypted,D,N)

#二分法冥取模算法
def quick_ming_mod(di,ming,mode):
    temp=0x1
    di_1=di
    if ming>0x0 and di>0x0:
        while ming>0x0:
            if ming&0x1:
                temp=temp*di_1%mode
                ming=ming-1
            else:
                di_1=(di_1*di_1)%mode
                ming=ming>>0x1
    elif di>0x0:
        temp=0x1
    else:
        temp=0x0
    return temp

def Hash_before_rsa1(chai_fen_str):
#根据4/3算法27字节密文生成RSA计算前的16进制数
    hash_mi_hex = 0x0
    for n3 in range(0,len(chai_fen_str)//2):
    #27组
        b3 = int(chai_fen_str[n3*2:n3*2+2],0x10)
        #print ('chaifen %x' % b3)
        if b3 <= 0x7f:
            #正数
            c3 = b3 >> 0x4
            d3 = b3 % 0x10
        else:
            b3 = b3 + 0xffffff00
            c3 = ((b3 + 0xf) >> 0x4) & 0xff
            d3 = ((((b3 & 0x8000000f) - 0x1) | 0xfffffff0) + 0x1) & 0xff
        c3 = Turn_hex(Check_hex(c3))
        d3 = Turn_hex(Check_hex(d3))
        #print ('chai shang %x' % c3)
        #print ('chai yu    %x' % d3)
        if n3 == len(chai_fen_str)//2 - 1:
            hash_mi_hex = (((hash_mi_hex + c3) << 4) + d3)
        else:
            hash_mi_hex = (((hash_mi_hex + c3) << 4) +d3) << 4
    return hash_mi_hex

if __name__=="__main__":
    Main()

上传的附件:
最新回复 (12)
6
loudy 2017-6-18 18:53
2
真666
8
kanxue 2017-6-18 20:47
3
赞,文章写的很详细!
11
爱琴海 2017-6-18 20:52
4
kanxue 赞,文章写的很详细!
段老大您过奖了,高手懒得看,新手没耐心看,详细是我的毛病,呵呵
addictor 2017-6-18 21:16
5
文章写的很详细!学习了。谢谢。
小黑一名 2017-6-18 22:29
6
膜拜樓主,相當感謝分享!
伊邪那美 2017-6-18 22:58
7
感谢分享
windtrace 2017-6-19 08:31
8
我只能说:老鸟牛!
luobingguan 2017-6-19 10:15
9
kankana
luobingguan 2017-6-19 10:15
10
kankan
芥末口香糖 2017-6-19 11:03
11
666,很详细,那段跑的代码不算VM吧?感觉像是个虚表?
2
hyabcd 2017-6-19 12:21
12
大赞如此用心之作
5
poyoten 2017-6-19 12:50
13
太详细了。OD的RUN跟踪功能,从来没用过,新姿势get。
返回