首页
社区
课程
招聘
(新手向)新版某数字壳脱壳,过frida检测,及重打包
发表于: 2024-8-11 22:44 33679

(新手向)新版某数字壳脱壳,过frida检测,及重打包

2024-8-11 22:44
33679

大家好,我是小生,这次的app是一个国内某计划app, 功能相当全,界面也很美观,很实用,这个app我很欣赏。总共花了有三天晚上加一个白天,抓包分析,脱壳,过检测,手撕smail, 调试等, 做开发好久了,逆向有段时间没有接触了,很生疏了

就是会员太贵了,终身会员300多嘞!

【为该公司的权益考虑,不提供成品,也不提供app相关 信息】
(现在大大小小的app全都加壳,甚至一些颜色灰产的也加国内的这些壳!!! 动不动就抽取,dex2c,都不能愉快的好好玩耍了)​

图片描述
还有asserts目录下的 libjiagu.so 就知道是数字壳无疑了!

图片描述

apktool解包,发现6月份的新版数字加固

脱壳用的fart改的脱壳机,详细过程就不赘述了

图片描述
总共脱下来21个dex,一个个先脱进jadx中看看是否都是有用的,发现有两个全是壳相关的,剩下了19个

发现脱下来还是相对较完整的,里面也有损坏的部分,但影响不太大,
图片描述

因为这次我需要的是里面的vip功能,按照惯例先搜isVip等字样
发现搜出来很多结果,不影响,排除掉本app的广告sdk和依赖的库,一个个看,看和用户相关的,发现两个类都是相关的
直接写hook,
图片描述
只截取部分,
图片描述

然后 frida启动!
我是先attach启动的,发现会闪退
图片描述
换成去掉部分特征的strongr frida发现还是如此,
1.我又尝试了换端口,span启动,
2.hook libc.so中的 strstr,strcmp来去掉内存里的frida,gmain,gdbus等字样
3.hook 重定向/proc/xxx/maps
4.hook libc.so的exit
5.hook android.os.Process的killProcess
再配合上常用的几个过检测脚本还是一样闪退,感觉事情不简单了

提前说一嘴,这个frida检测不是在壳里,是在app的so里,还有hook这个业务代码要延迟一段时间执行,不然classloader还没有加载相关类。

既然不是在java层,那就是在native层检测的了,通常是hook android_dlopen_ext,观察加载到哪个so的时候退出就可以定位到了,

图片描述
可以定位到是在libmxxxdesc.so中

然后hook pthread_create函数,尝试找到来自libmxxxdesc.so创建的检测线程
图片描述
然后就一直卡在那了,一直也找不到来自该so的创建线程的调用,
下面的部分借鉴看雪的看雪bilibili frida过检测
把so放进ida中也没有发现有创建线程的导入符号
图片描述

尝试从更早的时机,通过hook dlsym函数来看是否有通过dlsym来获取pthread_create地址来进行调用

发现确实调用了创建线程的函数,只不过不是直接调用,而是采用通过dlsym获取地址再调用
图片描述

下面采用创建一个虚假的创建函数的地址返回,来欺骗目标so(还是来源于看雪bilibili frida过检测的思路和代码)

就过掉了检测

图片描述

通过hook关键的函数发现确实可以达到付费vip的效果,但是部分界面显示的vip样式还是有点问题,
我逐个把dex脱进jadx中,进行查看,去除掉没用的dex, 发现可以去除掉两个全是数字壳的特征dex,
图片描述

1.然后使用MT管理器把这21个dex替换了原来的dex
2.然后把asserts文件夹中的libjiagu.so 那四个数字壳的so文件删掉

3.然后把AndroidMinfest.xml中原来的com.stub.StubApp为程序真正的入口com.xxxxxx
这个app是真的大,光androidMinfest文件就干出去将近5000行!!(后面改smail的时候很痛苦)

图片描述
然后重打包编译,进行jarsinger签名,一气呵成,安装,闪退! 漂亮!

我一开始以为是不是有签名验证啊,我就再jadx中进行搜素packagemanager相关的,但都关系不太大,最后发现是脱壳还有数字的残留特征,
就是下面这种效果,1000多条!

图片描述

可以用正则的方式匹配替换掉,这里很麻烦,我替换了整整有半个多小时,各种各样的,真恶心!
这里我是使用 一键正则 工具走捷径了(尽管这样,也很慢)
下面这两个可以通用替换掉一些,但还是会有很多很多很多漏网之鱼

其实这个app算我运气好,onCreate函数没有被抽取掉,很赏脸了!

再都完成替换之后,确认没有stubapp, stub/stub等数字壳特征之后,再进行重打包,签名,发现可以打开了,我测试了一下,里面有两个子页面有点问题,打开会闪退,不过我会用到的页面都正常,(这个app大大小小加起来有62个页面,那两个无所谓)

首先声明一下,我不会smail(以下纯现学现用,所以看着像屎一样很正常)
这一步就没有什么技术含量了,(对于我这种小卡拉米以及 这种简单的app而言),主要是耐心和细心,
这里我是采用mt管理器来进行编辑的,不得不说,确实很方便,但是改smail也很麻烦,要操作寄存器,改完还不知道,只能重打包后安装才能验证出来,一不小心改错就会闪退,前文说到有两个相关的类,一个有get set方法,很好处理,get的话直接

还有一个bean全是public字段,没有get set方法,而且引用的地方相当多,我没有办法在构造函数中进行赋值,因为后续会被覆盖掉,这里我有想到用抓包改包的方式,我在有root和xposed的测试机上试验过,没问题,但我想在没有root和xposed的环境使用,这种方案显然不可行
我只能在每一个用到的地方都进行修改,比如

图片描述

之前一直采用的charles+postern方式抓包,用花哥的话说,走socket,靠近底层,能获取更多的上层流量

现在我改成了 Reqable小黄鸟来抓包,头一次用,挺方便的,也是要root,这个没得跑,
关于证书安装的问题,安卓7以后要手动remount,把证书移动到/system/etc/security/cacerts目录下
我试了好几次,小黄鸟都识别不到证书已安装,尽管64xxxk.0已经在系统证书目录中,后来我尝试移除charles证书,试了两次,重启过后可以了! 至于没有网络或者其他的问题导致无法安装证书,我的博客里有记载。

敢于尝试,就有成功的可能

文中所用到的部分过检测代码

function hook_dlopenAndExt() {
    Interceptor.attach(Module.findExportByName(null, "dlopen"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                //console.log("dlopen:", path);
                // if (path.indexOf("libart.so") >= 0) {
                //     // this.can_hook_libart = true;
                //     console.log("[dlopen:]", path);
                // }
                console.log("load " + path);
            }
        },
        onLeave: function (retval) {
            // if (this.can_hook_libart && !is_hook_libart) {
            //     dump_dex();
            //     is_hook_libart = true;
            // }
        }
    })
 
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                //console.log("android_dlopen_ext:", path);
                // if (path.indexOf("libart.so") >= 0) {
                //     // this.can_hook_libart = true;
                //     console.log("[android_dlopen_ext:]", path);
                // }
                console.log("load " + path);
            }
        },
        onLeave: function (retval) {
            // if (this.can_hook_libart && !is_hook_libart) {
            //     dump_dex();
            //     is_hook_libart = true;
            // }
        }
    });
}
function hook_dlopenAndExt() {
    Interceptor.attach(Module.findExportByName(null, "dlopen"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                //console.log("dlopen:", path);
                // if (path.indexOf("libart.so") >= 0) {
                //     // this.can_hook_libart = true;
                //     console.log("[dlopen:]", path);
                // }
                console.log("load " + path);
            }
        },
        onLeave: function (retval) {
            // if (this.can_hook_libart && !is_hook_libart) {
            //     dump_dex();
            //     is_hook_libart = true;
            // }
        }
    })
 
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                //console.log("android_dlopen_ext:", path);
                // if (path.indexOf("libart.so") >= 0) {
                //     // this.can_hook_libart = true;
                //     console.log("[android_dlopen_ext:]", path);
                // }
                console.log("load " + path);
            }
        },
        onLeave: function (retval) {
            // if (this.can_hook_libart && !is_hook_libart) {
            //     dump_dex();
            //     is_hook_libart = true;
            // }
        }
    });
}
function create_fake_pthread_create() {
    const fake_pthread_create = Memory.alloc(4096)
    Memory.protect(fake_pthread_create, 4096, "rwx")
    Memory.patchCode(fake_pthread_create, 4096, code => {
        const cw = new Arm64Writer(code, { pc: ptr(fake_pthread_create) })
        cw.putRet()
    })
    return fake_pthread_create
}
  
function hook_dlsym() {
    var count = 0
    console.log("=== HOOKING dlsym ===")
    var interceptor = Interceptor.attach(Module.findExportByName(null, "dlsym"),
        {
            onEnter: function (args) {
                const name = ptr(args[1]).readCString()
                console.log("[dlsym]", name)
                if (name == "pthread_create") {
                    count++
                }
            },
            onLeave: function(retval) {
                if (count == 1) {
                    retval.replace(fake_pthread_create)
                }
                else if (count == 2) {
                    retval.replace(fake_pthread_create)
                    // 完成2次替换, 停止hook dlsym
                    interceptor.detach()
                }
            }
        }
    )
    return Interceptor
}
  
function hook_dlopen() {
    var interceptor = Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    console.log("[LOAD]", path)
                    if (path.indexOf("libmxxxxxec.so") > -1) {
                        hook_dlsym()
                    }
                }
            }
        }
    )
    return interceptor
}
  
// 创建虚假pthread_create
var fake_pthread_create = create_fake_pthread_create()
var dlopen_interceptor = hook_dlopen()
function create_fake_pthread_create() {
    const fake_pthread_create = Memory.alloc(4096)
    Memory.protect(fake_pthread_create, 4096, "rwx")
    Memory.patchCode(fake_pthread_create, 4096, code => {
        const cw = new Arm64Writer(code, { pc: ptr(fake_pthread_create) })
        cw.putRet()
    })
    return fake_pthread_create
}
  
function hook_dlsym() {
    var count = 0
    console.log("=== HOOKING dlsym ===")
    var interceptor = Interceptor.attach(Module.findExportByName(null, "dlsym"),
        {
            onEnter: function (args) {
                const name = ptr(args[1]).readCString()
                console.log("[dlsym]", name)
                if (name == "pthread_create") {
                    count++
                }
            },
            onLeave: function(retval) {
                if (count == 1) {
                    retval.replace(fake_pthread_create)
                }
                else if (count == 2) {
                    retval.replace(fake_pthread_create)
                    // 完成2次替换, 停止hook dlsym
                    interceptor.detach()
                }
            }
        }
    )
    return Interceptor
}
  
function hook_dlopen() {
    var interceptor = Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    console.log("[LOAD]", path)
                    if (path.indexOf("libmxxxxxec.so") > -1) {
                        hook_dlsym()
                    }
                }
            }
        }
    )
    return interceptor
}
  
// 创建虚假pthread_create
var fake_pthread_create = create_fake_pthread_create()
var dlopen_interceptor = hook_dlopen()
public class Uxxxxfo implements Serializable {
    public List<AdX> adxList;
    public boolean axxxxeVip;
    public String alxxxcon;
    public String axxxge;
    public CheckFreeVipInfo cxxxnfo;
    public boolean evxxp;
    public int exxxxay;
    public String id;
    public boolean isPoxxxp;
    public boolean isxxxit;
    public boolean isVip;
......
......
public class Uxxxxfo implements Serializable {
    public List<AdX> adxList;
    public boolean axxxxeVip;
    public String alxxxcon;
    public String axxxge;
    public CheckFreeVipInfo cxxxnfo;
    public boolean evxxp;
    public int exxxxay;
    public String id;
    public boolean isPoxxxp;
    public boolean isxxxit;
    public boolean isVip;
......
......
function loadGson() {
 
    Java.openClassFile("/data/local/tmp/xiaosheng-dex-tool.dex").load();
    var js = Java.use("com.xiaosheng.tool.json.Gson");
    var gson = js.$new();
    return gson;
 
}
 
function hook_dlopen_ext() {
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    console.log("load " + path);
                }
            }
        }
    );
}
 
function hook_dlopenAndExt() {
    Interceptor.attach(Module.findExportByName(null, "dlopen"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                //console.log("dlopen:", path);
                // if (path.indexOf("libart.so") >= 0) {
                //     // this.can_hook_libart = true;
                //     console.log("[dlopen:]", path);
                // }
                console.log("load " + path);
            }
        },
        onLeave: function (retval) {
            // if (this.can_hook_libart && !is_hook_libart) {
            //     dump_dex();
            //     is_hook_libart = true;
            // }
        }
    })
 
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                //console.log("android_dlopen_ext:", path);
                // if (path.indexOf("libart.so") >= 0) {
                //     // this.can_hook_libart = true;
                //     console.log("[android_dlopen_ext:]", path);
                // }
                console.log("load " + path);
            }
        },
        onLeave: function (retval) {
            // if (this.can_hook_libart && !is_hook_libart) {
            //     dump_dex();
            //     is_hook_libart = true;
            // }
        }
    });
}
 
function hook_open() {
    var pth = Module.findExportByName(null, "open");
    Interceptor.attach(ptr(pth), {
        onEnter: function (args) {
            this.filename = args[0];
            console.log("", this.filename.readCString())
            if (this.filename.readCString().indexOf(".so") != -1) {
                args[0] = ptr(0)
            }
        }, onLeave: function (retval) {
            return retval;
        }
    })
}
 
function hookProcess() {
    var process = Java.use("android.os.Process");
    process.killProcess.implementation = function (pid) {
        console.log("kill process:" + pid)
    }
}
 
function hookExit() {
    var ByPassTracerPid = function () {
        var fgetsPtr = Module.findExportByName("libc.so", "fgets");
        var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
        Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
            var retval = fgets(buffer, size, fp);
            var bufstr = Memory.readUtf8String(buffer);
            if (bufstr.indexOf("TracerPid:") > -1) {
                Memory.writeUtf8String(buffer, "TracerPid:\t0");
                console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));
            }
            return retval;
        }, 'pointer', ['pointer', 'int', 'pointer']));
    };
 
 
 
}
function hook_Pthreadfunc() {
    var pthread_creat_addr = Module.findExportByName("libc.so", "pthread_create")
    Interceptor.attach(pthread_creat_addr, {
        onEnter(args) {
            console.log("call pthread_create...")
            let func_addr = args[2]
            console.log("The thread function address is " + func_addr)
            try {
                console.log('pthread_create called from:\n'
                    + Thread.backtrace(this.context, Backtracer.ACCURATE)
                        .map(DebugSymbol.fromAddress)
                        .join('\n')
                    + '\n');
            } catch (e) {
 
            }
        }
    })
}
function hookBaseExit() {
    function main() {
        const openPtr = Module.getExportByName('libc.so', 'open');
        const open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
        var readPtr = Module.findExportByName("libc.so", "read");
        var read = new NativeFunction(readPtr, 'int', ['int', 'pointer', "int"]);
        // var fakePath = "/sdcard/app/maps/maps";
        var fakePath = "/data/local/tmp/fakeMap";
        var file = new File(fakePath, "w");
        var buffer = Memory.alloc(512);
        Interceptor.replace(openPtr, new NativeCallback(function (pathnameptr, flag) {
            var pathname = Memory.readUtf8String(pathnameptr);
            var realFd = open(pathnameptr, flag);
            if (pathname.indexOf("maps") != 0) {
                while (parseInt(read(realFd, buffer, 512)) !== 0) {
                    var oneLine = Memory.readCString(buffer);
                    if (oneLine.indexOf("tmp") === -1) {
                        file.write(oneLine);
                    }
                }
                var filename = Memory.allocUtf8String(fakePath);
                return open(filename, flag);
            }
            var fd = open(pathnameptr, flag);
            return fd;
        }, 'int', ['pointer', 'int']));
    }
    setImmediate(main)
}
 
function replace_str() {
    var pt_strstr = Module.findExportByName("libc.so", 'strstr');
    var pt_strcmp = Module.findExportByName("libc.so", 'strcmp');
 
    Interceptor.attach(pt_strstr, {
        onEnter: function (args) {
            var str1 = args[0].readCString();
            var str2 = args[1].readCString();
            if (str2.indexOf("tmp") !== -1 ||
                str2.indexOf("frida") !== -1 ||
                str2.indexOf("gum-js-loop") !== -1 ||
                str2.indexOf("gmain") !== -1 ||
                str2.indexOf("gdbus") !== -1 ||
                str2.indexOf("pool-frida") !== -1 ||
                str2.indexOf("linjector") !== -1) {
                // console.log("strcmp-->", str1, str2);
                this.hook = true;
            }
        }, onLeave: function (retval) {
            if (this.hook) {
                retval.replace(0);
            }
        }
    });
 
    Interceptor.attach(pt_strcmp, {
        onEnter: function (args) {
            var str1 = args[0].readCString();
            var str2 = args[1].readCString();
            if (str2.indexOf("tmp") !== -1 ||
                str2.indexOf("frida") !== -1 ||
                str2.indexOf("gum-js-loop") !== -1 ||
                str2.indexOf("gmain") !== -1 ||
                str2.indexOf("gdbus") !== -1 ||
                str2.indexOf("pool-frida") !== -1 ||
                str2.indexOf("linjector") !== -1) {
                // console.log("strcmp-->", str1, str2);
                this.hook = true;
            }
        }, onLeave: function (retval) {
            if (this.hook) {
                retval.replace(0);
            }
        }
    })
 
}
// 定义一个函数anti_maps,用于阻止特定字符串的搜索匹配,避免检测到敏感内容如"Frida"或"REJECT"
function anti_maps() {
    // 查找libc.so库中strstr函数的地址,strstr用于查找字符串中首次出现指定字符序列的位置
    var pt_strstr = Module.findExportByName("libc.so", 'strstr');
    // 查找libc.so库中strcmp函数的地址,strcmp用于比较两个字符串
    var pt_strcmp = Module.findExportByName("libc.so", 'strcmp');
    // 使用Interceptor模块附加到strstr函数上,拦截并修改其行为
    Interceptor.attach(pt_strstr, {
        // 在strstr函数调用前执行的回调
        onEnter: function (args) {
            // 读取strstr的第一个参数(源字符串)和第二个参数(要查找的子字符串)
            var str1 = args[0].readCString();
            var str2 = args[1].readCString();
            // 检查子字符串是否包含"REJECT"或"frida",如果包含则设置hook标志为true
            if (str2.indexOf("REJECT") !== -1 || str2.indexOf("frida") !== -1) {
                this.hook = true;
            }
        },
        // 在strstr函数调用后执行的回调
        onLeave: function (retval) {
            // 如果之前设置了hook标志,则将strstr的结果替换为0(表示未找到),从而隐藏敏感信息
            if (this.hook) {
                retval.replace(0);
            }
        }
    });
 
    // 对strcmp函数做类似的处理,防止通过字符串比较检测敏感信息
    Interceptor.attach(pt_strcmp, {
        onEnter: function (args) {
            var str1 = args[0].readCString();
            var str2 = args[1].readCString();
            if (str2.indexOf("REJECT") !== -1 || str2.indexOf("frida") !== -1) {
                this.hook = true;
            }
        },
        onLeave: function (retval) {
            if (this.hook) {
                // strcmp返回值为0表示两个字符串相等,这里同样替换为0以避免匹配成功
                retval.replace(0);
            }
        }
    });
}
 
const STD_STRING_SIZE = 3 * Process.pointerSize;
class StdString {
    constructor() {
        this.handle = Memory.alloc(STD_STRING_SIZE);
    }
 
    dispose() {
        const [data, isTiny] = this._getData();
        if (!isTiny) {
            Java.api.$delete(data);
        }
    }
 
    disposeToString() {
        const result = this.toString();
        this.dispose();
        return result;
    }
 
    toString() {
        const [data] = this._getData();
        return data.readUtf8String();
    }
 
    _getData() {
        const str = this.handle;
        const isTiny = (str.readU8() & 1) === 0;
        const data = isTiny ? str.add(1) : str.add(2 * Process.pointerSize).readPointer();
        return [data, isTiny];
    }
}
 
function prettyMethod(method_id, withSignature) {
    const result = new StdString();
    Java.api['art::ArtMethod::PrettyMethod'](result, method_id, withSignature ? 1 : 0);
    return result.disposeToString();
}
 
 
function hook_libc_exit() {
    var exit = Module.findExportByName("libc.so", "exit");
    console.log("native:" + exit);
 
    Interceptor.attach(exit, {
        onEnter: function (args) {
            try {
                console.log(Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join("\n"));
            } catch (e) {
                console.log(e)
            }
        },
        onLeave: function (retval) {
            //send("gifcore so result value: "+retval);
        }
    });
}
 
function anti_exit() {
    const exit_ptr = Module.findExportByName(null, '_exit');
    // DMLog.i('anti_exit', "exit_ptr : " + exit_ptr);
    console.log("anti_kill, kill_ptr:" + exit_ptr)
    if (null == exit_ptr) {
        return;
    }
    Interceptor.replace(exit_ptr, new NativeCallback(function (code) {
        if (null == this) {
            return 0;
        }
        // var lr = FCCommon.getLR(this.context);
        // DMLog.i('exit debug', 'entry, lr: ' + lr);
        console.log("kill debug entry,lr")
        return 0;
    }, 'int', ['int', 'int']));
}
 
function anti_kill() {
    const kill_ptr = Module.findExportByName(null, 'kill');
    // DMLog.i('anti_kill', "kill_ptr : " + kill_ptr);
    console.log("anti_kill, kill_ptr:" + kill_ptr)
 
    if (null == kill_ptr) {
        return;
    }
    Interceptor.replace(kill_ptr, new NativeCallback(function (ptid, code) {
        if (null == this) {
            return 0;
        }
        // var lr = FCCommon.getLR(this.context);
        // DMLog.i('kill debug', 'entry, lr: ' + lr);
        console.log("kill debug entry,lr")
        // FCAnd.showNativeStacks(this.context);
        return 0;
    }, 'int', ['int', 'int']));
}
 
// FCCommon哪个库我引用一直有问题,就把那段代码注释掉了
function loadGson() {
 
    Java.openClassFile("/data/local/tmp/xiaosheng-dex-tool.dex").load();
    var js = Java.use("com.xiaosheng.tool.json.Gson");
    var gson = js.$new();
    return gson;
 
}
 
function hook_dlopen_ext() {
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    console.log("load " + path);
                }
            }
        }
    );
}
 
function hook_dlopenAndExt() {
    Interceptor.attach(Module.findExportByName(null, "dlopen"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                //console.log("dlopen:", path);
                // if (path.indexOf("libart.so") >= 0) {
                //     // this.can_hook_libart = true;
                //     console.log("[dlopen:]", path);
                // }
                console.log("load " + path);
            }
        },
        onLeave: function (retval) {
            // if (this.can_hook_libart && !is_hook_libart) {
            //     dump_dex();
            //     is_hook_libart = true;
            // }
        }
    })
 
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                //console.log("android_dlopen_ext:", path);
                // if (path.indexOf("libart.so") >= 0) {
                //     // this.can_hook_libart = true;
                //     console.log("[android_dlopen_ext:]", path);
                // }
                console.log("load " + path);
            }
        },
        onLeave: function (retval) {
            // if (this.can_hook_libart && !is_hook_libart) {
            //     dump_dex();
            //     is_hook_libart = true;
            // }
        }
    });
}
 
function hook_open() {
    var pth = Module.findExportByName(null, "open");
    Interceptor.attach(ptr(pth), {
        onEnter: function (args) {
            this.filename = args[0];
            console.log("", this.filename.readCString())
            if (this.filename.readCString().indexOf(".so") != -1) {
                args[0] = ptr(0)
            }
        }, onLeave: function (retval) {
            return retval;
        }
    })
}
 
function hookProcess() {
    var process = Java.use("android.os.Process");
    process.killProcess.implementation = function (pid) {
        console.log("kill process:" + pid)
    }
}
 
function hookExit() {
    var ByPassTracerPid = function () {
        var fgetsPtr = Module.findExportByName("libc.so", "fgets");
        var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
        Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
            var retval = fgets(buffer, size, fp);
            var bufstr = Memory.readUtf8String(buffer);
            if (bufstr.indexOf("TracerPid:") > -1) {
                Memory.writeUtf8String(buffer, "TracerPid:\t0");
                console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2024-8-11 23:19 被xsSkyFall编辑 ,原因:
收藏
免费 15
支持
分享
最新回复 (30)
雪    币: 31
活跃值: (396)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
mark,赞一个
2024-8-11 23:21
0
雪    币: 102
活跃值: (2045)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
mark,赞一个
2024-8-12 09:43
0
雪    币: 3082
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
onCreate函数没有被抽取,那数字壳方面就只需要dump dex就没有后续了
2024-8-12 10:13
0
雪    币: 524
活跃值: (649)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
怜渠客 onCreate函数没有被抽取,那数字壳方面就只需要dump dex就没有后续了
我看文章,有说oncreate函数被抽取的,不过我这个不是,dump dex之后还需要处理掉里面所有的数字的特征
2024-8-12 10:50
0
雪    币: 269
活跃值: (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
那数字公司的服务有4种价格吧,最低端的免费版估计不抽取,往上的收费版估计肯定要抽取一下了。
2024-8-12 12:34
1
雪    币: 524
活跃值: (649)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
gao健 那数字公司的服务有4种价格吧,最低端的免费版估计不抽取,往上的收费版估计肯定要抽取一下了。[em_84]
是指onCreate嘛
2024-8-12 14:54
0
雪    币: 269
活跃值: (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
xsSkyFall 是指onCreate嘛
是的,但是只是推测,没有试过,。因为穷
2024-8-13 10:53
1
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
frida检测和壳没有关系
2024-8-14 06:11
1
雪    币: 524
活跃值: (649)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
mb_pnlabahd frida检测和壳没有关系
也不能这么说吧,之前有遇到过双进程保护的
2024-8-14 08:33
0
雪    币: 859
活跃值: (915)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
标题是不是对新手这个词有什么误解
2024-8-14 17:07
1
雪    币: 524
活跃值: (649)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
TrumpWY 标题是不是对新手这个词有什么误解
没有没有,因为我就是新手
2024-8-15 09:19
0
雪    币: 443
活跃值: (1353)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
其实你可以把真正入口改为继承com.stub.StubApp的, 反正App都不会主动创建Application实例的.
2024-8-15 09:52
1
雪    币: 524
活跃值: (649)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
vrolife 其实你可以把真正入口改为继承com.stub.StubApp的, 反正App都不会主动创建Application实例的.
这倒是一个办法,不过这样改smail貌似有点麻烦吧
2024-8-15 16:47
0
雪    币: 443
活跃值: (1353)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
xsSkyFall 这倒是一个办法[em_63],不过这样改smail貌似有点麻烦吧
改一处好过改若干处
2024-8-15 20:12
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
xsSkyFall 也不能这么说吧,之前有遇到过双进程保护的
仅仅指你这个案例
2024-8-16 07:23
1
雪    币: 524
活跃值: (649)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
17
mb_pnlabahd 仅仅指你这个案例
那是的,这个确实不是在壳里,app本身的so带的检测
2024-8-16 08:54
0
雪    币: 338
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
数字壳是不是专指360的壳
2024-8-17 06:36
0
雪    币: 623
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
TrumpWY 标题是不是对新手这个词有什么误解

回复错误

最后于 2024-8-17 19:13 被mb_elqwyvnm编辑 ,原因:
2024-8-17 19:13
0
雪    币: 193
活跃值: (1215)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
新手吗?能不能研究一下i国网这个检测,貌似和这个还不一样,有挑战
2024-8-21 18:46
0
雪    币: 524
活跃值: (649)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
jfztaq 新手吗?能不能研究一下i国网这个检测,貌似和这个还不一样,有挑战[em_28]
好的,有时间我康康
2024-8-22 09:25
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
求大佬帮忙
2024-8-22 14:05
0
雪    币: 14824
活跃值: (6063)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
xsSkyFall 好的,有时间我康康
你这个frida脚本能过360Vip加固?
2024-8-22 16:11
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
666学习下
2024-8-22 16:28
0
雪    币: 524
活跃值: (649)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
25
tDasm 你这个frida脚本能过360Vip加固?
应该是不能
2024-8-22 20:03
0
游客
登录 | 注册 方可回帖
返回
//