045
无壳

暴力破解
根据字符串查找到相关跳转,直接将其改成jmp即可获取破解版本

算法分析
想上找到函数头下断点,重新分析程序先是获取用户名和序列号,之后再将序列号字符串转换成整数,接下来将用户名字的字符ASCII码累乘取后28位,将得到的结果与转换成整数的序列号进行对比相等则成功,不相等则失败

在撰写解码器时需要注意每一次累乘结果都需要取后32位,因为寄存器只能存32位,在这里的算法中也没有对溢出进行特殊处理,因此可以写出keygen:
python
username=input("Input username:").strip()
serial=1
for ch in username:
serial=serial*ord(ch)& 0xFFFFFFFF
serial=serial&0xFFFFFFF
print(f"serial{serial}")
046
UPX壳

去壳

暴力破解
字符串查找到关键跳转,将其给nop掉即可获得破解版本


算法分析
向上找到函数头,重新分析,发现在输入序列号之前就会进行一个数字预处理,之后将处理好的数据存储到444410处为30314010,之后再将输入的序列号与存储的数据30314010判断是否相等,如果相等则弹出成功语句

向上分析可以找到相关算法分别对内存的三个位置的数据进行了操作,地址分别为4445558、4445554、444555C,方便描述分别给他们起名为a1,a2,a3可以根据这个算法分析出伪代码为:a3*0xCDD+a1*a2+a3-a1+a3。在内存处查看相关地址内存储的数据可以找到a1=0x02,a2=0x06,a3=0x23F0

关于这个数据是怎么计算出来的,在401390函数中生成a1,a2,a3值,从函数中可以发现是从系统的版本号中直接获取的,因为程序是比较旧的程序,系统兼容性等问题,所以pyhton代码中没办法获取到程序计算使用的版本号,这里直接使用版本号
可以生成keygen为:
python
a1=0x02
a2=0x06
a3=0x23F0
print(a3*0xCDD+a1*a2+a3-a1+a3)
047
无壳

在x32dbg中没有找到相关线索,但是可以在IDA中发现函数名没有被魔改,还可以找到关键函数以及他所对应的地址429D24

暴力破解
根据找到的函数向下继续可以找到一个关键跳转,将他给nop掉即可获取破解版软件

算法分析
对文件中的字符串进行ASCII码值的累加,累加之后将和与0x20A9进行对比,相等则成功,不相等就失败

可打印字符中ASCII码值最大为126,也就意味着文件中至少有67个字符,使用随机生成算法每次随机生成一个数之后用目标值-随机ASCII码值,直到差也在可打印范围内,可以生成keygen:
python
import random
def generate_string(target=0x20A9):
MIN, MAX = 32, 126
chars = []
while target > MAX:
# 随机生成字符,但要保证剩余的能达到
max_val = min(MAX, target - MIN)
min_val = max(MIN, target - MAX)
if min_val > max_val:
min_val, max_val = MIN, MAX
val = random.randint(min_val, max_val)
chars.append(val)
target -= val
chars.append(target)
return ''.join(chr(c) for c in chars), chars
# 测试
for _ in range(3):
s, vals = generate_string(0x20A9)
print(f"\n字符串: {s}")
print(f"长度: {len(s)}")
print(f"累加和: {sum(vals)} (0x{sum(vals):04X}) ✓")