本帖最后由 Redmaplesoka 于 2025-3-8 22:20 编辑
记录破解某灰产软件
昨天去闲鱼搞了一单,买家给了我一个破解版和原版。破解版是数字加固,原版是梆梆加固。买家说要二次注入圈钱,于是我优先考虑搞原版。
原版分析
脱壳梆梆加固相信已经是基本操作,各种工具(如反射)都可以脱,脱完改入口再用np的加强版去签即可。脱修后打开如图所示,不输入内容,显示“请输出激活码.”。
于是我们定位这个字符串,在 com.hongbaodadui.主页面 出现
另外,为啥这个人喜欢用中文呢?好家伙,项目结构赫然出现com.e4a.runtime。其实,这是一款名叫易安卓的中文安卓程序开发平台,与易语言类似。易安卓实现了一堆工具类,还包含一些特别抽象的自实现类:
ok打不死的小强类库应该是与后台保活有关的。这命名方式也是绝了。我们继续分析验证激活码部分,跳转:
具体来说,就是提交这些数据来绑定卡密(Reg):注册码内容、软件编号、机器码、随机数、还有一个Sign。Sign是什么呢,如果是应用签名,我们需要进行替换来让联网部分正常运行,分析发现,就是传输密码的值去取md5.传输密码是什么呢?查找调用发现:
明文。继续分析,可以看到 多线程1 是接收联网验证任务的实例,它可能被挂载了事件,在请求完成后运行解锁。我们定位一下:
粗箭头指示它的创建。可以看到,它继承多线程Impl这个接口。细箭头指示它被挂载的事件。为什么是字符串呢?我们查找实现。
再查看registry。
大致可以看出,它将把”实例名$第三个参数字符串“这个函数挂载到实例上。对于我们的多线程1,它应该是对应“多线程1$发送网络数据完毕”这个函数。求证一番:
完美。我们看看错误信息处理中会发生什么:
还是完美!错误的注册码,提示的内容与上述字符串一致。我们只需要改变if结构即可。
去除这两处的if。运行,准备结单。但是!程序显示未知错误,然后立即退出。我们继续分析:
大致可以看出,程序收到的返回值还含有一些其他参数,显示未知错误,是因为分割出来的数组不足4个元素。看来,还需要给出正确的服务器数据才行。但是,我们没有vip,无法获取这些数据。不过,我们不是还有破解版吗?破解者一定也遇到了同样的问题,并一定也会内置数据,这是最简单的解法。
破解版分析
好。破解版是360加固,我们使用工具脱出dex,希望数据字符串并不在onCreate中,因为native化的函数我还不会还原。接下来,我们搜索“|“这个符号。
发现这个可疑数据。它和我们要找的十分相似,来看看:
完全一致。我们只需照葫芦画瓢,替换传入参数即可。
一些探索
不过,这一大坨是啥呢?可以看到,它被存在了 公用模块.静态数据 中,查找调用:
最可疑的是下面两个,右边那个像极了密钥,我们看看是什么:
它貌似要执行js,并以数据和”密钥“为参数。那么,AES_Decrypt就是函数名吧!我们看看d.txt这个文件是什么:
的确是js,我们也找到了AES_Decrypt。发现是aes解密,向量为空,CBC,pkcs7对齐。
解密出这一坨。还记得调用的第三个吗?用*分割字符串,我们看看:
没错,*前的是加密数据,后面是密钥,输入工具看看:
解密出了服务器地址和一些选项相关的字符,以及一些目标的官网。还记得吗?上面第二个用$分割字符串的调用,我们看看是什么:
是后台服务操作这个类对它的预处理,给到str这个数组中。看看str这个数组的调用
最后一个貌似用到了我们的服务器地址,我们看看:
之前我试过直接访问这个地址,报方法不对,那么它应该是接受post请求,用于验证码图片识别。具体我就不赘述了,这个服务器其实就挂了一个识别服务端,服务端源码是这个:
[Python] 纯文本查看 复制代码
import uvicorn
from fastapi import FastAPI, Body
import base64
import ddddocr
app = FastAPI(title='StupidOCR - 开发者文档', description='代码编写:81NewArk',version="1.0.2")
@app.post("/api.Image_to_Text", summary='识别图片内文字', description='普通图片验证码识别,上传图片的Base64编码', tags=['图片验证码识别'])
def OcrImageBase64(ImageBase64: str = Body(..., title='验证码图片Bse64文本', embed=True)):
base64_data = base64.b64decode(ImageBase64)
ocr = ddddocr.DdddOcr(show_ad=False)
res = ocr.classification(base64_data)
return {"result": res,
"Blog":"removed for 52pojie"}
@app.post("/api.Image_to_Arithmetic", summary='识别算数验证码', description='算术题验证码识别,上传图片的Base64编码,提供两个返回,自行取值分割文本并识别',tags=['图片验证码识别'])
def OcrImageBase64(ImageBase64: str = Body(..., title='验证码图片Bse64文本', embed=True)):
base64_data = base64.b64decode(ImageBase64)
ocr = ddddocr.DdddOcr(show_ad=False)
res = ocr.classification(base64_data)
if "+" or '-' or 'x' or '/' not in res:
zhi="Calculation error"
if '+' in res:
zhi = int(res.split('+')[0]) + int(res.split('+')[1][:-1])
if '-' in res:
zhi = int(res.split('-')[0]) - int(res.split('-')[1][:-1])
if 'x' in res:
zhi = int(res.split('x')[0]) * int(res.split('x')[1][:-1])
if '/' in res:
zhi = int(res.split('/')[0]) / int(res.split('/')[1][:-1])
return {"solution_result": zhi,
"raw_result":res,
"Blog":"removed for 52pojie"
}
@app.post("removed for 52pojie", summary='欢迎关注作者的博客', description='求一键三连',tags=['作者:Niuer-Pepsi'])
def Niuer():
return{"Blog":"removed for 52pojie"}
if __name__ == '__main__':
print("")
print("")
print(" _____ _ _ ____ _____ _____ ")
print(" / ____| | | (_) | | / __ \ / ____| | __ \ ")
print(" | (___ | |_ _ _ _ __ _ __| | | | | | | | | |__) |")
print(" \___ \ | __| | | | | | '_ \ | | / _` | | | | | | | | _ / ")
print(" ____) | | |_ | |_| | | |_) | | | | (_| | _ | |__| | | |____ | | \ \ ")
print(" |_____/ \__| \__,_| | .__/ |_| \__,_| (_) \____/ \_____| |_| \_/")
print(" | | ")
print(" |_| ")
print("")
print("")
print(" 开发者文档:http://127.0.0.1:6688/docs ")
print(" 项目依赖:FastAPI+ Uvicorn + DDDDOCR ")
print("")
print(" 乐乎:Niuer-Pepsi ")
print(" 代码编写:81NewArk ")
print("")
print("")
print("")
print("")
uvicorn.run(app, port=6688, host="127.0.0.1")
结语
至此,该软件的分析就告一段落了。但等我发结果时,十分凑巧,在一个我在的技术群里,看到这个买家,正拿着我脱修好给他看的半成品安装包(此时他还没付钱)去找人帮忙做完,为什么我确定是他呢,因为那个人的状态栏和他发我的截图一模一样。另外,他描述的这个安装包的异常和他反馈给我的也一样(因为去签用错了,导致在安卓15闪退)。于是这单我就不要了,臭骂他一顿之后,将他拉黑了事。希望大家在技术变现时要多加小心,害人之心不可有,防人之心不可无。
|