运行分析
- 输入Name和Serial,点击Check无反应
PE分析
- ASM程序,32位,无壳
静态分析&动态调试
- ida找到关键字符串,进入关键函数
- 通过静态分析和动态调试,得到以下结论
- 总结:
- 1、String = Serial
- 2、String2 是通过根据Name、c/d盘硬盘序列号、常量"071362de9f8ab45c",通过一系列计算得到,具体如下:
- 计算v14 = int(sqrt(v17v17 + v16v16)),v16和v17是c/d盘硬盘序列号
- 计算v9,取每一位Name的字符进行乘法、加法、或运算得到,详见算法分析
- 计算v11 = (v14 | rol(v9, 1)) & 0xFFFFFFF
- 计算String2 = str1[v11每次整除4%16],依次得到String2每个字符
算法分析
from ctypes import *
from math import sqrt
import win32api
Name = 'concealbear'
Serial = ''
str1 = '071362de9f8ab45c'
# 获取硬盘序列号
v17 = win32api.GetVolumeInformation("C:\\")[1]
v16 = win32api.GetVolumeInformation("D:\\")[1]
# 计算v14
v14 = int(sqrt(v17*v17 + v16*v16))
# 计算v9 = sub_401036(::String)
ecx = c_uint32(0)
ebx = c_uint32(0)
edx = c_uint32(0)
eax = c_uint32(1)
r = c_uint32(0)
for i in range(len(Name)):
ecx.value = ord(Name[i])
ecx.value = ecx.value | ecx.value
if ecx.value == 0:
break
r.value = eax.value * ecx.value # 执行完mul后,edx为乘积结果的高8位,eax为结果的低8位
edx.value = (eax.value * ecx.value - r.value) >> 32 # 计算mul的高8位
eax.value = r.value
eax.value = eax.value + edx.value
v9 = c_uint32(0)
v9.value = eax.value
# 计算v11
v11 = (v14 | (v9.value * 2 +((v9.value * 2)>>32))) & 0xFFFFFFF # rol溢出部分,最终eax = 高8位eax>>32 + 低8位eax
# 计算String2
String2 = ''
while 1:
v13 = v11
String2 += str1[v11%16]
v11 = v13 // 4
if v11 == 0:
break
Serial = String2
print(Name + '的序列号为:\n' + Serial)
- 验证成功