010破解(三)之算法分析二
概述
010破解(二)之算法分析一
上一篇详细分析了第一种算法,也就是k[3]=0x9C系列的
之后分析了k[3]=0xFC系列后发现函数返回值最终并不能返回0x2D
因此这篇分析k[3]=0xAC系列的算法,部分地方需要结合上篇文章,在这不重复分析了
逐行分析代码
枯燥的旅程,耐心、耐心、再耐心
013BDCFC 80FB AC CMP BL,0xAC
013BDCFF 0F85 70010000 JNZ 010Edito.013BDE75
013BDD05 8A45 DD MOV AL,BYTE PTR SS:[EBP-0x23] ; k[1]
013BDD08 3245 E3 XOR AL,BYTE PTR SS:[EBP-0x1D] ; AL=k[0]^k[7]
013BDD0B 0FB6C8 MOVZX ECX,AL ; ecx=AL&0xFF
013BDD0E B8 00010000 MOV EAX,0x100
013BDD13 66:0FAFC8 IMUL CX,AX ; CX=(k[0]^k[7]&0xFF)*0x100
013BDD17 8A45 DE MOV AL,BYTE PTR SS:[EBP-0x22] ; AL=k[2]
013BDD1A 32C7 XOR AL,BH ; k[2]^k[5]
013BDD1C C747 1C 0200000>MOV DWORD PTR DS:[EDI+0x1C],0x2
013BDD23 0FB6C0 MOVZX EAX,AL ; AL=(k[2]^k[5])&0xFF
013BDD26 66:03C8 ADD CX,AX
013BDD29 0FB7C1 MOVZX EAX,CX ; CX=(k[0]^k[7]&0xFF)*0x100+(k[2]^k[5])&0xFF
013BDD2C 50 PUSH EAX
013BDD2D E8 96A604FF CALL 010Edito.004083C8
013BDD32 0FB7C0 MOVZX EAX,AX
013BDD35 83C4 04 ADD ESP,0x4
013BDD38 8947 20 MOV DWORD PTR DS:[EDI+0x20],EAX
013BDD3B 85C0 TEST EAX,EAX
013BDD3D 0F84 32010000 JE 010Edito.013BDE75
013BDD43 3D E8030000 CMP EAX,0x3E8
013BDD48 0F87 27010000 JA 010Edito.013BDE75
013BDD4E 0FB655 E5 MOVZX EDX,BYTE PTR SS:[EBP-0x1B] ; k[9]
013BDD52 0FB64D E0 MOVZX ECX,BYTE PTR SS:[EBP-0x20] ; k[4]
013BDD56 0FB6C7 MOVZX EAX,BH ; k[5]
013BDD59 33D0 XOR EDX,EAX ; EDX=k[9]^k[5]
013BDD5B 0FB645 E4 MOVZX EAX,BYTE PTR SS:[EBP-0x1C] ; eax=k[8]
013BDD5F 33C8 XOR ECX,EAX ; ecx=k[4]^k[5]
013BDD61 C1E2 08 SHL EDX,0x8 ; EDX=(k[9]^k[5])<<8
013BDD64 0FB645 E2 MOVZX EAX,BYTE PTR SS:[EBP-0x1E] ; eax=k[6]
013BDD68 03D1 ADD EDX,ECX ; EDX=(k[9]^k[5])<<8+k[4]^k[5]
013BDD6A 0FB64D DC MOVZX ECX,BYTE PTR SS:[EBP-0x24] ; ecx=k[0]
013BDD6E C1E2 08 SHL EDX,0x8 ; EDX=((k[9]^k[5])<<8+k[4]^k[5])<<8
013BDD71 33C8 XOR ECX,EAX ; ecx=k[0]^k[6]
013BDD73 03D1 ADD EDX,ECX ; EDX=((k[9]^k[5])<<8+k[4]^k[5])<<8+k[0]^k[6]
013BDD75 68 278C5B00 PUSH 010Edito.005B8C27 ; ASCII CC,"烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫"
013BDD7A 52 PUSH EDX
013BDD7B E8 0BCA04FF CALL 010Edito.0040A78B
013BDD80 83C4 08 ADD ESP,0x8
验证完用户名之后会有个判断k[3]==0xAC的比较,继续逐行分析,会发现函数最终返回值是0x2D
013BDE2B 80FB AC CMP BL,0xAC
013BDE2E 75 1A JNZ SHORT 010Edito.013BDE4A
013BDE30 8B45 F0 MOV EAX,DWORD PTR SS:[EBP-0x10]
013BDE33 85C0 TEST EAX,EAX
013BDE35 74 13 JE SHORT 010Edito.013BDE4A
013BDE37 3945 0C CMP DWORD PTR SS:[EBP+0xC],EAX
013BDE3A 76 07 JBE SHORT 010Edito.013BDE43
013BDE3C BE 4E000000 MOV ESI,0x4E
013BDE41 EB 0C JMP SHORT 010Edito.013BDE4F
013BDE43 BE 2D000000 MOV ESI,0x2D
013BDE48 EB 05 JMP SHORT 010Edito.013BDE4F
013BDE4A BE E7000000 MOV ESI,0xE7
013BDE4F 8D4D EC LEA ECX,DWORD PTR SS:[EBP-0x14]
013BDE52 C745 FC FFFFFFF>MOV DWORD PTR SS:[EBP-0x4],-0x1
013BDE59 FF15 7C24E702 CALL DWORD PTR DS:[<&Qt5Core.??1QByteArr>; Qt5Core.??1QByteArray@@QAE@XZ
013BDE5F 8BC6 MOV EAX,ESI
013BDE61 8B4D F4 MOV ECX,DWORD PTR SS:[EBP-0xC]
013BDE64 64:890D 0000000>MOV DWORD PTR FS:[0],ECX
算法到这就分析全部分析完了
算法总结
-
判断用户名/密码是否为空
-
将密码字符串转为16进制数据
-
验证密码
-
k[3]=0x9C 或 0xFC 或者 0xAC
-
sub_00407644函数返回值不能为0
即AL = (k0 ^ k6 ^ 0x18 + 0x3D) ^ 0xA7
AL!=0
-
sub_004083C8函数返回值不能为0 且 小于等于0x3e8
即esi=((K[2]k[5]&0xFF)+(K[1]k[7]&0xFF)*0x100)&0xFFFF
EAX=((esi0x7892+0x4D30)0x3421&0xFFFF)/0xB
if (dwEAX % 0xB == 0 && dwEAX/0xB <= 0x3e8)
-
-
将用户名转为ASCII字符串
-
调用sub_402E50函数计算用户名字符串加密值,参数是(用户名,1,0,sub_004083C8函数返回值)
用户名加密值与k4 k5 k6 k7有对应关系
K[4]=Ret&0xFF
k[5]=(Ret>>8)&0xFF
k[6]=(Ret>>0x10)%0xFF
k[7]=(Ret>>0x18)&0xFF -
判断参数
即sub_00407644函数返回值>=9
或者<=0x4389(根据算法选择不同的参数作比较)