某考吧题库软件破解分析
前言
前段时间报考了计算机二级的python,在报名页面加了考点Q群,群主居然在推销题库。看它题库挺新的,就想买来练下手。下载之后看着粗制滥造的界面顿时感觉这四十多块好不值😂😂😂。激活的时候发现它有离线激活,于是萌生破解的想法,权当一次练手了
小白第一次破解,可能写得比较啰嗦,见谅~~
软件地址:aHR0cDovL3d3dy53eWs4LmNvbS8=
分析
掏出exeinfope看看有没有壳先
欸嘿,没壳而且还是 .NET,这不就简单了吗
直接拖进dotPeek反编译分析一下
在入口文件 Program
中,注意到这段代码,解密了 Register.UI.dll
然后动态加载
计算 Exam.exe
的MD5,作为AES128-ECB的密钥,然后解密再加载
需要注意的是文件的末尾还附加了 Register.UI.dll
解密后的MD5,用于校验完整性
合理猜测,这个加密的dll应该就是跟激活有关的
写个py脚本解密看看先
import cryptography
from cryptography.hazmat.primitives.ciphers import algorithms
from cryptography.hazmat.primitives.ciphers import modes, Cipher
import hashlib
with open("./Exam.exe", 'rb') as f:
file_data = f.read()
md5_hash = hashlib.md5(file_data).digest()
with open("Register.UI.dll", "rb") as f:
encrypted_data = f.read()
cipher = Cipher(algorithms.AES128(md5_hash), modes.ECB())
decryptor = cipher.decryptor()
decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()
with open("Register.UI.dec.dll", "wb") as f:
f.write(decrypted_data)
解密完还是拖到dotpeek分析,一眼锁定 Activation
找到个 VerifyRegisterCode
函数,应该就是验证注册码的
追踪一下调用,到了 ActiveWindow
里的 ActiveOffline
函数,这里的 card
和 password
对应的应该就是卡号和卡密
到这里就发现不对劲了,WebAccessor.GetOffineActiveCode
难道还要联网获取注册码?
好吧,还真是得联网,这怎么破解,完结
继续分析
正当我一筹莫展的时候,突然想到既然我不能通过生成注册码的方式激活,那能不能直接绕过激活,直接就是已激活的状态呢
接着前文分析,在 ActiveOffline
函数中,注意到当注册码校验成功之后,会给 IsActivation
赋值为true
PersionVersionEncryptModuleEntry.IsActivation = true;
定位到 IsActivation
的位置
可以看到,基本都是通过这个变量确定是否激活,包括公共变量 IsActivationed
也是读取该变量
至此,我们的目标就是想办法修改 Register.UI.dll
,使得 get IsActivation
时的值始终为True
反编译&重编译
一开始,看到dotpeek可以直接导出C#源码,我就直接导出了。
但是由于我完全不会C#,visual studio打开项目之后一堆报错,好不容易把报错消完了,编译出来的还跑不了(┬┬﹏┬┬)
后来在网上搜索.NET反编译的原理时了解到,反编译时其实是先把dll转为IL代码,再把IL代码转换成C# (应该没理解错吧)
那既然C#跑不通,那就试试底层一点的IL代码,还不用处理各种依赖关系
在dotPeek中刚好可以对照着看IL代码,非常方便,从 windows -> IL viewer
打开
嗯,很好,看不懂一点 无所谓,直接把IL扔给LLM
GPT真好用
现在的步骤就很明确了:
- 反编译
Register.UI.dll
为IL代码
- 修改IL代码,将
ldsfld bool Wuyou.Exam.Encrypt.PersionVersionEncryptModuleEntry::'<IsActivation>k__BackingField'
改为 ldc.i4.1
- 重新编译为dll
- 重新加密dll并替换
实践
使用ildasm反编译
.\ildasm.exe /UTF8 ./Register.UI.dec.dll /out=Register.UI.il
修改IL
重编译
.\ilasm.exe .\Register.UI.il /output=test.dll /dll
补上MD5,重新加密
import cryptography
from cryptography.hazmat.primitives.ciphers import algorithms
from cryptography.hazmat.primitives.ciphers import modes, Cipher
import hashlib
def encrypt_file(file_data: bytes, key: bytes) -> bytes:
padding_data = hashlib.md5(file_data).digest()
cipher = Cipher(algorithms.AES128(key), modes.ECB())
encryptor = cipher.encryptor()
encrypted_data = encryptor.update(file_data+padding_data) + encryptor.finalize()
return encrypted_data
with open("./Exam.exe", 'rb') as f:
file_data = f.read()
md5_hash = hashlib.md5(file_data).digest()
with open("./Register.UI.dll", "wb") as f:
with open("./test.dll", "rb") as f2:
f.write(encrypt_file(f2.read(), md5_hash))
替换掉原来的 Register.UI.dll
,测试成功
后记
第一次成功破解软件,成就感满满~~。虽然文章写得挺顺利的,但是前前后后还是了折腾三天,走了不少弯路😂😂😂。浅浅记录了一下,不当之处还请大佬们指正。