第二个需要写注册机
首先查看文件,打开文件,什么也没有,help ->about,弹出下面的弹窗
看来是没有什么线索,直接放进OD里面
这里有一个函数CreatFileA,这个函数目的是访问一个文件,如果文件不存在返回值为-1
HANDLE CreateFile(
LPCTSTR lpFileName, //指向文件名的指针
DWORD dwDesiredAccess, //访问模式(写/读)
DWORD dwShareMode, //共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针
DWORD dwCreationDisposition, //如何创建
DWORD dwFlagsAndAttributes, //文件属性
HANDLE hTemplateFile //用于复制文件句柄
);
跟下去看,可以看到函数执行完成后会返回一个-1到eax,下一条指令cmp捕获到后让ZF位变成0,后面的jnz指令就没办法跳转了
如果没有这个文件的话就没有办法继续下去了,所以我们在同目录下新建一个同名称文件(CRACKME3.KEY),而且在里面写入字符串,重新开始调试
重新调试后就不会返回-1了
继续,接下来又调用了一个ReadFile函数把文件里面的字符串放进寄存器ebx和内存空间里面
而且可以看到,这个函数到这里只截取了到r的字符,也就是说前18个截取到了,后面8个暂时没有管
继续往下,有一个陌生的call,由于不清楚这个call的用处,所以f7跟进
前面两个xor清空寄存器,之后把push进来的参数,也就是18个字符给esi,然后给bl数值41,之后就是一串循环
循环是根据cl的大小来判断的,循环内部有bl的自加算法,如果bl里面的数等于4f就会跳出循环,之前给bl的数是41,也就是说这个循环会执行4f-41=14次
看一下这个代码,首先以字节的大小把刚才esi里面传入的字符给到al,然后将bl里面的数和al里面的数进行异或,异或完了之后再将它传给esi。
我们来看第一次异或后得到的结果,第一次是a的ascall码和41异或
得到了0x20,然后我们再搜索0x20的ascall码的含义
在键盘上是space,以字符的形式显示就是空格
b的ascall码和0x42(每次循环bl自加1)异或得到的结果也是0x20,所以前十四个字符在循环过后都显示为空格。
再看另外一个指令
这个是把前14个字符的ascall码加到0x4020f9这个地址上,原本地址里面数字是00,加上14次之后就变成了0x01c0这个十六进制数
那这个循环就没有什么其他含义了,往下走
可以看见刚出call后,刚才的4020f9这个地址就和12345678进行了一次异或,异或完了之后这个地址里面的数变成了123457b8,之后又进了一个call
这个call也是不清楚什么含义,f7进去看看之后发现是给esi赋值opqr,然后把123457b8(即所有输入进去字符中的前14个字符的ascall码的和异或上0x12345678之后得到的数)和opqr进行比较,如果相同就进行跳转。
而跳转是跳转到了破解成功的弹窗上,那么我们就明白了key文件里面的后4位字符和前面的14位字符的关系,后4位字符就是前面14位字符的ascall码和异或上0x12345678得到的
理清了思路,我们就可以写注册机制作key文件破解程序了
下面是注册机的脚本
username = input("please input your username:").center(14)
if len(username) > 14:
print("error,please input number less 14")
exit(0)
#先用username和0x41开始异或
tem_ = 0
xor_use = []
sum = 0
for i in range(len(username)):
tem = ord("A") + i
xor_use.append(tem ^ ord(username[i]))
#还有连加异或后得到的结果
sum += ord(username[i])
key = sum ^ 0x12345678
key_bytes = bytes(key.to_bytes(4,byteorder='little'))
with open('CRACKME3.KEY',"wb+") as f:
#把前十四个加密后的字符输入进去,然后把后四位需要进行比较的字符也输入进去,即可搞定key文件注册
f.write(bytes(xor_use))
f.write(bytes(key_bytes))
print("it is ok!")
当然,这个程序也能破解,不过破解难度会比较大,有时间的话会更新