sgmain x-sign 分析 - unidbg

android 逆向 4 / 37

仅供学习研究 。请勿用于非法用途,本人将不承担任何法律责任。

前言

apk 版本, 某猫 8.11.0, 本次主要说分析下如何使用 unidbg 跑通 x-sign,博主也是初学者,有啥问题可以加博主一起讨论哈,非常欢迎

charles 数据包分析

1-charles-01

主要分析这个 x-sign,知道目标后,直接开始使用 unidbg

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 不全,比较容易出问题

libsgmainso

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 函数里调用一下,开始运行

2-idea-01

3-idea-02

这里就开始报常见的环境错误了, 我们给他加上

4-idea-03

5-idea-04

这里继续,返回 apkbase.apk 路径

6-idea-05

7-idea-06

这里连续报的两个错误,可以统一处理,返回 files 文件夹路径

8-idea-07

这里需要返回 apk 的 native lib/arm 路径

9-idea-08

这个是 sgmain 抛异常的类,我们需要把 msg code 打印下,看看报了啥错误

10-idea-09

继续执行,果然报错了 code = 123。这里查找错误原因有两种,第一种是 百度搜索 阿里聚安全 123 是啥错误,第二种是自己查看 log 日志,猜测试错。过程还是比较坑的,我这里踩了很多坑,就直接说答案吧是缺少了文件。具体缺少啥文件,搜索 resolve.pathname: 这个字眼,不知道补哪些就能补的都补下

11-idea-10

我这里是补了左侧的几个文件,跟 base.apk,文件就在手机里对应的目录下,pull 下来就行,运行后发现不再报 123 错误了

12-idea-11

这里报了两个错误,可以一起补

13-idea-12

14-idea-13

中间又补了几个错误之后,这里是读取文件里的 json 内容,因为是固定的我就直接取出来了,这个补完之后再补一个常见的就 OK

15-idea-14

这里算是 sgmain 就补完了,全都正常返回了 0,这个结果我是 frida call 出来的结果

libsgsecuritybodyso

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 函数里调用

16-idea-15

17-idea-16

18-idea-17

上图都是执行结果却啥补啥,就行

19-idea-18

20-idea-19

补到最后报了个指针错误,因为啥也不知道,还是使用相同的方法补文件,经过测试补 dev/__properties__ 即可,继续运行,OK

libsgavmpso

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());
}

这个比较简单,跟上诉逻辑差不多,就不说了,缺啥补啥

get x-sign


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());
}

21-idea-20

22-idea-21

23-idea-22

24-idea-23

上图环境报错全部补完之后,就可以出结果了,经过测试,这个结果是可以使用的


想学习 unidbg 的伙伴,可点击加入星球,星主是一位全能的傻宝,每天都会分享各种姿势骚操作

16 条评论
本文作者:
本文链接: https://www.qinless.com/?p=179
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 qinless 的博客!
100

16 条评论

rookie

在执行initMain 失败 加载 libsgmain so文件 unidbg版本问题?

D:\application\jdk8\bin\java.exe "-javaagent:D:\application\ideaIU\IntelliJ IDEA 2019.2\lib\idea_rt.jar=59884:D:\application\ideaIU\IntelliJ IDEA 2019.2\bin" -Dfile.encoding=UTF-8 -classpath D:\application\jdk8\jre\lib\charsets.jar;D:\application\jdk8\jre\lib\deploy.jar;D:\application\jdk8\jre\lib\ext\access-bridge-64.jar;D:\application\jdk8\jre\lib\ext\cldrdata.jar;D:\application\jdk8\jre\lib\ext\dnsns.jar;D:\application\jdk8\jre\lib\ext\jaccess.jar;D:\application\jdk8\jre\lib\ext\jfxrt.jar;D:\application\jdk8\jre\lib\ext\localedata.jar;D:\application\jdk8\jre\lib\ext\nashorn.jar;D:\application\jdk8\jre\lib\ext\sunec.jar;D:\application\jdk8\jre\lib\ext\sunjce_provider.jar;D:\application\jdk8\jre\lib\ext\sunmscapi.jar;D:\application\jdk8\jre\lib\ext\sunpkcs11.jar;D:\application\jdk8\jre\lib\ext\zipfs.jar;D:\application\jdk8\jre\lib\javaws.jar;D:\application\jdk8\jre\lib\jce.jar;D:\application\jdk8\jre\lib\jfr.jar;D:\application\jdk8\jre\lib\jfxswt.jar;D:\application\jdk8\jre\lib\jsse.jar;D:\application\jdk8\jre\lib\management-agent.jar;D:\application\jdk8\jre\lib\plugin.jar;D:\application\jdk8\jre\lib\resources.jar;D:\application\jdk8\jre\lib\rt.jar;D:\work\workspace_ideaIU\unidbg-master-20220311\unidbg-android\target\test-classes;D:\work\workspace_ideaIU\unidbg-master-20220311\unidbg-android\target\classes;D:\work\workspace_ideaIU\unidbg-master-20220311\unidbg-api\target\classes;C:\Users\rookie\.m2\repository\com\github\zhkl0228\unicorn\1.0.12\unicorn-1.0.12.jar;C:\Users\rookie\.m2\repository\org\scijava\native-lib-loader\2.3.5\native-lib-loader-2.3.5.jar;C:\Users\rookie\.m2\repository\com\github\zhkl0228\capstone\3.1.6\capstone-3.1.6.jar;C:\Users\rookie\.m2\repository\net\java\dev\jna\jna\5.10.0\jna-5.10.0.jar;C:\Users\rookie\.m2\repository\com\github\zhkl0228\keystone\0.9.7\keystone-0.9.7.jar;C:\Users\rookie\.m2\repository\commons-codec\commons-codec\1.15\commons-codec-1.15.jar;C:\Users\rookie\.m2\repository\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar;C:\Users\rookie\.m2\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0.jar;C:\Users\rookie\.m2\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;C:\Users\rookie\.m2\repository\com\alibaba\fastjson\1.2.79\fastjson-1.2.79.jar;C:\Users\rookie\.m2\repository\com\github\zhkl0228\demumble\1.0.3\demumble-1.0.3.jar;C:\Users\rookie\.m2\repository\net\dongliu\apk-parser\2.6.10\apk-parser-2.6.10.jar;D:\work\workspace_ideaIU\unidbg-master-20220311\backend\dynarmic\target\classes;D:\work\workspace_ideaIU\unidbg-master-20220311\backend\hypervisor\target\classes;D:\work\workspace_ideaIU\unidbg-master-20220311\backend\kvm\target\classes;D:\work\workspace_ideaIU\unidbg-master-20220311\backend\unicorn2\target\classes;C:\Users\rookie\.m2\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;C:\Users\rookie\.m2\repository\junit\junit\4.13.2\junit-4.13.2.jar;C:\Users\rookie\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\rookie\.m2\repository\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;C:\Users\rookie\.m2\repository\org\slf4j\slf4j-reload4j\1.7.36\slf4j-reload4j-1.7.36.jar;C:\Users\rookie\.m2\repository\ch\qos\reload4j\reload4j\1.2.19\reload4j-1.2.19.jar com.tianmiao_x.TianMaoXSign1
22222222222222
0123:80-75-3-4
Exception in thread "main" net.fornwall.jelf.ElfException: Bad magic number for file
at net.fornwall.jelf.ElfFile.(ElfFile.java:272)
at net.fornwall.jelf.ElfFile.fromBytes(ElfFile.java:259)
at com.github.unidbg.linux.AndroidElfLoader.loadInternal(AndroidElfLoader.java:317)
at com.github.unidbg.linux.AndroidElfLoader.loadInternal(AndroidElfLoader.java:176)
at com.github.unidbg.linux.AndroidElfLoader.loadInternal(AndroidElfLoader.java:63)
at com.github.unidbg.spi.AbstractLoader.load(AbstractLoader.java:219)
at com.github.unidbg.linux.android.dvm.BaseVM.loadLibrary(BaseVM.java:307)
at com.tianmiao_x.TianMaoXSign1.initMain(TianMaoXSign1.java:91)
at com.tianmiao_x.TianMaoXSign1.main(TianMaoXSign1.java:129)

Process finished with exit code 1

回复

会爬山的小脑虎

@rookie 你这错误有点看不懂,没遇到过

回复

SkyDancer

Btw, Did you try to get wua or mini-wua? I emulated everything the library wants in the log every file\directory and also every syscall like string\int\long but still cant get correct data:
Somehow the length is wrong Have no clue why it can't generate wua with correct length

Here what I get on JNICLibrary.callStaticJniMethodObject(emulator, NativeMethod, 20102.....
HHnB_dhPopjlThIqMVdNrXyXDkIe8m1rOla4TBivMj6hiuQ0=

But it has to be much longer, Did you manage to get correct wua\mini-wua?

回复

SkyDancer

Ohh, Finally found my issue, somehow the issue was in my SDK version (23), no clue why I didn't work but now all is fine 🙂
https://user-images.githubusercontent.com/13561846/154678721-6babb5cd-68c5-43be-b5a1-e3a7d36212b8.png

回复

SkyDancer

Like How to resolve paths errors like "resolve.pathname: /data/user/0/com.testsignso/app_SGLib/app_1645089519" this part? When I try to resolve this I have SecException Code 199. I'm almost sure the problem is about the paths, because when I try to send FileIO, from my path like this "/data/user/0/com.testsignso/app_SGLib", the unidbg reads the folder but sends "failResult" this framework can't read folders or what? How to resolve foleer not a file? Also how to resolve file from undbg linus path like this"?

回复

SkyDancer

Hi, I have some issues with some part of the resolving on the paths, can I contact somehow with the author?

回复

czw

吊吊吊

回复

会爬山的小脑虎

@czw 大佬谦虚了

回复

tkan

大佬,为啥 我 __properties__ 是一个文件 ,我看你是 文件夹下面 好多文件,还有 initMain xiayu, initMain.ret-10101: 一直卡着 [ libc.so] [0x17508] [ 00 f0 20 e3 ] 0x40199508: nop , xiayu, initMain.ret-10102: 能执行成功。

回复

会爬山的小脑虎

@tkan 老哥,没太明白你的问题,可能是哪里操作有误,方便的话可以到关于页面,加微信讨论

回复

Shanks

dev/__properties__ 大佬这个文件怎么补啊? adb pull 不下来

回复

会爬山的小脑虎

@Shanks 文件夹先复制到 sdcard 目录,在 pull

回复

123

老哥,emulator.set("inode", iNode) INode里put的路径和数字是什么东西

回复

会爬山的小脑虎

@123 这个是 linux 系统文件的一些数据好像,具体我也不太清楚,没仔细研究过

回复

Entertainment

大佬 这个可以通用调用吗 支持不同的类型so吗

回复

会爬山的小脑虎

@Entertainment 可以的 unidbg 就是模拟 so 运行环境,可以执行 任意 so 文件

回复

发表评论

返回顶部