新手破解练习Crackme160之125 - nullz
-
Very Easy
OD载入程序, 通过失败关键词 "Invalid Registration Key!" 定位到00401A4B, 跳转来自004019EF, 上面即是字符串比较, 得到固定串 "qJT62aWfviq0P57JGs2FelQkX", 输入验证成功~
-
Simple version1
同理搜索错误提示关键词 "User Name must ..." 定位到00401B10, 00401C96, 分别下断, 点验证~ 在00401B10处停下~, 所以这个事件入口是00401A70, 看到有跳入指示, 所以往上看, 发现了5个jmp应该对应1~5关的跳转吧, 都下断测试确实如猜想那般~ 我们继续第2关, 输入abcde, 12345单步分析算法:
1). for(i=1; i<=len; i++){ rlt = (rlt+user[i]) * i; }
2). for((i=0; i<len; i++){ code[i] = rlt / user[i] % 10 + 0x30; }
3). 得到code = "63963" 与 输入的12345对比
注册机代码如下:
#include <stdio.h>
#include <string.h>
int main() {
char user[21] = {0};
char code[21] = {0};
unsigned long rlt = 0;
printf("User Name: "); scanf("%s",user);
int len = strlen(user);
if(len < 5){
printf("User Name must have at least 5 characters.");
return 0;
}
for(int i=1; i<=len; i++){
rlt = (rlt + user[i]) * i;
}
for(int i=0; i<len; i++){
code[i] = rlt / user[i] % 10 + 0x30;
}
printf("Reg. Key : %s\n", code);
getchar();getchar();
return 0;
}
运行示例:
User Name: abcde
Reg. Key : 63963
- Simple version2
断点已经下好了直接单步跟踪分析算法: (直接上注册机代码, 对着看吧)
#include <stdio.h>
#include <string.h>
int main() {
char user[21] = {0};
unsigned long esi = 0x81276345;
int edi=0;
printf("User Name: "); scanf("%s",user);
int len = strlen(user);
if(len < 5){
printf("User Name must have at least 5 characters.");
return 0;
}
for(int i=0; i<len; i++){
esi += user[i];
esi ^= i << 8;
esi *= (i + 1);
esi *= ~edi;
edi += len;
}
printf("Reg. Key : %lu\n", esi);
getchar();getchar();
return 0;
}
运行示例:
User Name: abcde
Reg. Key : 3534803155
- Pretty Common
同上断点已下, 输入abcde, 12345, 67890, 单步跟踪, 这个比较复杂一些, 有好几个循环, 需要花比较多时间来跟踪分析, 其中公司名无用, 随便输, 注册机代码如下, 可以对比理解一下:
#include <stdio.h>
#include <string.h>
int CalculateValue(char *szName, unsigned int nLength, unsigned int initValue);
char *reverse_string(char *p, unsigned int nLength);
int main() {
char user[21] = {0};
char code[101] = {0};
unsigned long val1=0, val2=0;
printf("User Name: "); scanf("%s",user);
int len = strlen(user);
if(len < 5){
printf("User Name must have at least 5 characters.");
return 0;
}
for(int i=0; i<len; i++){
if(i % 2 == 1){
val1=CalculateValue((char*)user, len, val2+i);
} else {
val2=CalculateValue((char*)user, len, val1+i);
}
}
sprintf(code, "%lu-%X", val1, val2);
reverse_string((char*)code, strlen(code));
printf("Reg. Key : %s\n", code);
getchar();getchar();
return 0;
}
int CalculateValue(char *szName, unsigned int nLength, unsigned int initValue)
{
unsigned int i, j, k, nTemp, nTemp1, nTemp2, nTemp3, nTemp4, nTemp5, nValue;
int iResult;
char szConst[] = "h14Ml0x\n7kCHwXBzH\tG8iN9+wb5VHZ";
unsigned int dwConstLength = strlen(szConst);
nValue = 1;
for (i = 0; i < nLength; i++)
{
nTemp = szName[i];
nValue *= nTemp;
k = 1;
for (j = 0; j < dwConstLength / 2; j++)
{
nTemp2 = k + j;
nTemp3 = szName[i] % nTemp2;
nTemp4 = szConst[dwConstLength - j - 1] - nTemp3;
nTemp5 = szConst[j];
nTemp5 += nValue;
nValue = nTemp5 + nTemp4;
}
nValue *= (i+1);
nValue = nValue << 8;
nValue ^= initValue;
}
iResult = nValue;
return iResult;
}
//字符串倒序
char *reverse_string(char *p, unsigned int len)
{
if ((NULL == p) || (0 == len) || ('\0' == *p)) return p;
char c;
int i=0;
while(i<len/2){ //头尾对换
c = *(p+len-1-i);
*(p+len-1-i) = *(p+i);
*(p+i) = c;
i++;
}
return p;
}
运行示例:
Company: 任意
User Name: abcde
Reg. Key : A0B544EA-6808514132
- Slightly Diffical
这关比较难一点, 步骤比较多, 大佬都没做完, 我先记录下大佬代码:
#include <stdio.h>
#include <string.h>
unsigned int getvaluebyname(char *szName,unsigned int filesize,unsigned int nCompanyLength,unsigned int *psize);
int rol(unsigned int num, unsigned char i);
int main() {
unsigned char szName[32] = { 0 };
unsigned char szCompany[32] = { 0 };
char * pBuf,c0,c1,c2,*pTempBuf,*pNewBuf;
unsigned int nNameLength, nFileLength, nCompanyLength, nNameValue, nbufsize, i, j, nReadSize, *pInt, nTemp,nTemp10, nTemp2, nTemp9,nTemp11;
FILE *fp=NULL;
printf("User Name: ");
scanf("%s", szName);
nNameLength = strlen((char*)szName);
if (nNameLength < 5)
{
printf("User Name must have at least 5 characters.");
return 0;
}
printf("Company:");
scanf("%s", szCompany);
nCompanyLength = strlen((char*)szCompany);
fp = fopen("nullz.exe", "rb");
if (NULL == fp)
{
printf("Open nullz.exe Fail.\r\n");
return 0;
}
fseek(fp, 0, SEEK_END);
nFileLength = ftell(fp);
nNameValue = getvaluebyname("abcdefgh", nFileLength, nCompanyLength,&nbufsize);
if (nNameValue < nFileLength)
fseek(fp, nNameValue, 0);
pBuf = new char[nbufsize + 3];
if (NULL == pBuf)
{
fclose(fp);
printf("Set Memery Fail.\r\n");
return 0;
}
nReadSize=fread(pBuf, 1, nbufsize, fp);
fclose(fp);
j = 0;
for (i = 0; i < nReadSize; i = i + 4)
{
pInt = (unsigned int *)(pBuf + i);
nTemp = (*pInt) ^ (*((unsigned int *)szName)) ^ j;
while(true){ // 由下面汇编翻译
nTemp = rol(nTemp, (nTemp % 0x1F) & 0xFF);
if(nTemp >= 0) {break;}
nTemp = ~nTemp;
}
/* __asm{
push eax
push edx
push ecx
push ebx
mov eax,nTemp
xor edx,edx
mov ebx,0x1F
div ebx
mov eax, nTemp
mov cl,dl
rol eax,cl
jnb _NEXT
not eax
_NEXT:
mov nTemp,eax
pop ebx
pop ecx
pop edx
pop eax
}*/
*pInt = nTemp;
j += 4;
}
pTempBuf = pBuf+1;
pNewBuf = new char[nReadSize >> 2]();
j = 0;
for (i = 0; i <((nReadSize/4)*4); i=i+4)
{
nTemp2 = (unsigned char)*(pTempBuf - 1);
nTemp2 = nTemp2<<8;
nTemp2 |= (unsigned char)(pTempBuf[0]);
nTemp2 = nTemp2 << 8;
nTemp2 |= (unsigned char)*(pTempBuf + 1);
pTempBuf += 4;
nTemp2 = nTemp2 << 8;
nTemp2 |= (unsigned char)*(pTempBuf - 2);
*((unsigned int*)(pNewBuf + j * 4)) = nTemp2;
j++;
}
nTemp10 = 0xFF33FF77;//esi
pTempBuf = pNewBuf;
nTemp9 = 1;
nTemp11 = (*(unsigned int *)(pTempBuf)) ^ (*(unsigned int *)(pTempBuf-4));//对应00402222 |. 33CB xor ecx,ebx
//以下代码未验证
for (i = 0; i <((nReadSize / 4) ); i++)
{
nTemp2 = *((unsigned int *)(pTempBuf + 4 * i));
nTemp10 ^= nTemp2;
nTemp2 -= i;
nTemp10 *= (i + 1);
nTemp9 += nTemp2;
c0 = *(((char*)&nTemp9));
*(((char*)&nTemp9)) = *(((char*)&nTemp10)+1);
*(((char*)&nTemp10) + 1) = c0;
}
nTemp = (nTemp11^nTemp10 + nTemp9) ^ nTemp9;
//printf("Reg. key : %s\r\n ", (char*)&nTemp);
getchar();getchar();
return 0;
}
int rol(unsigned int num, unsigned char i)
{
return (num << i) | (num >> (sizeof(int) * 8 - i));
}
//004023BA |. E8 A1000000 call nullz.00402460
//getvaluebyname实现了call 00402460函数调用的功能
unsigned int getvaluebyname(char *szName,unsigned int filesize,unsigned int nCompanyLength,unsigned int *psize)
{
unsigned int nResult = 0;
unsigned int i = 0,nLength,nTemp;
nLength = strlen(szName);
nResult = 1;
for (i = 0; i < nLength; i++)
{
nResult *= (szName[i] - nCompanyLength + i);
}
nResult ^= (filesize<<8);
nTemp = filesize >> 1;
if (0 == (nResult%nTemp))
nResult = ~nResult;
nResult = nResult%nTemp;
*psize = nResult;
nResult = filesize - nResult;
nResult = nResult >> 1;
return nResult;
}
因为代码没完全写完, 所以就还没有结果了, 有空再来细究~
- Little Challenging
这关作都说了还没有, 不用解了~
1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~


浙公网安备 33010602011771号