【翻译】R4ndom破解教程全文翻译(For新手):第十六章(下)
本帖最后由 sighout 于 2016-9-9 17:19 编辑先说说上篇文章最后留的作业这是我做的,可能不是最好的方法第一个是按一次按钮出现破解成功信息。这个简单,把代码中和0xA比较改为和0x1比较就OK了。第二个也不是很难,初始化显示成功在初始化数据“DEAD”“42424242”和错误信息后的跳转,直接跳到Call正确信息的地方。
注意:1、需要把3次错误检查的地方Nop掉,否则点三次按钮还是会出现暴力破解信息。2、点第二次的时候会回到一个错误发生字串,这里我还没想到要怎么处理,有思路的请提供想法,谢谢!(其实用奇偶的方法可以做,但是代码空间可能够)
以上就是作业的思路,有兴趣的再去试试看,可能你的方法比我好。欢迎提供不同的思路。
【翻译】R4ndom破解教程全文翻译(For新手):第十六章(下)
翻译都是我理解的方式进行描述,可能和原文不一致。本教程中文版只在吾爱破解论坛 首发。转载请注明来自吾爱破解论坛@52pojie.cn
正文开始了
暴力破解是一种方法,这中方法是你可以从程序中找到爆破点然后直达我们需要的地方,虽然通过常规的加密/解密你已经知道这个程序的输入和输出,但是你不知道他的解密过程,而是直接打了一个补丁就完事。而这种方法与通过输入用户名和序列号的方式是不同的。如果你以前下载过破解软件,是通过输入用户名和序列号来让程序工作的,它有可能是通过暴力破解来的。
这种工作方式是通过常规的加密/解密输入的用户名和序列号,你尝试不同的输入直到有一次匹配成功,例如:我们输入“12121212”,程序通过常规解密后得到“j6^^gD7-L”,我们使用不同的输入,得到的结果是不同的。我们就是要想办法知道“12121212”是怎么变成“j6^^gD7-L”的,然后让我们的输入的序列号能让程序启动,或者能够注册成功。
请记住,这中方法只适用于程序内部检查用户名和序列号,不适用于网络验证。
和大家说的一样,暴力破解不是难事,首先你至少知道一门编程语言这样就可以自己编写暴力破解的程序,此教程主要是汇编语言,因为要分析代码中的算法。作者自己也会两门其他编程语言____,因此你就可以在高级语言中做暴力破解算法(译者注:我只会C++初阶)
另一个就是要明白用户名和序列号是怎么变成输出的,这样做的原因是它减少了操作次数,所以我们必须尝试。如果我说我们必须在密码栏输入“SECRET“导致输出为”MESSAGE”。这有无限多的方法。但是如果我说把用户名做异或操作后的值很有价值,这样会减少很多方法。
破译密码
还记得前面的教程中我问你是否能破译密码吗,修改什么地方能出现成功,下面就是所有的程序代码:(译者注:这里后面的解释好像ecx和eax反了,我自己是吧eax当作a,ebx当作b,ecx当作c,然后我放上我的解释)004012A9 mov ecx, dword_403040 ; 变量 'c' 004012AF mov ebx, dword_40303C ; 变量 'b' 004012B5 mov eax, dword_403038 ; 变量 'a' 004012BA cmp , 1 ; ***** Button 1004012BE jnz short loc_4012D0004012C0 add ecx, 54Bh ;c += 54Bh004012C6 imul ebx, eax ; b *= a 004012C9 xor eax, ecx ; a^= c004012CB jmp loc_4013E7004012D0 cmp , 2 ; ***** Button 2004012D4 jnz short loc_4012E8004012D6 sub ecx, 233h ; c -= 233h004012DC imul ebx, 14h ; b *= 14h004012DF add ecx, eax ; c += a004012E1 and ebx, eax ; b &= a004012E3 jmp loc_4013E7004012E8 cmp , 3 ; ***** Button 3004012EC jnz short loc_4012FD004012EE add eax, 582h ; a += 582h004012F3 imul ecx, 16h ; c *= 16h004012F6 xor ebx, eax ; b ^= a004012F8 jmp loc_4013E7004012FD cmp , 4 ; ***** Button 400401301 jnz short loc_40131200401303 and eax, ebx ; a &= b00401305 sub ebx, 111222h ; b -= 111222h0040130B xor ecx, eax ; c ^= a0040130D jmp loc_4013E700401312 cmp , 5 ; ***** Button 500401316 jnz short loc_40132400401318 cdq00401319 idiv ecx ; a /= c, divisionrest --> (r)0040131B sub ebx, edx ; b -= r0040131D add eax, ecx ; a += c0040131F jmp loc_4013E700401324 cmp , 6 ; ***** Button 600401328 jnz short loc_4013390040132A xor eax, ecx ; a ^= c0040132C and ebx, eax ; b &= a0040132E add ecx, 546879h ; c += 546879h00401334 jmp loc_4013E700401339 cmp , 7 ; ***** Button 70040133D jnz short loc_4013510040133F sub ecx, 25FF5h ; c -= 25FF5h00401345 xor ebx, ecx ; b ^= c00401347 add eax, 401000h ; a += 401000h0040134C jmp loc_4013E700401351 cmp , 8 ; ***** Button 800401355 jnz short loc_40136700401357 xor eax, ecx ; a ^= c00401359 imul ebx, 14h ; b *= 14h0040135C add ecx, 12589h ; c += 12589h00401362 jmp loc_4013E700401367 cmp , 9 ; ***** Button 90040136B jnz short loc_4013780040136D sub eax, 542187h ; a -= 542187h00401372 sub ebx, eax ; b -= a00401374 xor ecx, eax ; c ^= a00401376 jmp short loc_4013E700401378 cmp , 0Ah ; ***** Button 100040137C jnz short loc_40138A0040137E cdq0040137F idiv ebx ; a /= b, division rest -->(r)00401381 add ebx, edx ; b += r00401383 imul eax, edx ; a *= r00401386 xor ecx, edx ; c ^= r00401388 jmp short loc_4013E70040138A cmp , 0Bh ; ***** Button 110040138E jnz short loc_4013A300401390 add ebx, 1234FEh ; b += 1234FEh00401396 add ecx, 2345DEh ; c += 2345DEh0040139C add eax, 9CA4439Bh ; a += 9CA4439Bh004013A1 jmp short loc_4013E7004013A3 cmp , 0Ch ; ***** Button 12004013A7 jnz short loc_4013B2004013A9 xor eax, ebx ; a ^= b004013AB sub ebx, ecx ; b -= c004013AD imul ecx, 12h ; c *= 12h004013B0 jmp short loc_4013E7004013B2 cmp , 0Dh ; ***** Button 13004013B6 jnz short loc_4013C8004013B8 and eax, 12345678h ; a &= 12345678h004013BD sub ecx, 65875h ; c -= 65875h004013C3 imul ebx, ecx ; b *= c004013C6 jmp short loc_4013E7004013C8 cmp , 0Eh ; ***** Button 14004013CC jnz short loc_4013DB004013CE xor eax, 55555h ; a ^= 55555h004013D3 sub ebx, 587351h ; b -= 587351h004013D9 jmp short loc_4013E7004013DB cmp , 0Fh ; ***** Button 15004013DF jnz short loc_4013E7004013E1 add eax, ebx ; a += b004013E3 add ebx, ecx ; b += c004013E5 add ecx, eax ; c += a*** 特别感谢figugegl在他的教程中为我做了大部分工作 (当我发现我已经完成了三分之二后). ***
现在我们知道了每一个按钮都做了什么操作了。接下来我们需要的是输入和输出。这是我们已经知道的数据了,在代码自修改段中有官方(译者注:程序自己的算法,我们分析的代码)的算法,然后进行一些列合法的异或操作。具体就是与变量a、b、c进行异或后保存,然后第二个以后的数据都是和之前异或后的数据进行再次异或。
地址 401407的值EB 3F 90 90 与a 异或后为 528B550C(这个值是我们之前修改出来的)然后反向求出 a为 B9B4C59C地址 40143B的值04 66 E7 BB与b 异或后为FF 75 0C 6A 然后可反向求出b就是直接与结果异或就OK了地址 40143F 的值 4D BD 08 8B与c 异或后为03 FF 75 08 然后可反向求出c
我们最终要做的是尝试修改的每一个组合,通过点击按钮模仿每一个尝试手动可能的组合,当我们做了10次按钮操作后,我们可以看到a\b\c中的值,这个就是正确的值。(译者注:不明白为什么是正确的值,是我们补丁后的程序?)
这个程序的作者提供了前两个值是7和9.给出的原因是,如果你的电脑比较慢的话,要把所有有可能的值都试一次的话要花费太多时间,在不知道前两位的情况下我用一台8核的电脑花了大约1小时才破译出密码。知道前两位的情况下只花了大约1分钟。通常在破解程序时我们不会有任何的提示(当然),我在破译程序中有包含两个已知的数。
下面是C语言写的破译程序#include <iostream>usingnamespace std;
void brute(void){ charfinalAsciiSerial =""; int i, varA, varB, varC,tempVar, tempSerial;
// we know the first number is '7' for (tempSerial = 7;tempSerial <= 7; tempSerial++) { // and we know the second number is '9' for (tempSerial = 9;tempSerial <= 9; tempSerial++) { for (tempSerial = 1;tempSerial <= 15; tempSerial++) { for (tempSerial = 1;tempSerial <= 15; tempSerial++) { for (tempSerial = 1;tempSerial <= 15; tempSerial++) { cout <<"."; // Update display for (tempSerial = 1;tempSerial <= 15; tempSerial++) { for (tempSerial = 1;tempSerial <= 15; tempSerial++) { for (tempSerial = 1;tempSerial <= 15; tempSerial++) { for (tempSerial = 1;tempSerial <= 15; tempSerial++) { for (tempSerial = 1;tempSerial <= 15; tempSerial++) { // Reset variables varA = 0xDEAD; varB = 0xDEAD; varC = 0x42424242;
// Apply each digit for (i = 0; i < 10; i++) { switch(tempSerial) { case1: varC += 0x54B; varB *= varA; varA ^= varC; break ;
case2: varC = varC - 0x233 +varA; varB = (varB * 0x14)& varA; break ;
case3: varA += 0x582; varC *= 0x16; varB ^= varA; break ;
case4: varA &= varB; varB -= 0x111222; varC ^= varA; break ;
case5: if(varC != 0) // Watch divide by zero! { varB -= (varA %varC); varA /= varC; varA += varC; } break ;
case6: varA ^= varC; varB &= varA; varC += 0x546879; break ;
case7: varC -= 0x25FF5; varB ^= varC; varA += 0x401000; break ;
case8: varA ^= varC; varB *= 0x14; varC += 0x12589; break ;
case9: varA -= 0x542187; varB -= varA; varC ^= varA; break ;
case10: if(varB != 0) // Watch divide by zero! { tempVar = varA %varB; varA /= varB; varB += tempVar; varA *= tempVar; varC ^= tempVar; } break ;
case11: varB += 0x1234FE; varC += 0x2345DE; varA += 0x9CA4439B; break ;
case12: varA ^= varB; varB -= varC; varC *= 0x12; break ;
case13: varA &=0x12345678; varC -= 0x65875; varB *= varC; break ;
case14: varA ^= 0x55555; varB -= 0x587351; break ;
case15: varA += varB; varB += varC; varC += varA; break ; } }
// stop if serial equals propervalues if((varA == 0x9CC5B4B9) &&(varB == 0xD1EB13FB) &&(varC == 0x837D424E)) { // Convert to ASCII for (i = 0; i < 10; i++) { if(tempSerial <= 9) { finalAsciiSerial= tempSerial + 0x30; } else { finalAsciiSerial = tempSerial +0x37; } } cout <<"\n\n***** Bruteforced serial: "; cout<< finalAsciiSerial << "\n"; return; }}}}}}}}}}}}intmain(){ cout <<"Bruteforcerby R4ndom\n\n"; brute(); cout << "\nBruteforcing done...\n"; return0;}首先,建立我们的变量a\b\c,然后我们知道第一个和第二个是7和9,后面的是在1-15之间,然后我插入了一个“点”字串在控制台中输出,我不太喜欢程序没有任何反应,能看到解密的动作,证明程序没有当掉。接下来,我们执行的变量的修改取决于哪个键被按下,就像我们在上面显示的一样。当输入10个数据时(因为长度是10位),我们会检查这三个变量,看它们是否与我们程序中比较的数据一致,如果一致,我们则停下来,把这个数据转换为ASCII码,然后把它显示在程序上。如果不一致则继续进行下一条数据。下面是控制台破译过程和结果:让我输入破译后的密码看看程序怎么运行我们现在已经破译了这个程序。
译者注:算法中要注意5和7里面,5和A是一样的东西
由于工作关系,后面的文章可能会比较晚才进行翻译,因为我要正在破解了,才能写出我理解的流程,才能在这里告诉大家。
文章链接和程序放到附件中
翻译的很不错。 楼主辛苦。 谢谢分享, 学习了 整理成电子书的话,就更好啦,不错,支持楼主 好详细。。值得收藏 。。谢谢LZ 新手过来看看 继续!谢谢
页:
[1]