apk 版本, 天猫 8.11.0
, 本次主要说分析下如何使用unidbg
跑通x-sign
,博主也是初学者,有啥问题可以加博主一起讨论哈,非常欢迎
主要分析这个 x-sign
,知道目标后,直接开始使用 unidbg
具体的函数定位就不说了,各位看官应该都知道 JNICLibrary.doCommandNative
这个是 so
入口
package com.xiayu; import com.github.unidbg.AndroidEmulator; import com.github.unidbg.Emulator; import com.github.unidbg.LibraryResolver; 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.AndroidEmulatorBuilder; import com.github.unidbg.linux.android.AndroidResolver; import com.github.unidbg.linux.android.dvm.AbstractJni; import com.github.unidbg.linux.android.dvm.DvmClass; import com.github.unidbg.linux.android.dvm.DvmObject; import com.github.unidbg.linux.android.dvm.VM; import com.github.unidbg.memory.Memory; import com.github.unidbg.spi.SyscallHandler; import com.github.unidbg.virtualmodule.android.AndroidModule; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; public class TianMaoXSign1 extends AbstractJni implements IOResolver<AndroidFileIO> { private final AndroidEmulator emulator; private final VM vm; private long slot; public String sgMain = "unidbg-android/src/test/resources/test_so/tianmao8110/libsgmainso-6.4.156.so"; public String sgSecurityBody = "unidbg-android/src/test/resources/test_so/tianmao8110/libsgsecuritybodyso-6.4.90.so"; public String sgAvMp = "unidbg-android/src/test/resources/test_so/tianmao8110/libsgavmpso-6.4.34.so"; public String sgMisc = "unidbg-android/src/test/resources/test_so/tianmao8110/libsgmiscso-6.4.44.so"; public File sgMainFile = new File(sgMain); public File sgSecurityBodyFile = new File(sgSecurityBody); public File sgAvMpFile = new File(sgAvMp); public File sgMiscFile = new File(sgMisc); public String dataAppPath = "/data/app/com.tmall.wireless-NsaOVgz2fomXJNoPTrbOwg=="; public String packageName = "com.tmall.wireless"; public String methodSign = "doCommandNative(I[Ljava/lang/Object;)Ljava/lang/Object;"; public DvmClass JNICLibrary; public DvmObject<?> context; public DvmObject<?> ret; public String APK_INSTALL_PATH = dataAppPath + "/base.apk"; public File APK_FILE = new File("/Users/admin/Desktop/android/file/tianmao-8.11.0.apk"); private static LibraryResolver createLibraryResolver() { return new AndroidResolver(23); } private static AndroidEmulator createARMEmulator() { return AndroidEmulatorBuilder .for32Bit() .setRootDir(new File("appFile/tianmao-xsign1")) .setProcessName("com.tmall.wireless") .build(); } public TianMaoXSign1() { emulator = createARMEmulator(); Map<String, Integer> iNode = new LinkedHashMap<>(); iNode.put("/data/system", 671745); iNode.put("/data/app", 327681); iNode.put("/sdcard/android", 294915); iNode.put("/data/user/0/com.tmall.wireless", 655781); iNode.put("/data/user/0/com.tmall.wireless/files", 655864); emulator.set("inode", iNode); emulator.set("uid", 10074); Memory memory = emulator.getMemory(); memory.setLibraryResolver(createLibraryResolver()); SyscallHandler<AndroidFileIO> handler = emulator.getSyscallHandler(); handler.setVerbose(false); handler.addIOResolver(this); vm = emulator.createDalvikVM(APK_FILE); vm.setJni(this); vm.setVerbose(true); new AndroidModule(emulator, vm).register(memory); JNICLibrary = vm.resolveClass("com/taobao/wireless/security/adapter/JNICLibrary"); context = vm.resolveClass("android/content/Context").newObject(null); } public static void main(String[] args) throws IOException { TianMaoXSign1 tm2 = new TianMaoXSign1(); tm2.destroy(); } public void destroy() throws IOException { emulator.close(); } @Override public FileResult<AndroidFileIO> resolve(Emulator<AndroidFileIO> emulator, String pathname, int oflags) { System.out.println("resolve.pathname: " + pathname); return null; } }
这里先把框架搭起来,IOResolver<AndroidFileIO>
这个接口类可以直接使用 unidbg
的虚拟文件系统,方便补文件。运行,如果没啥错误就说明一切正常,继续下一步
下面开始对各个 so
进行初始化,具体的初始化流程,可以使用 frida hook
查看整体流程,使用 jnitrace
不全,比较容易出问题
public void initMain() { DalvikModule dm = vm.loadLibrary(sgMainFile, true); dm.callJNI_OnLoad(emulator); ret = JNICLibrary.callStaticJniMethodObject( emulator, methodSign, 10101, new ArrayObject( context, DvmInteger.valueOf(vm, 3), new StringObject(vm, ""), new StringObject(vm, "/data/user/0/" + packageName + "/app_SGLib"), new StringObject(vm, "") )); System.out.println("xiayu, initMain.ret-10101: " + ret.getValue().toString()); ret = JNICLibrary.callStaticJniMethodObject( emulator, methodSign, 10102, new ArrayObject( new StringObject(vm, "main"), new StringObject(vm, "6.5.156"), new StringObject(vm, "/data/user/0/com.tmall.wireless/app_SGLib/app_1627957761/main/libsgmainso-6.5.156.so") )); System.out.println("xiayu, initMain.ret-10102: " + ret.getValue().toString()); }
这里是初始化 sgmain
具体流程是 frida hook
的结果,写好后在 main
函数里调用一下,开始运行
这里就开始报常见的环境错误了, 我们给他加上
这里继续,返回 apk
的 base.apk
路径
这里连续报的两个错误,可以统一处理,返回 files
文件夹路径
这里需要返回 apk 的 native lib/arm
路径
这个是 sgmain
抛异常的类,我们需要把 msg code
打印下,看看报了啥错误
继续执行,果然报错了 code = 123
。这里查找错误原因有两种,第一种是 百度搜索 阿里聚安全 123
是啥错误,第二种是自己查看 log
日志,猜测试错。过程还是比较坑的,我这里踩了很多坑,就直接说答案吧是缺少了文件。具体缺少啥文件,搜索 resolve.pathname:
这个字眼,不知道补哪些就能补的都补下
我这里是补了左侧的几个文件,跟 base.apk
,文件就在手机里对应的目录下,pull
下来就行,运行后发现不再报 123
错误了
这里报了两个错误,可以一起补
中间又补了几个错误之后,这里是读取文件里的 json
内容,因为是固定的我就直接取出来了,这个补完之后再补一个常见的就 OK
了
这里算是 sgmain
就补完了,全都正常返回了 0
,这个结果我是 frida call
出来的结果
public void initSecurityBody() { DalvikModule securityBody = vm.loadLibrary(sgSecurityBodyFile, true); securityBody.callJNI_OnLoad(emulator); ret = JNICLibrary.callStaticJniMethodObject( emulator, methodSign, 10102, new ArrayObject( new StringObject(vm, "securitybody"), new StringObject(vm, "6.4.90"), new StringObject(vm, "/data/user/0/com.tmall.wireless/app_SGLib/app_1627957761/main/libsgsecuritybodyso-6.4.90.so") )); System.out.println("xiayu, initSecurityBody.ret-10102: " + ret.getValue().toString()); }
新增个函数,main
函数里调用
上图都是执行结果却啥补啥,就行
补到最后报了个指针错误,因为啥也不知道,还是使用相同的方法补文件,经过测试补 dev/__properties__
即可,继续运行,OK
了
public void initAvMp() { DalvikModule avMp = vm.loadLibrary(sgAvMpFile, true); avMp.callJNI_OnLoad(emulator); ret = JNICLibrary.callStaticJniMethodObject( emulator, methodSign, 10102, new ArrayObject( new StringObject(vm, "avmp"), new StringObject(vm, "6.4.34"), new StringObject(vm, "/data/user/0/com.tmall.wireless/app_SGLib/app_1627957761/main/libsgavmpso-6.4.34.so") )); System.out.println("xiayu, initAvMp.ret-10102: " + ret.getValue().toString()); }
这个比较简单,跟上诉逻辑差不多,就不说了,缺啥补啥
public void getXSign() { Map<String, String> map = new HashMap<>(); map.put("INPUT", "&&&231817&1c9d79ea8dd4bc56fb7a7727a30366&1629886&mtop.tmall.inshopsearch.searchitems&1.0&&231200@tmall_android_8.11.0&AnlJxyMxqqSURHlmKQRVnNJ8Y7la4LNiuKMrpD&&&27&&&&&&&"); DvmObject<?> ret = JNICLibrary.callStaticJniMethodObject( emulator, methodSign, 10401, new ArrayObject( vm.resolveClass("java/util/HashMap").newObject(map), new StringObject(vm, "23181017"), DvmInteger.valueOf(vm, 7), null, DvmBoolean.valueOf(vm, true) )); System.out.println("xiayu, getXSign.ret-10401: " + ret.getValue().toString()); }
上图环境报错全部补完之后,就可以出结果了,经过测试,这个结果是可以使用的