160CM-034
1. 爆破
程序打开以后,没有注册按钮和窗口,只有一个uncracked的提示。直接拖进OD中,从头往下看,可以很容易的看出程序流程:
① 判断CRACKME3.key文件是否存在;
② 读取文件内容并判断读取内容的字节数;
③ 将读取到的内容按两个校验算法进行计算,比较结果是否相同。
因此,要爆破就需要将上述三处判断的跳转都改到正确的流程上去,需要:
(1)401035处,将jnz short 00401043
改为jmp short 00401043
;
(2)40106D处,将jnz short 00401037
改为nop
;
(3)40109F处,将je short 00401037
改为nop
;
上述修改完成后,程序启动后的菜单栏提示已经变成了Cracked的字样,但是没有破解成功的提示框弹窗,还需要在40118A处,将jnz short 004011A3
改为nop
,这样就全部爆破就完成了。
2. 算法分析
先分析校验算法1,用IDA打开程序,找到算法子程序401311
,按F5得到伪代码,如下图:
从伪代码中可以看出,算法依次将每个字节与变量v4(从65到79每次加1)进行异或计算,然后将结果累加,共执行14次。
然后累加结果再与0x12345678
进行异或计算。
校验算法2很简单,将从文件中读取到的内容,取第15~18字节的内容,当成整型变量值。
然后比较算法1的异或结果和算法2得到的整型变量是否相等,相等则成功。
另外,由于注册成功后提示的字符串是异或后的结果,如果要显示希望的字符,则需要先进行异或处理后,将异或处理后的内容当做1~14字节的内容。
编写注册机算法程序如下:
// 160CrackMe-034.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <math.h>
int _tmain(int argc, _TCHAR* argv[])
{
char input[50],String1[18];
int i, j,length;
int k,temp;
int code1;
printf("请输入用户名:");
scanf_s("%s", input, 50);
length = strlen(input);
k = 65;
//现将用户名异或处理得到长度为14字节的字符串
for (i = 0; i < 14; i++)
{
if (i<length)
{
String1[i] = input[i] ^ k;
}
else
{
String1[i] = 0 ^ k;
}
k++;
}
j = 0;
k = 65;
code1 = 0;
do
{
temp = k ^ String1[j];
k++;
code1 = code1+temp;
if (!temp)
break;
j++;
} while (k != 79);
code1 = code1 ^ 0x12345678;
String1[14] = code1 & 0xFF;
String1[15] = (code1 & 0xFF00)>>8;
String1[16] = (code1 & 0xFF0000) >> 16;
String1[17] = (code1 & 0xFF000000) >> 24;
char * path = "z:\\CRACKME3.KEY";
FILE * pfile;
fopen_s(&pfile, path, "w");
fwrite(String1, sizeof(byte), 18, pfile);
fclose(pfile);
system("pause");
return 0;
}
输入用户名helloworld
,生成key文件后,将文件复制到程序目录下,运行程序,验证成功。
3. 总结
这道题由于异或计算会得到非可见的ASCII码字符,因此注册机输出文本信息会有不可见的字符,需要直接二进制写入key文件。