文章目录[隐藏]
android 逆向 26 / 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 逻辑分析
本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!
推荐阅读
本文样本来自 龙哥 csdn 参考链接: csdn 链接
更多 Unidbg 使用和算法还原的教程可见星球: 点击加入龙哥星球
前言
某团 android app mtgsig 参数分析,美食列表接口,版本 11.9.405
charles 抓包
就是它,本文主要分析 mtgsig
参数
java 层分析
反编译 apk
全局搜索 mtgsig
,有个赋值点过去,查找用例
这里有 hashMap.put
点过去
这里先是调用了 getBuilder
函数,猜测是获取 url
参数等,在调用 makeHeader
makeHeader
函数,前面是 url
处理,字符串拼接,调用 WTSign.makeHeader
获取结果
此函数又调用了 NBridge.main
函数
NBridge.main
是个 native
函数
libmtguard.so 文件查找
在上述的 NBridge.java
文件里,并没有看到有,so
文件的加载,那 native
函数是在哪个 so
呢
- 1、可以使用 frida 等工具来分析
- 2、可以参考别人文章的逻辑来分析
- 3、可以自己根据经验来分析
根据经验查找也有多种方式,这里就假设你已经阅读了龙哥 csdn
的文章,那就肯定知道 main
函数同时也是初始化函数,既然是初始化哪加载 so
的逻辑,估计也在一起,没错就直接查找 main
函数的交叉引用
有多个但 111
是初始化直接点过去,该逻辑是在 initNative
函数里,查看交叉引用,哪里调用的
在这里调用,如果细心点就会发现,上面有个 if
,根据名称可以猜测出来跟 so
相关,查看交叉引用
在 loadSo
函数里,有个 System.loadLibrary
逻辑,加载成功就 isLoaded = true;
MTGConfigs.MTG
的值正是 mtguard
frida hook
function getProcessId() {
var androidProcess = Java.use('android.os.Process');
return 'processId: ' + androidProcess.myTid() + ' - ';
}
function hook() {
var javaString = Java.use('java.lang.String');
var NBridge = Java.use('com.meituan.android.common.mtguard.NBridge');
var WTSign = Java.use('com.meituan.android.common.mtguard.wtscore.plugin.sign.core.WTSign');
WTSign.makeHeader.implementation = function (a, b) {
console.log(getProcessId(), 'WTSign.makeHeader.a: ', a);
console.log(getProcessId(), 'WTSign.makeHeader.b: ', javaString.$new(a));
var res = this.makeHeader(a, b);
console.log(getProcessId(), 'WTSign.makeHeader.res: ', res);
return res;
}
NBridge.main.implementation = function (a, b) {
console.log(getProcessId(), 'NBridge.main.a: ', a);
console.log(getProcessId(), 'NBridge.main.b: ', b);
if (b.length === 3) {
console.log(getProcessId(), 'NBridge.main.b.0: ', b[0]);
console.log(getProcessId(), 'NBridge.main.b.1: ', b[1]);
console.log(getProcessId(), 'NBridge.main.b.2: ', b[2]);
} else {
for (var i = 0; i < b.length; i++) {
console.log(getProcessId(), 'NBridge.main.b.i: ', i, ' data: ', b[i]);
}
}
var res = this.main(a, b);
console.log(getProcessId(), 'NBridge.main.res: ', res);
for (var j = 0; j < res.length; j++) {
console.log(getProcessId(), 'NBridge.main.res.j: ', j, ' data: ', res[j]);
}
return res;
}
}
function main() {
Java.perform(function () {
hook();
})
}
setImmediate(main);
// frida -UF -l hook.js
// frida -UF -l hook.js | tee hook.log
使用 frida hook
一下,看看 main
函数的输入输出是啥
main
函数有两个参数
- 1、int 203
- 2、object array,1、固定的 key,2、url相关参数,3、int 数字
下面使用 unidbg
运行 main
函数
unidbg
package com.xiayu.meituan;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.LibraryResolver;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import java.io.File;
import java.io.IOException;
public class MtGsigTest extends AbstractJni {
private final AndroidEmulator emulator;
private final Module module;
private final VM vm;
private final DvmClass NBridge;
public String apkPath = "apkPath";
public String soPath = "soPath";
private static LibraryResolver createLibraryResolver() {
return new AndroidResolver(23);
}
private static AndroidEmulator createARMEmulator() {
return AndroidEmulatorBuilder
.for32Bit()
.build();
}
MtGsigTest() {
emulator = createARMEmulator();
final Memory memory = emulator.getMemory();
memory.setLibraryResolver(createLibraryResolver());
vm = emulator.createDalvikVM(new File(apkPath));
vm.setVerbose(true);
DalvikModule dm = vm.loadLibrary(new File(soPath), true);
vm.setJni(this);
dm.callJNI_OnLoad(emulator);
module = dm.getModule();
NBridge = vm.resolveClass("com/meituan/android/common/mtguard/NBridge");
}
public static void main(String[] args) throws IOException {
MtGsigTest mtGsig = new MtGsigTest();
mtGsig.destroy();
}
private void destroy() throws IOException {
emulator.close();
}
}
先把架子搭好,跑起来,没啥问题
call main 111
public void callMain111() {
DvmObject<?> strRc = NBridge.callStaticJniMethodObject(
emulator, "main(I[Ljava/lang/Object;)[Ljava/lang/Object;",
111,
new ArrayObject(vm.resolveClass("java/lang/object").newObject(null))
);
System.out.println("callMain111: " + strRc.getValue());
}
有了前面的分析经验,得知,需要先调用 main
初始化加载函数,跑起来
这里报了个错误,正常补环境即可,具体的值,可以使用 frida call
或者 jnitrace
获取
- 写文章之前博主已经补过一遍了,所以这里就直接贴上 frida hook 的代码
function call() {
var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
var context = currentApplication.getApplicationContext();
var PackageManager = context.getPackageManager();
var getPackageInfo = PackageManager.getPackageInfo('com.sankuai.meituan', 64);
var NBridge = Java.use('com.meituan.android.common.mtguard.NBridge');
console.log('NBridge.getDfpId : ', NBridge.getDfpId());
console.log('NBridge.getPicName : ', NBridge.getPicName());
console.log('NBridge.getSecName : ', NBridge.getSecName());
console.log('NBridge.getMtgVN : ', NBridge.getMtgVN());
console.log('PackageManager.GET_SIGNATURES: ', PackageManager.GET_SIGNATURES.value);
console.log('PackageInfo.versionCode : ', getPackageInfo.versionCode.value);
console.log('context.getPackageCodePath : ', context.getPackageCodePath());
}
中间省略一部分补环境逻辑。。。。。。
这个直接返回 apk
的路径即可,后面在补一些环境,即可成功,下面直接调用 main 203
call main 203
public void callMain203() {
DvmObject<?> strRc = NBridge.callStaticJniMethodObject(
emulator, "main(I[Ljava/lang/Object;)[Ljava/lang/Object;",
203,
new ArrayObject(
new StringObject(vm, "key"),
new ByteArray(vm, "url 参数".getBytes()),
DvmInteger.valueOf(vm, 2)
)
);
System.out.println("callMain203: " + ((DvmObject<?>[]) ((ArrayObject) strRc).getValue())[0]);
}
代码跑起来发现没问题,但是结果也没出来,肯定是有问题,查看 log
发现有读取文件,读的还是 apk
哪咱们就补一下这个文件
- 1
- 2
- 3
@Override
public FileResult<AndroidFileIO> resolve(Emulator<AndroidFileIO> emulator, String pathname, int oflags) {
System.out.println("resolve.pathname-11111: " + pathname);
if (("/data/app/com.sankuai.meituan-TEfTAIBttUmUzuVbwRK1DQ==/base.apk").equals(pathname)) {
return FileResult.<AndroidFileIO>success(new SimpleFileIO(oflags, new File(apkPath), pathname));
}
return null;
}
补完再次跑起来
这里又报了个错误,前面 frida call
出来了,直接加上
再次运行,就没啥问题了,结果也正常出来了
浩然
2022-03-09新版本使用unidbg 生成的a9 比app生成的短,有人遇到过这个问题吗
tofu
2022-01-27现在的sign 到a10了。请问你这文章的结果有a10吗。我hook出来只有到a6。用不了
会爬山的小脑虎
2022-01-27@tofu 那应该是版本的问题了,我这个是老版本的
tofu
2022-01-27@会爬山的小脑虎 可以知道一下你用的什么版本吗。下了好几个版本都没发现只有6位数的
会爬山的小脑虎
2022-01-27@tofu 具体我也忘记了,我记得好像是 10.x 的
于与禹
2022-01-08大佬,在步环境的时候,这种应该是android本身的一些东西吧,这个需要怎么补呀,Landroid/content/pm/PackageManager;->signatures:[Landroid/content/pm/Signature;,应该是一个数组
会爬山的小脑虎
2022-01-08@于与禹 对是的,返回这个环境的正确数据就可以了,