003-Cruehead-Crackme-3
算法分析
使用x32dbg分析,进入程序。发现调用了CreateFile函数,然后将返回值与-1对比来决定是否跳转。从参数可以得到一个文件名“CRACKME3.KEY”。根据CreateFile函数的定义发现:如果已有该文件则返回-1,反之返回句柄。说明这个函数在此是判断是否有这样一个KEY文件。
接着往后看
发现一个readfile函数,猜测该函数是要读取key文件中的数据。从参数可以发现,数据被保存到了0x402008地址处,长度被保存到0x4021A0处。如果不为18则要跳转。那估计key的长度要为18,或者也可以往后看看到底哪个跳转分支为破解成功,这里不再赘述。
继续
0x401074处的函数估计是对key进行处理,也就是最关键的函数。因为存放key的地址0x402008入栈作为了参数。
进入函数
函数的逻辑很简单,key一共18位前14位依次与0x41到0x4F异或,并将每一位的结果累加至地址4020F9处。异或结果为0则退出循环。实际计算次数保存在0x402149处。
退出函数后继续
之后将0x4020F9处的结果与0x12345678异或。在调用一个函数后,如果eax与0x4021F9处数值相等将al置1,反之置0。观察后面的跳转,如果al为0就发生跳转,可以发现跳转的方向与之前key不为18位跳转的方向一样,说明这是失败的情况。即eax需要与0x4020F9处数值相等。
进入40133C函数
发现在函数内又移动了esi,即指向后四位key,将其值赋予eax。说明eax是后四位key的ASCII码按字节倒序排列。
到此就结束了。
算法总结:
需要一个CRACKME3.KEY文件
其中保存着key
key一共18位
key前14位异或0x41-0x4F(A-O)
将异或后的结果累加至4020F9处
将0x4021f9处结果与0x12345678异或
将密码后4位的ASCII码倒序存放至eax
如果eax与0x4021f9处结果相等则成功
注册机:
str='endmaxendmax66' #想要显示的字符(前14位按位异或后的结果)
#获取输入的前14位密码
def getinput(str):
print("显示字符串:",str)
lis=[]
for i in range(0,14):
lis.append(chr(ord(str[i])^(0x41+i)))
input=''.join(lis)
return input
#获取完整密码
def function(input):
print("输入:",input)
password1=list(input)
result=0;
for i in range(0,14):
result+=ord(password1[i])^(0x41+i)
result^=0x12345678
result=hex(result)
print('计算结果:',result)
password2=[]
for i in range(4):
password2.append('0x'+result[2+2*i:4+2*i])
password2[i]=chr(int(password2[i],16))
password2.reverse()
out = ''.join(password2)
password=input+out;
print('密码长度:',len(password))
with open("D:/re_work/New160CrackMe/003-Cruehead-CrackMe-3/CRACKME3.KEY", "wb+") as f:
f.write(bytes(password.encode()))
f.close()
function(getinput(str))