运行分析
- 需破解Name、Company、Serial
PE分析
- 32位程序,EP Section为.text,猜测无壳
静态分析&动态调试
- ida搜索关键字符串,双击进入函数
level 0
- 动调sub_401403函数,注释如上
- Serial输入JPL-168-39,level 0通过
level 1
- 需要满足Serial值为CR-Game vXO,且因第8位为空格,第11位需减去31
- O的ascii值为79,减去31后为48,即数字0,因此Serial最终值为CR-Game vX0
- 验证成功,点击确定后,左下角Level变为Level 002
level 2
- sub_401403函数处按X返回上一层函数,发现了level 1-7的函数
- 动态调试level 2函数sub_4014C7,得到Serial为2leveL1GC,其中第7位ascii值要-59,即第7位=108-59=49=‘1’
- 验证成功
level 3
- 动调level 3函数sub_40154B,注释如上,逻辑如下:
- 1、Name长度为5~20
- 2、Name字母小写转大写
- 3、提取Name每个字符-65,找到其对应v7下标处的字母,拼接在一起
- 4、上述得到的值要等于Serial
Name = 'conceal'
Serial = ''
v7 = 'QWERTYUIOPASDFGHJKLZXCVBNM'Names = []
for i in range(len(Name)):Names.append(ord(Name[i])-32)for i in range(len(Names)):Serial += v7[Names[i] - 65]print(Name + '的Serial为:\n' + Serial)
- 验证成功
level 4
- 动调level 4函数sub_401602,注释如上,逻辑如下:
- 1、Name长度为5~20,Serial长度为2倍Name
- 2、循环一:提取Name每个字符,若为大写-65,找到其对应v7下标处的字母;若为小写-97,找到其对应v8下标处的字母
- 3、循环二:提取Name每个字符,若为大写-65,找到其对应v8下标处的字母;若为小写-97,找到其对应v7下标处的字母
- 4、上述得到的值要等于Serial
Name = 'conceal'
Serial = ''
v7 = 'QWERTYUIOPASDFGHJKLZXCVBNM'
v8 = 'polkiujmnhytgbvfredcxswqaz'for i in range(len(Name)):if ord(Name[i]) < ord('a') or ord(Name[i]) > ord('z'):Serial += v7[ord(Name[i]) - 65]else:Serial += v8[ord(Name[i]) - 97]for i in range(len(Name)):if ord(Name[i]) < ord('a') or ord(Name[i]) > ord('z'):Serial += v8[ord(Name[i]) - 65]else:Serial += v7[ord(Name[i]) - 97]print(Name + '的Serial为:\n' + Serial)
- 验证成功
level 5
- 动调level 5函数sub_40172D,注释如上,逻辑如下:
- 1、Name长度为5~20,Serial长度与Name长度相等
- 2、循环一:Name小写字母转大写字母
- 3、循环二:提取Name每个字符,找到其对应在v10的下标k
- 4、需要满足v9[k] = Serial[k]
Name = 'conceal'
Serial = ''
v10 = 'QWERTYUIOPASDFGHJKLZXCVBNM'
v9 = 'pOlKiUjmnhytgbVfredCXSwqaZ'for i in range(len(Name)):if ord(Name[i]) >= ord('a'):k = v10.index(chr(ord(Name[i]) - 32))Serial += v9[k]else:k = v10.index(chr(ord(Name[i])))Serial += v9[k]print(Name + '的Serial为:\n' + Serial)
- 验证成功
level 6
- 动调level 6函数sub_401823,注释如上,逻辑如下:
- 1、Name长度大于4,company存在,Serial长度大于9
- 2、Serial第一位为’J’,第二位为’i’,第三位为’P’
- 3、通过计算,得到Serial第4-14位
- 4、提取Name每个字符,小写字母转大写字母,再减去61,找到v7[字符]下标对应字母,拼接到Serial第14位之后
Name = 'conceal'
company = 'bear'
Serial = 'JiP'# 初始化Serial
Serials = [ord(i)for i in Serial]
Serials.extend([32]*30)# 计算Serial第4/5/5位
Serials[3] = (ord(company[0]) & 6) + ord(Name[0])
Serials[4] = (ord(Name[0]) & 9) + ord(company[0])Name_0_3 = int("".join([hex(ord(Name[i]))[2:]for i in range(3,-1,-1)]),16)
Serial_9_13 = hex(Name_0_3 + ((0x20202020 ^ Name_0_3) & 0x9070503))[2:]
Serials[9] = int(Serial_9_13[6:],16)
Serials[10] = int(Serial_9_13[4:6],16)
Serials[11] = int(Serial_9_13[2:4],16)
Serials[12] = int(Serial_9_13[0:2],16)# 匹配v7下标
v7 = 'JiP4ZAQWSXCDERFVBGTYHNMJUIKLOP'
for i in range(len(Name)):if ord(Name[i]) >= 97:Serials[13 + i] = ord(v7[ord(Name[i]) - 32 - 61])else:Serials[13 + i] = ord(v7[ord(Name[i]) - 32])print(Name + '的Serial为:\n' + "".join([chr(i) for i in Serials]))
- 验证成功
level 7
- 动调level 7函数sub_401967,注释如上,逻辑如下:
- 1、Serial长度为16,Company长度小于17,Name长度小于17
- 2、通过sub_4012E8函数对Serial进行计算,得到v3
- 3、Name+company的值与v3相等
- 进入sub_4012E8函数进行分析,发现是3个字符处理一次,且有个sub_4011DB函数未知
- 发现码表和取下标操作,是base64decode特征,猜测sub_4012E8函数被base64decode函数
Name = 'conceal' # Name+Company长度为10-12
company = 'bear'import binascii
Serial = binascii.b2a_base64((Name+company).encode()).decode()print(Serial)
- 直接用python的binascii库进行base64decode逆向运算(即base64加密正向运算)
- Name + Company长度必须为10-12位,这样base64加密后,Serial长度才是16位
- 验证成功