文章目录[隐藏]
android 逆向 13 / 38
- app OAuth api_sign 分析
- app sig 参数加密分析 unidbg 模拟黑盒调用
- app sign so 加密参数破解|unidbg
- sgmain x-sign 分析 - unidbg
- androidAsync fridaManager sgmain 70102 rpc 远程调用
- app edata 参数 so aes 加密分析破解|unidbg
- frida 加载 sekiro dex 文件 实现与服务端交互
- frida sekiro 实现 sgmain 70102 远程 rpc 调用
- xposed sekiro hook 获取 wx 万能 key
- unidbg console debugger 使用
- unidbg hook inline hook 使用
- app 公众号文章列表 so 加解密算法分析还原 | 简单分析
- app 公众号文章列表 so 加解密算法分析还原 | 加密 rsa base64 分析
- app 公众号文章列表 so 加解密算法分析还原 | 加密 zip aes 分析
- app 公众号文章列表 so 加解密算法分析还原 | response 内容解密分析
- app sign so 加密算法分析还原|简单分析
- app sign so 加密算法分析还原|so 算法分析
- app sign so 加密算法分析还原|so sub_126AC 函数算法还原
- app so signkeyV1 参数分析
- ida 动态调试 android so 文件|基础入门环境搭建
- app so newSign 参数分析破解
- app tzRgz52a 参数分析破解
- app sign-v2 签名算法 aes 加解密分析
- app so 加密参数分析|protocbuf 分析
- mxtakatak android app 加解密分析
- android app so 加密算法分析破解|mtgsig unidbg
- android app so 加密算法分析破解|siua unidbg
- android app nsign so 加密算法分析
- android app sig 参数 so 加密逻辑逆向分析
- android app so sig 加密参数 unidbg
- 狗狗音乐登陆协议加密参数逆向分析
- android sign so 加密参数分析|unidbg
- android app X-SS-QUERIES 参数分析
- unidbg android app xgorgon 加密参数 leviathan
- sgmain 6.4.x xsign 加密算法分析研究
- sgmain 6.4.x xminiwua 加密算法分析研究
- 某 app mas 算法分析还原 cms so
- 某东登陆协议 tlv 逻辑分析
仅供学习研究 。请勿用于非法用途,本人将不承担任何法律责任。
const 龙哥 = Function() {}
const a = 全能的傻宝,每天都会换一种姿势来分享各种操作,最近 10 月在分享密码学;
const b = 点击加入星球;
return "无敌的龙哥";
前言
想学习
unidbg android逆向 密码学 算法还原
的小伙伴可以call 龙哥 ();
接着上一篇文章分析,本次来分析下rsa base64
的加密逻辑
0x1
上一篇文章分析到了
so
的静态注册逻辑
也就是这里点进去
一共五个参数,前两个是默认的,分别是 JNIEnv jObject or jClass
,后面三个就是我们传进来的
上面是做了一些字符串初始化然后调用了 j_Sc_EncryptWallEncode
这个函数,点进去看看
进来之后有三个函数需要我们关注,前两经过分析都不是很重要,主要分析最后一个
要感谢代码符号没去掉,才能看到里面密密麻麻的算法
在往下分析,就看到我们熟悉字符串,不正是前面请求包的请求参数吗,这里就是全部算法的加密逻辑了
0x2
里面的算法很多,这次就来分析下,rsa 跟 base64
rsa
前面是一些常规的判断赋值操作
v10 = operator new(48u);
这一行就是创建一个大小 48字节 的内存,v10 就只内存地址
EncryptWall::WallKey::WallKey(v10);
这里调用一个函数,把内存地址进去,点进去看看
EncryptWall::WallKey::WallKey
点进来逻辑也比较简单,两个 do while
一共循环 48 次,刚好把 48字节大小的 内存填空
linux 下的 lrand48()
函数
随机生成0 - 2 ^ 31
之间的长整数
Tips: 继续往下
v12 = RSA_Encrypt(v10 + 16, 32u, &v60, &v59);
这里就是调用rsa
加密函数,四个参数分别是v10 的首地址加上 16
,32数字
,v60 的地址
,v59 的地址
RSA_Encrypt
n_crypto::SetSignPubKey
这里是生成public_key
,模数,指数都传进去了
n_crypto::PublicEnc(v8, v9, v6, &v11, v4);
调用这个函数开始加密,一共有五个参数
分别是1:32字节的地址
,2:32数字
,3:128字节大小的内存
,4:内存地址
,5:80字节大小的内存地址
Tips: rsa 分析结束
base64Encode
这里就是对 rsa
的加密结果,再来一层 base64
编码,稍后可以验证下是否是标准的 base64
0x3
算法分析的差不多了,在使用
unidbg 的 console debugger 跟 hook
功能,验证下数据,不熟悉的可以看下上面的推荐文章
unidbg unicorn inline hook
先
EncryptWall::WallKey::WallKey
函数看看生成的啥数据
public void hookUnicornWallKey() {
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void onAttach(Unicorn.UnHook unHook) {
}
@Override
public void detach() {
}
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB332)) {
System.out.println("Hook By Unicorn hookUnicornWallKey");
RegisterContext ctx = emulator.getContext();
Pointer input1 = ctx.getPointerArg(0);
Inspector.inspect(input1.getByteArray(0, 0x100), " 参数1");
}
if (address == (module.base + 0xB336)) {
RegisterContext ctx = emulator.getContext();
Inspector.inspect(ctx.getPointerArg(0).getByteArray(0, 0x100), " Unicorn hook hookUnicornWallKey");
}
}
}, module.base + 0xB332, module.base + 0xB336, null);
}
运行结果可以看到,刚好是 48字节 的数据
接着分别
hook rsa base64
函数
public void hookUnicornRsa() {
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void onAttach(Unicorn.UnHook unHook) {
}
@Override
public void detach() {
}
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB34E)) {
RegisterContext ctx = emulator.getContext();
Pointer input1 = ctx.getPointerArg(0);
Inspector.inspect(input1.getByteArray(0, 0x100), " hookUnicornRsa 参数1");
}
if (address == (module.base + 0xB352)) {
RegisterContext ctx = emulator.getContext();
Inspector.inspect(ctx.getPointerArg(0).getByteArray(0, 0x100), " Unicorn hook hookUnicornRsa");
}
}
}, module.base + 0xB34E, module.base + 0xB352, null);
}
public void hookUnicornBase64Encode() {
emulator.getBackend().hook_add_new(new CodeHook() {
@Override
public void onAttach(Unicorn.UnHook unHook) {
}
@Override
public void detach() {
}
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB372)) {
RegisterContext ctx = emulator.getContext();
Pointer input1 = ctx.getPointerArg(0);
Inspector.inspect(input1.getByteArray(0, 0x100), " hookUnicornBase64Encode 参数1");
}
if (address == (module.base + 0xB376)) {
RegisterContext ctx = emulator.getContext();
Inspector.inspect(ctx.getPointerArg(0).getByteArray(0, 0x100), " Unicorn hook hookUnicornBase64Encode");
}
}
}, module.base + 0xB372, module.base + 0xB376, null);
}
代码写完跑起来
rsa
的第一个参数,是 32 个字节,也就是前面随机生成 48 字节数据的后 32个字节数据,返回值是 128 个字节
base64
的第一个参数,刚好是前面rsa
的返回值
使用
CyberChef
网站来验证,是否是标准的base64
,结果不出所料,就是标的
最后
rsa base64
就分析完了,下一篇文章在分析zip + aes
算法