此程序要求找到serial 为 76876-77776 的名字
载入OD运行,搜索字符串,找到correct字样,跟进
向上找关键call,看到1051cd4处的call,猜测应该为关键call,进入call看看
进入关键call,下断点之后输入name :11111 ,serial :76876-77776
可以看到寄存器窗口确实出现了11111,说明是对我们输入的进行处理,说明这是关键call,我们没有找错.
但是输入长度应该为4,不为4就失败;因此我们在10517a2处下条件断点shift+f2 ,[ecx-0xc]==4
继续往下走,分析出输入的name应该是小写的a到z,并且这是个字母不能重复
继续往下走,看到密码长度应该为11,并且中间为serial的第6个元素应该为2D(即'-')
往下分析,发现#4478这个函数是取出name的第0位,push 0和ecx 是他的参数,接下来就是关键算法了
上图call后的代码大概意思就是,
注意这里的-20,-1f,-1e 等,是ebp-0x20,ebp-0x1f,ebp-0x1e
继续后走的大概意思和上图差不多
然后name的第三个第四个都是类似操作就不分析了;
接下来把ebp-0x20和bl相加,此时bl是(name[1]>>2) & 1 +1的结果,他们要等于7 (密码的第一位)
分析完是[ebp-0x20]和[ebp-0x26]相加,[ebp-0x1d]和[ebp-0x25]相加,[ebp-0x24]和[ebp-0x1f]相加,[ebp-0x1e]和[ebp-0x28]相加,[ebp-0x1c]和[ebp-0x27]相加
他们的和必须等于密码,所以我们写如下的程序跑
#include<stdio.h>
int main()
{
char name[4];
char temp1[5];
char temp2[5];
int i=0;
name[0]='a';
name[1]='a';
while(name[0]!='z'+1)
{
name[1]='a';
for(i=0;i<5;i++)
{
temp1[i]=((name[0]>>i)&1)+5;
}
while(name[1]!='z'+1)
{
//printf("name[1]=%c\t",name[1]);
//temp=name[0];
for(i=0;i<5;i++)
{
temp1[i]=((name[0]>>i)&1)+5;
}
for(i=0;i<5;i++)
{
temp2[i]=((name[1]>>i)&1)+1;
}
if(((temp1[2]+temp2[2])==7)&&((temp1[3]+temp2[3])==6)&&
((temp1[1]+temp2[4])==8)&&((temp1[2]+temp2[0])==7)
&&((temp1[4]+temp2[1])==6))
{
printf("0: %c 1: %c\n",name[0],name[1]);
}
name[1]++;
}
name[0]++;
}
name[2]='a';
name[3]='a';
while(name[2]!='z'+1)
{
name[3]='a';
for(i=0;i<5;i++)
{
temp1[i]=((name[2]>>i)&1)+5;
}
while(name[3]!='z'+1)
{
for(i=0;i<5;i++)
{
temp2[i]=((name[3]>>i)&1)+1;
}
if(((temp1[0]+temp2[2])==7)&&((temp1[3]+temp2[3])==7)&&
((temp1[1]+temp2[4])==7)&&((temp1[2]+temp2[0])==7)
&&((temp1[4]+temp2[1])==6))
{
printf("2: %c 3: %c\n",name[2],name[3]);
}
name[3]++;
}
name[2]++;
}
}
#include<stdio.h>
int main()
{
char name[4];
char temp1[5];
char temp2[5];
int i=0;
name[0]='a';
name[1]='a';
while(name[0]!='z'+1)
{
name[1]='a';
for(i=0;i<5;i++)
{
temp1[i]=((name[0]>>i)&1)+5;
}
while(name[1]!='z'+1)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)