Unidbg模拟执行某段子so实操教程(二) LoadSo对比

简介: Unidbg模拟执行某段子so实操教程(二) LoadSo对比

一、目标


上篇文章里面,我们跑出来的结果有点不对头,多个一个 ABC


这次我们试试用 LoadSo的方式来排查下问题。


参考: [借鸡生蛋之SandHook的使用(一)]


二、步骤

我们先用Android Studio 4.0 来编译一个so


打开AS,然后用向导创建一个 Native C++ 工程。

28.png

然后创建 /xxx/app/src/main/jniLibs/armeabi-v7a 目录,把我们要分析的 libnet_crypto.so 复制进去


调用下试试


仿照 Jadx分析的结果,把 com.ixxixx.network.NetCrypto 类创建好

package com.ixxixxx.network;
public class NetCrypto {
    // static {
    public static void loadso(){
        try {
            System.loadLibrary("net_crypto");
        }catch(Throwable ex){
            ex.printStackTrace();
        }
        native_init();
    }
    public static native byte[] decodeAES(byte[] bArr, boolean z);
    public static native byte[] encodeAES(byte[] bArr);
    public static native String generateSign(byte[] bArr);
    public static native String getProtocolKey();
    public static native void native_init();
    public static native boolean registerDID(byte[] bArr);
    public static native void setProtocolKey(String str);
    public static native String sign(String str, byte[] bArr);
}


编译一下,没问题,编译通过。


跑一下

java.lang.ClassNotFoundException: Didn't find class "com.ixxixx.common.base.BaseApplication" on path: DexPathList


找不到  #BaseApplication# 这个类,我们也把他补齐

public class BaseApplication extends Application {
    private static Context context;
    public void onCreate() {
        super.onCreate();
        BaseApplication.context = getApplicationContext();
    }
    public static Context getAppContext() {
        return BaseApplication.context;
    }
}


再运行一下,直接跑起来了,结果正常 v2-1ff7402d2b4fa9a4c39b3853262f18fd


这下尴尬了


我们之前用unidbg跑的出来的结果不正常,多一个 ABC, 现在直接LoadSo跑出来的结果是对的?为什么?


我们回忆一下,用Unidbg跑的时候,首先补齐了 BaseApplication,然后 补齐了


AppLogReporterandroid/os/Debug->isDebuggerConnected()


说明 Unidbg跑的时候被 so识别出来了不是真实环境,  isDebuggerConnected 是判断程序有没有被调试器连接, 这个好验证呀,我们在调试模式下跑一下 LoadSo就行了。

java.lang.ClassNotFoundException: Didn't find class "cn.xiaochuankeji.tieba.common.debug.AppLogReporter" on path


果然不出所料,在调试模式下,不仅结果输出 v2-ABC1ff7402d2b4fa9a4c39b3853262f18fd , 而且还提示 AppLogReporter 类不存在。


真相只有一个so在执行过程中,判断是否是真实环境,比如是否被调试,是否是真机,如果发现环境不对,就在结果中加入ABC。


那好吧,可以收工了,还是按照昨天计划的玩法,Unidbg跑出结果之后,把 ABC 过滤掉。


继续分析


这次的so比较良心,也就加了个 ABC,而且长度和真实签名不一样,我们一眼都能看出来。


这要是让李老板来设计,发现环境不对之后,返回同样长度的签名串,到服务器也可以验证,这个是灰度用户,然后给他返回假数据。 那就比较棘手了。


所以正好继续拿这个so练练手,再分析分析,以后遇到类似的情况,也知道如何排雷了。


先把 AppLogReporter 类补齐,然后再用 SandHook 来hook这个 isDebuggerConnected


补齐 AppLogReporter

import android.util.Log;
public class AppLogReporter {
    public static void reportAppRuntime(String str, String str2) {
        String strOut = str + " ---- " + str2;
        Log.i("ZYDBG", strOut);
    }
}


Hook  isDebuggerConnected  ,直接返回 False

@HookClass(Debug.class)
public class OsDebug {
    @HookMethodBackup("isDebuggerConnected")
    static Method onIsDebuggerConnectedBackup;
    @HookMethod("isDebuggerConnected")
    public static boolean onIsDebuggerConnected() throws Throwable {
        boolean rc = (boolean)SandHook.callOriginByBackup(onIsDebuggerConnectedBackup,null);
        Log.e("ZYDBG OsDebug", "hooked isDebuggerConnected success rc= " + rc );
        return Boolean.FALSE;
    }
}


继续调试状态下运行, 结果还是带 ABC


这是为什么呢? 我们看看 Logcat

I/ZYDBG: runtiem ---- traced


原来又被发现 traced ,这时我们回想一下,Unidbg跑的时候 reportAppRuntime 函数的输出是 "invalid application name: izxxyxx"


这个so还真是不错,反Unidbg的样本。 搞错了 还会用 reportAppRuntime 来提示我们错在哪?


敲黑板,留作业


那么正好给大家留个作业,把这个so的反Unidbg和反调试部分,分析清楚,最后用Unidbg跑出正确的结果。


方法就是 LoadSo和Unidbg两个工程互相对照。 比如 Unidbg里面跑的时候调用了 getSimpleName 来获取名称,我们模拟的时候就随便写了个 izxxyxx,被发现了。  那么


就在 LoadSo 这个工程里面来 hook getSimpleName ,看看正确的结果是什么。

这样一步一步向真实靠拢。


三、总结


假到真时真亦假,安全对抗的时候就是比拼耐心,互相给对方挖坑埋雷。挖的坑要深点,雷要迷惑性强点。偶尔可以给对方一个甜头,让他以为搞定收工。实际后面还有千转百绕。


最后谁坚持不住放弃了,谁就输了。29.png

那些花半秒钟就看透事物本质的人,和花一辈子都看不清事物本质的人,注定是截然不同的命运。


TIP: 本文的目的只有一个就是学习更多的逆向技巧和思路,如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担,和本文以及作者没关系,本文涉及到的代码项目可以去 奋飞的朋友们 知识星球自取,欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: fenfei331 讨论下。


关注微信公众号: 奋飞安全,最新技术干货实时推送



相关文章
|
算法 安全 Java
Unidbg模拟执行某段子so实操教程(一) 先把框架搭起来
Unidbg模拟执行某段子so实操教程(一) 先把框架搭起来
Unidbg模拟执行某段子so实操教程(一) 先把框架搭起来
|
6月前
|
前端开发 JavaScript Java
童年回忆——捕鱼达人(内含源码inscode一键运行)
童年回忆——捕鱼达人(内含源码inscode一键运行)
|
11月前
|
测试技术
【测试平台系列】第一章 手撸压力机(十)-定义场景
上一章,咱们对http请求进行了一些优化,本章节我们将组成场景去运行。首先场景就是一连串的http接口的请求,我们使用list(列表)来组装成一个场景
【测试平台系列】第一章 手撸压力机(十)-定义场景
|
11月前
|
测试技术
【测试平台系列】第一章 手撸压力机(九)- 封装函数
将我们的一些代码封装到函数和方法中,这样我们看来代码可读性更好。如果发现bug,也可以更好的进行追踪。
|
传感器
时隔这么长时间,我把常用的功能整理好了,再来感受VueUse工具库的优雅吧~
时隔这么长时间,我把常用的功能整理好了,再来感受VueUse工具库的优雅吧~
时隔这么长时间,我把常用的功能整理好了,再来感受VueUse工具库的优雅吧~
|
IDE 算法 开发工具
面向 CV 编程:COPY 了别人文章中的代码,想让代码能像作者一样跑通,应该注意什么呢?怎样才能让代码愉快地跑起来呢
一千个读者,一千个哈姆雷特,写代码也是如此,不同人,理解不同,逻辑不同,同一道题,代码各有千秋,所以出现的问题也是千奇百怪;预期结果就一个,解法却千千万。正如列夫托尔斯泰的安娜卡列尼娜中所说:幸福的家庭千遍一律,不幸的家庭各有各的不幸,但是主要不离题万里,错误基本能在一个常见的范围。 有人写代码是为了生计,有的人写代码仅仅是自己的兴趣使然。应该大多人都是第一种情况,我也一样,到了大学才拥有自己的第一台电脑,那时候智能手机刚出现,再往前倒推几年,手机都是个稀罕物,没有条件所以跟兴趣不沾边,唯一沾点边的是以前我喜欢刷竞赛题,锻炼逻辑,对学习算法有点帮助,但是作用有限。甚至有些人对自己所选的专业一无
982 2
面向 CV 编程:COPY 了别人文章中的代码,想让代码能像作者一样跑通,应该注意什么呢?怎样才能让代码愉快地跑起来呢
|
存储 编译器 C++
类的入门<C++入门>(跑路人笔记)(3)
类的入门<C++入门>(跑路人笔记)
类的入门<C++入门>(跑路人笔记)(3)
|
编译器 C++
类的入门<C++入门>(跑路人笔记)(2)
类的入门<C++入门>(跑路人笔记)
类的入门<C++入门>(跑路人笔记)(2)
|
存储 编译器 C语言
类的入门<C++入门>(跑路人笔记)(1)
类的入门<C++入门>(跑路人笔记)
类的入门<C++入门>(跑路人笔记)(1)
|
存储 自然语言处理 程序员
预处理和程序的编程(跑路人笔记2)
预处理和程序的编程(跑路人笔记)
预处理和程序的编程(跑路人笔记2)