android 逆向 34 / 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 逻辑分析
前言
libmcs leviathan 函数获取 xg 加密函数
app 版本: 11.5.0。unidbg 版本:0.9.7
Tips
本文内容参考了,龙哥星球的 td
案例
java
层就不分析了直接开始今天的主题,native
函数在 com.ss.sys.ces.a
frida hook
function hook() {
var aCls = Java.use('com.ss.sys.ces.a');
aCls.leviathan.implementation = function (a, b, c) {
printLog('aCls.leviathan.a: ', a);
printLog('aCls.leviathan.b: ', b);
printLog('aCls.leviathan.c: ', c);
printLog('aCls.leviathan.c: ', bytes2Hex(c));
var res = this.leviathan(a, b, c);
printLog('aCls.leviathan.res: ', res);
printLog('aCls.leviathan.res: ', bytes2Hex(res));
return res;
}
aCls.meta.implementation = function (a, b, c) {
printLog('aCls.meta.a: ', a);
printLog('aCls.meta.b: ', b);
printLog('aCls.meta.c: ', c);
var res = this.meta(a, b, c);
printLog('aCls.meta.res: ', res);
return res;
}
aCls.decode.implementation = function (a, b) {
printLog('aCls.decode.a: ', a);
printLog('aCls.decode.b: ', b);
printLog('aCls.decode.b: ', bytes2Hex(b));
var res = this.decode(a, b);
printLog('aCls.decode.res: ', res);
printLog('aCls.decode.res: ', bytes2Hex(res));
return res;
}
aCls.encode.implementation = function (a) {
printLog('aCls.encode.a: ', a);
printLog('aCls.encode.a: ', bytes2Hex(a));
var res = this.encode(a);
printLog('aCls.encode.res: ', res);
printLog('aCls.encode.res: ', bytes2Hex(res));
return res;
}
}
function main() {
Java.perform(function () {
hook();
})
}
setImmediate(main);
清楚 dy app
全部数据,使用 frida spwan
模式启动
unidbg
run unidbg
package com.qinless.douyin.v1150;
import com.androidFrameWork.*;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.file.FileResult;
import com.github.unidbg.file.IOResolver;
import com.github.unidbg.file.linux.AndroidFileIO;
import com.github.unidbg.linux.android.AndroidARMEmulator;
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 com.github.unidbg.memory.SvcMemory;
import com.github.unidbg.unix.UnixSyscallHandler;
import com.github.unidbg.virtualmodule.android.AndroidModule;
import java.io.File;
import java.io.IOException;
public class LibCmsTest extends AbstractJni implements IOResolver<AndroidFileIO> {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
public DvmClass AClass;
public String apkPath = "/Volumes/T7/android/android-file/douyin-11.5.0.apk";
public LibCmsTest() {
AndroidEmulatorBuilder builder = new AndroidEmulatorBuilder(false) {
@Override
public AndroidEmulator build() {
return new AndroidARMEmulator(processName, rootDir, backendFactories) {
@Override
protected UnixSyscallHandler<AndroidFileIO> createSyscallHandler(SvcMemory svcMemory) {
return new DyARM32SyscallHandler(svcMemory);
}
};
}
};
emulator = builder.setRootDir(new File("target/douyin-1150-test")).build();
final Memory memory = emulator.getMemory();
memory.setLibraryResolver(new AndroidResolver(23));
emulator.getSyscallHandler().addIOResolver(this);
vm = emulator.createDalvikVM(new File(apkPath));
vm.setVerbose(true);
memory.addModuleListener(new hookImports(emulator, "libcms.so", "unidbg-android/src/test/resources/douyin/files/imports.txt"));
new AndroidModule(emulator, vm).register(memory);
emulator.getSyscallHandler().setEnableThreadDispatcher(true);
DalvikModule dm = vm.loadLibrary("cms", true);
vm.setJni(this);
module = dm.getModule();
dm.callJNI_OnLoad(emulator);
AClass = vm.resolveClass("com/ss/sys/ces/a");
}
public static void main(String[] args) {
LibCmsTest libCms = new LibCmsTest();
libCms.destroy();
}
private void destroy() {
try {
emulator.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public FileResult<AndroidFileIO> resolve(Emulator<AndroidFileIO> emulator, String pathname, int oflags) {
System.out.println("pathname: " + pathname);
return null;
}
}
老规矩架子先搭建起来
这里使用了自定义的 SyscallHandler
主要是处理了下 unidbg
未实现/实现不完善的函数(代码来自龙哥星球 td 案例)
还有 hook patch
逻辑(代码来自龙哥星球 td 案例)
跑起来
第一次运行发现程序卡住了,这时不用管,咱们先把需要的文件给补起来 /dev/__properties__, /proc/stat
这两个文件也是需要补的,直接复制手机里的即可
补完之后就可正常运行了
然后开始调用 meta native
函数,这是我 frida hook
的结果,需要调用
call meta
public void callMeta() {
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 102),
vm.resolveClass("android/content/Context").newObject(null),
vm.resolveClass("java/lang/Object").newObject(1128)
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 101),
null,
vm.resolveClass("java/lang/Object").newObject(255)
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 1020),
null,
vm.resolveClass("java/lang/Object").newObject("")
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 105),
null,
vm.resolveClass("java/lang/Object").newObject(110501)
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 106),
null,
vm.resolveClass("java/lang/Object").newObject("com.ss.android.ugc.aweme")
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 107),
null,
vm.resolveClass("java/lang/Object").newObject("com.ss.android.ugc.aweme")
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 108),
null,
vm.resolveClass("java/lang/Object").newObject("/data/app/com.ss.android.ugc.aweme/base.apk")
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 109),
null,
vm.resolveClass("java/lang/Object").newObject("/storage/emulated/0")
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 110),
null,
vm.resolveClass("java/lang/Object").newObject("/data")
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 101),
null,
vm.resolveClass("java/lang/Object").newObject(0)
);
AClass.callStaticJniMethodObject(
emulator, "meta(ILandroid/content/Context;Ljava/lang/Object;)Ljava/lang/Object;",
DvmInteger.valueOf(vm, 100),
vm.resolveClass("android/content/Context").newObject(null),
vm.resolveClass("java/lang/Object").newObject(294)
);
}
然后运行,在补两个环境即可
call leviathan
然后开始调用 leviathan native
函数
public void callLeviathan() {
DvmObject<?> ret = AClass.callStaticJniMethodObject(
emulator, "leviathan(II[B)[B",
DvmInteger.valueOf(vm, -1),
DvmInteger.valueOf(vm, 1647670270),
new ByteArray(vm, QLUtils.hexToByteArray("3270d9629da3616f34db087c591628a3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"))
);
System.out.println(QLUtils.bytesToHexString((byte[]) ret.getValue()));
}
跑起来,然后就开始正常补环境即可
中间会遇到这个问题,不要慌,往上翻
可以看到里有读取文件夹,但是我们并没有处理这个所以报错(该问题也是请教了大佬)把这个补上即可。当然其他的读取文件也都一并补一下
这里一共补了四个
/data/data/com.ss.android.ugc.aweme/files/assets.czl
这个也不知道干啥的,不补就不行很奇怪,补上之后在运行就成功了,继续补 jni
环境
遇到这个错误时重载 java/io/File->getAbsolutePath()Ljava/lang/String;
函数返回正确的数据就行了
最后补完之后结果也是出来(博主没有测试过是否可用)
nick
2022-09-10什么是 QLContext? 你可以分享它的实现吗?