【文章标题】: WinAudio Recorder破解手记
【文章作者】: 阿蔡
【软件名称】: WinAudio Recorder2.2.2
【下载地址】: 自行搜索
【编写语言】: Microsoft Visual C++ 7.0(PEID识别)
【使用工具】: od & ida & peid
【作者声明】: 第一次写技术文章,错误在所难免,敬请诸位大侠赐教!
第一次成功破解程序(简单的CrackMe不算程序吧,不过此程序也很简单),并写出注册机,兴奋不已,写下笔记与大家分享(文笔不好敬请原谅,排版也不好),错误之处欢迎大家指正.
我并没有尝试在网上搜索此软件的破解教程,不知道网上有没有,不过我的目的在于学习,所以这也就没关系了.
首先用PEID查壳,如图:
没有加壳,正好适合我等菜鸟.运行程序输入假注册码注册,结果如图:
有提示信息,记之.OD载入,F9运行.出来注册窗口,用Ultra String Reference插件搜索字符串信息,找到刚才提示的字符串,如图:
双击字符串来到下面的地方:
代码:
0040F19C . 6A 00 PUSH 0 0040F19E . 6A 00 PUSH 0 0040F1A0 . 68 D4E04300 PUSH Recorder.0043E0D4 ; please input correct registration code! 0040F1A5 . E8 6B160200 CALL Recorder.00430815 0040F1AA . 5F POP EDI 0040F1AB . 5E POP ESI 0040F1AC . 5D POP EBP
代码:
0040F16E . E8 D0B10100 CALL Recorder.0042A343 ; UpdateData 0040F173 . 8B46 70 MOV EAX, DWORD PTR DS:[ESI+70] ; 用户名 0040F176 . 8B68 F4 MOV EBP, DWORD PTR DS:[EAX-C] ; 用户名长度 0040F179 . 83FD 02 CMP EBP, 2 ; 长度是否大于2,不大于则提示信息,注册失败 0040F17C . 7D 15 JGE SHORT Recorder.0040F193 0040F17E . 6A 00 PUSH 0 0040F180 . 6A 00 PUSH 0 0040F182 . 68 FCE04300 PUSH Recorder.0043E0FC ; please input correct user name! 0040F187 . E8 89160200 CALL Recorder.00430815 0040F18C . 5F POP EDI 0040F18D . 5E POP ESI 0040F18E . 5D POP EBP 0040F18F . 83C4 0C ADD ESP, 0C 0040F192 . C3 RETN 0040F193 > 8B4E 74 MOV ECX, DWORD PTR DS:[ESI+74] ; KEY 0040F196 . 8379 F4 08 CMP DWORD PTR DS:[ECX-C], 8 ; KEY长度是否大于等于8 0040F19A . 7D 15 JGE SHORT Recorder.0040F1B1 ; 小于则提示信息,注册失败 0040F19C . 6A 00 PUSH 0 0040F19E . 6A 00 PUSH 0 0040F1A0 . 68 D4E04300 PUSH Recorder.0043E0D4 ; please input correct registration code! 0040F1A5 . E8 6B160200 CALL Recorder.00430815 0040F1AA . 5F POP EDI 0040F1AB . 5E POP ESI 0040F1AC . 5D POP EBP 0040F1AD . 83C4 0C ADD ESP, 0C 0040F1B0 . C3 RETN 0040F1B1 > 8B46 70 MOV EAX, DWORD PTR DS:[ESI+70] ; 用户名 0040F1B4 . 8B48 F4 MOV ECX, DWORD PTR DS:[EAX-C] ; 用户名长度 0040F1B7 85C9 TEST ECX, ECX 0040F1B9 . 7D 0A JGE SHORT Recorder.0040F1C5 ; 用户名长度大于0则跳 0040F1BB . 68 57000780 PUSH 80070057 0040F1C0 . E8 AB22FFFF CALL Recorder.00401470 0040F1C5 > 8A10 MOV DL, BYTE PTR DS:[EAX] ; 取第一位用户名 0040F1C7 . 8B46 70 MOV EAX, DWORD PTR DS:[ESI+70] 0040F1CA . 3978 F4 CMP DWORD PTR DS:[EAX-C], EDI 0040F1CD . 7D 0A JGE SHORT Recorder.0040F1D9 ; 用户名长度大于等于1则跳 0040F1CF . 68 57000780 PUSH 80070057 0040F1D4 . E8 9722FFFF CALL Recorder.00401470 0040F1D9 > 8A40 01 MOV AL, BYTE PTR DS:[EAX+1] ; 取第二位用户名 0040F1DC . 884424 0E MOV BYTE PTR SS:[ESP+E], AL ; 保存到局部变量 0040F1E0 8B46 70 MOV EAX, DWORD PTR DS:[ESI+70] ; 取用户名 0040F1E3 . 8B48 F4 MOV ECX, DWORD PTR DS:[EAX-C] ; 用户名长度 0040F1E6 . 85C9 TEST ECX, ECX 0040F1E8 . 7D 0A JGE SHORT Recorder.0040F1F4 ; 用户名长度大于等于0则跳 0040F1EA . 68 57000780 PUSH 80070057 0040F1EF . E8 7C22FFFF CALL Recorder.00401470 0040F1F4 > 8B4E 70 MOV ECX, DWORD PTR DS:[ESI+70] ; 取用户名 0040F1F7 . 53 PUSH EBX 0040F1F8 . 8A18 MOV BL, BYTE PTR DS:[EAX] ; 取第一位用户名 0040F1FA . 3979 F4 CMP DWORD PTR DS:[ECX-C], EDI ; 用户名长度是否大于0 0040F1FD . 7D 0A JGE SHORT Recorder.0040F209 0040F1FF . 68 57000780 PUSH 80070057 0040F204 . E8 6722FFFF CALL Recorder.00401470 0040F209 > 0FB6C2 MOVZX EAX, DL 0040F20C . 83C8 52 OR EAX, 52 ; EAX = EAX | 0x52 0040F20F . 99 CDQ 0040F210 . BF 0A000000 MOV EDI, 0A 0040F215 . F7FF IDIV EDI ; EAX = EAX / 10 0040F217 . 0FB64424 12 MOVZX EAX, BYTE PTR SS:[ESP+12] ; 取第二位用户名 0040F21C . 83C8 45 OR EAX, 45 ; EAX = EAX | 0x45 0040F21F . 885424 16 MOV BYTE PTR SS:[ESP+16], DL ; 保存余数 0040F223 . 99 CDQ 0040F224 . F7FF IDIV EDI 0040F226 . 0FB6C3 MOVZX EAX, BL 0040F229 . 83C8 43 OR EAX, 43 0040F22C . 885424 12 MOV BYTE PTR SS:[ESP+12], DL ; 保存余数 0040F230 . 99 CDQ 0040F231 . F7FF IDIV EDI 0040F233 . 0FB641 01 MOVZX EAX, BYTE PTR DS:[ECX+1] ; 取第二位用户名 0040F237 . 83C8 4F OR EAX, 4F 0040F23A . 8BCF MOV ECX, EDI 0040F23C . 885424 17 MOV BYTE PTR SS:[ESP+17], DL ; 保存余数 0040F240 . 99 CDQ 0040F241 . F7F9 IDIV ECX 0040F243 . 33C0 XOR EAX, EAX 0040F245 . 33C9 XOR ECX, ECX 0040F247 . 85ED TEST EBP, EBP ; 用户名长度 0040F249 . 885424 18 MOV BYTE PTR SS:[ESP+18], DL ; 保存余数 0040F24D . 7E 20 JLE SHORT Recorder.0040F26F ; 不大于则跳 0040F24F . 90 NOP 0040F250 > 85C9 TEST ECX, ECX 0040F252 . 0F8C D2000000 JL Recorder.0040F32A 0040F258 . 8B7E 70 MOV EDI, DWORD PTR DS:[ESI+70] ; 用户名 0040F25B . 3B4F F4 CMP ECX, DWORD PTR DS:[EDI-C] ; 用户名长度 0040F25E . 0F8F C6000000 JG Recorder.0040F32A 0040F264 . 0FB6140F MOVZX EDX, BYTE PTR DS:[EDI+ECX] ; 循环将相加每一位用户名的ASCII值相加,结果保存在EAX中 0040F268 . 03C2 ADD EAX, EDX 0040F26A . 41 INC ECX 0040F26B . 3BCD CMP ECX, EBP 0040F26D .^ 7C E1 JL SHORT Recorder.0040F250 ; 下一次循环 0040F26F > 8B4E 74 MOV ECX, DWORD PTR DS:[ESI+74] ; 取KEY 0040F272 . 8B51 F4 MOV EDX, DWORD PTR DS:[ECX-C] ; 取KEY长度 0040F275 . 85D2 TEST EDX, EDX 0040F277 . 7D 0A JGE SHORT Recorder.0040F283 ; 长度大于0则跳 0040F279 . 68 57000780 PUSH 80070057 0040F27E . E8 ED21FFFF CALL Recorder.00401470 0040F283 > 8A11 MOV DL, BYTE PTR DS:[ECX] ; 取第一位KEY 0040F285 . 8B4E 74 MOV ECX, DWORD PTR DS:[ESI+74] 0040F288 . 8379 F4 01 CMP DWORD PTR DS:[ECX-C], 1 ; KEY长度是否大于等于1 0040F28C . 885424 19 MOV BYTE PTR SS:[ESP+19], DL ; 保存到局部变量 0040F290 . 7D 0A JGE SHORT Recorder.0040F29C 0040F292 . 68 57000780 PUSH 80070057 0040F297 . E8 D421FFFF CALL Recorder.00401470 0040F29C > 8A49 01 MOV CL, BYTE PTR DS:[ECX+1] ; 取第2位KEY 0040F29F . 8B7E 74 MOV EDI, DWORD PTR DS:[ESI+74] 0040F2A2 . 884C24 13 MOV BYTE PTR SS:[ESP+13], CL 0040F2A6 . 837F F4 02 CMP DWORD PTR DS:[EDI-C], 2 ; KEY长度是否大于2 0040F2AA . 7D 0A JGE SHORT Recorder.0040F2B6 0040F2AC . 68 57000780 PUSH 80070057 0040F2B1 . E8 BA21FFFF CALL Recorder.00401470 0040F2B6 > 8A4F 02 MOV CL, BYTE PTR DS:[EDI+2] ; 取第3位KEY 0040F2B9 . 8B7E 74 MOV EDI, DWORD PTR DS:[ESI+74] 0040F2BC . 884C24 14 MOV BYTE PTR SS:[ESP+14], CL 0040F2C0 . 837F F4 03 CMP DWORD PTR DS:[EDI-C], 3 ; KEY长度是否大于3 0040F2C4 . 7D 0A JGE SHORT Recorder.0040F2D0 0040F2C6 . 68 57000780 PUSH 80070057 0040F2CB . E8 A021FFFF CALL Recorder.00401470 0040F2D0 > 8A4F 03 MOV CL, BYTE PTR DS:[EDI+3] ; 取第四位KEY 0040F2D3 . 8B7E 74 MOV EDI, DWORD PTR DS:[ESI+74] 0040F2D6 . 884C24 15 MOV BYTE PTR SS:[ESP+15], CL 0040F2DA . 837F F4 04 CMP DWORD PTR DS:[EDI-C], 4 0040F2DE . 7D 0A JGE SHORT Recorder.0040F2EA 0040F2E0 . 68 57000780 PUSH 80070057 0040F2E5 . E8 8621FFFF CALL Recorder.00401470 0040F2EA > 8A4F 04 MOV CL, BYTE PTR DS:[EDI+4] ; 第五位KEY 0040F2ED . 8B7E 74 MOV EDI, DWORD PTR DS:[ESI+74] 0040F2F0 . 837F F4 05 CMP DWORD PTR DS:[EDI-C], 5 0040F2F4 . 7D 0A JGE SHORT Recorder.0040F300 0040F2F6 . 68 57000780 PUSH 80070057 0040F2FB . E8 7021FFFF CALL Recorder.00401470 0040F300 > 8A5F 05 MOV BL, BYTE PTR DS:[EDI+5] ; 第六位KEY 0040F303 . 8B7E 74 MOV EDI, DWORD PTR DS:[ESI+74] 0040F306 . 885C24 1A MOV BYTE PTR SS:[ESP+1A], BL 0040F30A . 837F F4 06 CMP DWORD PTR DS:[EDI-C], 6 0040F30E . 7D 0A JGE SHORT Recorder.0040F31A 0040F310 . 68 57000780 PUSH 80070057 0040F315 . E8 5621FFFF CALL Recorder.00401470 0040F31A > 8A5F 06 MOV BL, BYTE PTR DS:[EDI+6] ; 第七位KEY 0040F31D . 8B7E 74 MOV EDI, DWORD PTR DS:[ESI+74] 0040F320 . 885C24 1B MOV BYTE PTR SS:[ESP+1B], BL 0040F324 . 837F F4 07 CMP DWORD PTR DS:[EDI-C], 7 0040F328 . 7D 0A JGE SHORT Recorder.0040F334 0040F32A > 68 57000780 PUSH 80070057 0040F32F . E8 3C21FFFF CALL Recorder.00401470 0040F334 > 8A5F 07 MOV BL, BYTE PTR DS:[EDI+7] ; 第八位KEY 0040F337 . 0FB67C24 16 MOVZX EDI, BYTE PTR SS:[ESP+16] 0040F33C . 0FB6D2 MOVZX EDX, DL ; DL为第一位KEY的ASCII值 0040F33F . 83EA 30 SUB EDX, 30 0040F342 . 3BFA CMP EDI, EDX ; EDI = ((第一位用户名 | 0x52) % 0x0a) 0040F344 . 75 48 JNZ SHORT Recorder.0040F38E 0040F346 . 0FB65424 13 MOVZX EDX, BYTE PTR SS:[ESP+13] ; 第二位KEY 0040F34B . 0FB67C24 12 MOVZX EDI, BYTE PTR SS:[ESP+12] ; ((第二位用户名 | 0x45) % 0x0a) 0040F350 . 83EA 30 SUB EDX, 30 0040F353 . 3BFA CMP EDI, EDX 0040F355 . 75 37 JNZ SHORT Recorder.0040F38E ; 不相等则跳,通过方法2来进行验证 0040F357 . 0FB65424 14 MOVZX EDX, BYTE PTR SS:[ESP+14] ; 第三位KEY 0040F35C . 0FB67C24 17 MOVZX EDI, BYTE PTR SS:[ESP+17] ; ((第一位用户名 | 0x43) % 0x0a) 0040F361 . 83EA 30 SUB EDX, 30 0040F364 . 3BFA CMP EDI, EDX 0040F366 . 75 26 JNZ SHORT Recorder.0040F38E ; 不相等则跳,通过方法2来进行验证 0040F368 . 0FB65424 15 MOVZX EDX, BYTE PTR SS:[ESP+15] ; 第四位KEY 0040F36D . 0FB67C24 18 MOVZX EDI, BYTE PTR SS:[ESP+18] ; ((第二位用户名 | 0x4f) % 0x0a) 0040F372 . 83EA 30 SUB EDX, 30 0040F375 . 3BFA CMP EDI, EDX 0040F377 . 75 15 JNZ SHORT Recorder.0040F38E ; 不相等则跳,通过方法2来进行验证 0040F379 . 99 CDQ 0040F37A . BF 0A000000 MOV EDI, 0A 0040F37F . F7FF IDIV EDI ; EAX=用户名各位ASCII值的累加 0040F381 . 0FB6C2 MOVZX EAX, DL ; 余数 0040F384 . 0FB6D1 MOVZX EDX, CL ; 第五位KEY 0040F387 . 83EA 30 SUB EDX, 30 0040F38A . 3BC2 CMP EAX, EDX 0040F38C . 74 38 JE SHORT Recorder.0040F3C6 ; 相等则跳,注册成功,否则通过方法2进行验证,以下代码为方法2验证 0040F38E > 807C24 19 38 CMP BYTE PTR SS:[ESP+19], 38 ; 与第一位KEY相比 0040F393 0F85 83000000 JNZ Recorder.0040F41C ; 不相等则跳,注册失败 0040F399 . 807C24 13 33 CMP BYTE PTR SS:[ESP+13], 33 ; 第二位KEY 0040F39E 75 7C JNZ SHORT Recorder.0040F41C 0040F3A0 . 8A5424 14 MOV DL, BYTE PTR SS:[ESP+14] ; 第三位KEY 0040F3A4 . B0 36 MOV AL, 36 0040F3A6 . 3AD0 CMP DL, AL 0040F3A8 75 72 JNZ SHORT Recorder.0040F41C 0040F3AA . 384424 15 CMP BYTE PTR SS:[ESP+15], AL ; 第四位KEY 0040F3AE 75 6C JNZ SHORT Recorder.0040F41C 0040F3B0 . 3AC8 CMP CL, AL ; CL为第五位KEY 0040F3B2 75 68 JNZ SHORT Recorder.0040F41C 0040F3B4 . 807C24 1A 31 CMP BYTE PTR SS:[ESP+1A], 31 ; 第六位KEY 0040F3B9 75 61 JNZ SHORT Recorder.0040F41C 0040F3BB . 807C24 1B 34 CMP BYTE PTR SS:[ESP+1B], 34 ; 第七位KEY 0040F3C0 75 5A JNZ SHORT Recorder.0040F41C 0040F3C2 . 3AD8 CMP BL, AL ; BL为第八位KEY 0040F3C4 75 56 JNZ SHORT Recorder.0040F41C 0040F3C6 > 6A 00 PUSH 0 ; 注册成功 0040F3C8 . 6A 00 PUSH 0 0040F3CA . 68 B8E04300 PUSH Recorder.0043E0B8 ; registration has succeeded! 0040F3CF . E8 41140200 CALL Recorder.00430815 0040F3D4 . 8B7E 70 MOV EDI, DWORD PTR DS:[ESI+70] 0040F3D7 . E8 507A0200 CALL Recorder.00436E2C 0040F3DC . 8B40 04 MOV EAX, DWORD PTR DS:[EAX+4] 0040F3DF . 57 PUSH EDI ; /Arg3 0040F3E0 . 68 B0CF4300 PUSH Recorder.0043CFB0 ; |username 0040F3E5 . 68 34CD4300 PUSH Recorder.0043CD34 ; |option 0040F3EA . 8BC8 MOV ECX, EAX ; | 0040F3EC . E8 3F150200 CALL Recorder.00430930 ; \WriteProfileString保存用户名 0040F3F1 . 8B7E 74 MOV EDI, DWORD PTR DS:[ESI+74] 0040F3F4 . E8 337A0200 CALL Recorder.00436E2C 0040F3F9 . 8B40 04 MOV EAX, DWORD PTR DS:[EAX+4] 0040F3FC . 57 PUSH EDI ; /Arg3 0040F3FD . 68 9CCF4300 PUSH Recorder.0043CF9C ; |registration_code 0040F402 . 68 34CD4300 PUSH Recorder.0043CD34 ; |option 0040F407 . 8BC8 MOV ECX, EAX ; | 0040F409 . E8 22150200 CALL Recorder.00430930 ; \WriteProfileString保存密码 0040F40E . 5B POP EBX 0040F40F . 5F POP EDI 0040F410 . 8BCE MOV ECX, ESI 0040F412 . 5E POP ESI 0040F413 . 5D POP EBP 0040F414 . 83C4 0C ADD ESP, 0C 0040F417 . E9 32970100 JMP Recorder.00428B4E 0040F41C > 6A 00 PUSH 0 ; 注册失败 0040F41E . 6A 00 PUSH 0 0040F420 . 68 A0E04300 PUSH Recorder.0043E0A0 ; registration failed! 0040F425 . E8 EB130200 CALL Recorder.00430815 0040F42A . 5B POP EBX 0040F42B . 5F POP EDI 0040F42C . 5E POP ESI 0040F42D . 5D POP EBP 0040F42E . 83C4 0C ADD ESP, 0C 0040F431 . C3 RETN
【分析总结】
通过分析可以发现算法其实很简单,但反汇编代码很长,感觉有很多无用代码,不知道是不是作者故意以此来增加我等菜鸟的分析难度的.
要成功注册的条件为:用户名必须大于等于2,KEY必须大于等于8,注册码验证方法分两种(下面用C++语言进行描述):
一. 只需要验证前面五位注册码,但是注册码的位数还是必须大于等于5,否则前面验证长度的时候通不过.五位注册码要满足的条件为:
Char *pName;//用户名
Char* pKey;//注册码
1.pKey[0] = (pName[0] | 0x52) % 10 + 0x30;
2. pKey[1] = (pName[1] | 0x45) % 10 + 0x30;
3. pKey[2] = (pName[0] | 0x43) % 10 + 0x30;
4. pKey[3] = (pName[1] | 0x4f) % 10 + 0x30;
5.pKey[4] = (各位用户名ASCII值累加的值 % 10) + 0x30;
二.第二种方法我实现想不出一个好名字来形容它,这里估且叫它硬编码方式吧.因为这种方式不用考虑用户名(长度得大于2位),只要输入了这个注册码就可以注册成功(真想问一下作者干嘛要这样做^_^),由上可知这个注册码为:83666146
下面帖一个正规的C++代码.
代码:
void MakeKey(char* pName) { int iValue = 0,iLen = strlen(pName); for (int i = 0; i < iLen; ++i) { iValue += pName[i]; //累加用户名的ASCII值 } //这里没有加x30就直接输出了,原因大家自己想吧,嘻... cout<<(pName[0] | 0x52) % 10; cout<<(pName[1] | 0x45) % 10; cout<<(pName[0] | 0x43) % 10; cout<<(pName[1] | 0x4f) % 10; cout<<iValue % 10; //由于上面只有五位,所以还要多输出三位以上 cout<<"-cai"<<endl; }
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!