【crackmes.one】———— keygenme90
Language: c/c++ | Arch: x86 | Platform: Windows |Tech: keygenme,base64,xor
在WinMain函数中找到这一行
WndClass.lpfnWndProc = sub_401046;
这个函数是回调函数,用于处理窗口消息,
进入该子函数,找到CreateWindowExA函数,把他们的返回值重命名,以增加可读性,像下面这样:
name_hWnd = CreateWindowExA(
dwExStyle: 0,
lpClassName: "EDIT",
lpWindowName: byte_4250C8,
dwStyle: 0x50800080u,
X: 110,
Y: 20,
nWidth: 180,
nHeight: 20,
hWndParent,
hMenu: (HMENU)1,
hInstance: nullptr,
lpParam: nullptr);
pwd_hWnd = CreateWindowExA(
dwExStyle: 0,
lpClassName: "EDIT",
lpWindowName: byte_4250C8,
dwStyle: 0x50800080u,
X: 110,
Y: 60,
nWidth: 180,
nHeight: 20,
hWndParent,
hMenu: (HMENU)2,
hInstance: nullptr,
lpParam: nullptr);
后面GetWindowTextA用于获取输入的name和password
GetWindowTextA(hWnd: name_hWnd, lpString: Name, nMaxCount: 256);
GetWindowTextA(hWnd: pwd_hWnd, lpString: password, nMaxCount: 256);
对应的参数也进行重命名
下面两个是string对象的构造函数,从这里开始切到反汇编视图会比较方便
sub_4010E1(a1: Name, a2: v6);
sub_4010E1(a1: password, a2: v5);
紧接着代码对name进行了处理,然后把处理的结果与password做比较,这里把sub_4010A0的另一个参数注释为obj_expected
; try {
mov byte ptr [ebp+var_4], 1
lea eax, [ebp+obj_Name]
push eax
lea ecx, [ebp+obj_expected]
push ecx
call sub_4010A0
add esp, 8
; } // starts at 401966
; try {
mov byte ptr [ebp+var_4], 2
lea edx, [ebp+obj_expected]
push edx
lea eax, [ebp+obj_password]
push eax
call sub_40108C
具体如何处理,进入sub_4010A0一探究竟

其中edx是下标,sub_401078用于获取Name[i],然后把字符与0x5A异或。
循环完成后,sub_40109B对字符串进行进一步处理
从其中部分代码,如
v14 = (v18 & 0xFC) >> 2;
v15 = ((v19 & 0xF0) >> 4) + 16 * (v18 & 3);
v16 = ((v20 & 0xC0) >> 6) + 4 * (v19 & 0xF);
v17 = v20 & 0x3F;
可以看出有许多移位指令和掩码,这是典型的base64加密算法
因此可以知道,程序对输入的字符串进行了按位xor和base64编码
解密脚本如下
import base64
xor_key = 0x5A
def keygen(Name):
xored = bytes(ord(c) ^ xor_key for c in Name)
return base64.b64encode(xored).decode("ascii")
if __name__ == "__main__":
name = str(input("Please input name: "))
password = keygen(name)
print(f"Your password is: {password}")
浙公网安备 33010602011771号