Android逆向(反调,脱壳,过ssl证书脚本)

2024-09-09 03:52

本文主要是介绍Android逆向(反调,脱壳,过ssl证书脚本),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

      • 总结
    • 基础
      • Android基础
      • 工具
    • 定位关键代码
      • 页面activity定位
      • 数据包参数定位
      • 堆栈追踪
    • 编写
    • 反调
    • 脱壳
    • 好用的脚本
      • 过ssl证书校验抓包
      • 反调的脚本
      • 打印堆栈
      • bilibili反调的脚本

总结

暑假做了两个月的Android逆向,记录一下自己学到的东西。对于app渗透有了一些思路。
这两个月主要做的是代码分析,对于分析完后的持久化等没有学习。主要是如何反编译源码,如何找到关键函数。
在这里插入图片描述

基础

Android基础

开始学习Android逆向,需要先掌握一些Android开发常见的知识点:

1、需要了解一个apk的目录架构,什么文件放在什么位置,将apk当作zip解压可以看到xml文件(声明入口,权限,服务等)、lib文件(so文件)、asserts文件等
2、知道一些常见的函数,(请求的url函数,处理json的函数等),便于后续hook,可以边学边记录,

工具

jadx:反编译工具,得到的java代码较清晰,但是可能会有部分反编译不了
GDA:反编译工具,相对于jadx可能稍微不太好读,但是该工具编译快,且能够直接调用frida,更加方便
frida:编写hook脚本,相对于xpose更加方便调试,但是持久化比xpose麻烦。
模拟器,或者是root的手机。

定位关键代码

在反编译完代码需要的是找到我们需要分析的功能点。

页面activity定位

首先打开我们功能点所在的页面,比如我想查看我的个人记录处的代码逻辑,我就需要打开对应的页面,然后使用下面的命令,查看表层的activity名称,然后去源代码中寻找对应的activity。

查看表层activity的名称
adb shell "dumpsys activity top | grep --color=always ACTIVITY"

在这里插入图片描述

数据包参数定位

找到对应功能的数据包,然后根据里面的参数去代码中搜索
比如:这里我想要找这个app是如何触发升级的,于是我拦截他的数据包,然后看到其中的参数app_version,于是我去代码中搜索app_version,如果太多,也可以换参数vm。
在这里插入图片描述

堆栈追踪

假如我们需要找的功能,调用了一处函数,但是我们又不知道在哪里调用的,这个时候我们可以打印堆栈。frida脚本放结尾。
我们找到了tostring函数,然后打印堆栈发现a方法调用了tostring

============================= 调用堆栈开始 =======================com.netease.commonupgrade.CommonUpgradeResponse.toString(Native Method)
com.netease.commonupgrade.CommonUpgradeResponse.a(Native Method)
com.netease.commonupgrade.CommonUpgradeImpl.a(SourceFile:114)
com.netease.commonupgrade.CommonUpgradeImpl.a(SourceFile:49)
com.netease.service.pris.v4.CheckUpdateTransaction.a(SourceFile:158)
com.netease.framework.task.AsyncTransaction.run(SourceFile:52)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:919)
============================= 调用堆栈结束 ==========================

编写

编写frida脚本,刚开始的时候我们可以多看看其他人的脚本,然后去frida官网查询相关的函数。
对于一些简单的分析,直接用GDA就可以,选中对应的函数,右键hook方法,或者自定义脚本然后将代码复制出来。

//GDA复制的代码可以直接使用:
Java.perform(function() {var targetClass='com.netease.commonupgrade.CommonUpgradeResponse';var methodName='a';var gclass = Java.use(targetClass);gclass[methodName].overload('int').implementation = function(arg0) {console.log('\nGDA[Hook a(int)]'+'\n\targ0 = '+arg0);var i=this[methodName](arg0);console.log('\treturn '+i);printStack();return i;}
})

反调

对于反调试,一些常见的手段就是检测相关的特征。

检测文件:检测在/data/local/tmp文件夹下是否存在名称为frida,ida的调试文件等。检测文件的权限是否为x(第二个较少)。
端口检查: 检测常用的调试端口是否打开
ptrace占用: 检测父进程
TracePid:检测调试的变量

常用的绕过手段。

将检测的文件重定向
改名称,端口
将相关代码nop

一些检测的路径。

“/data/data/” + ProName + “/maps”;
“/data/data/” + ProName + “/fmaps”;
“/data/data/” + ProName + “/task”;
“/data/data/” + ProName + “/exe”;
“/data/data/” + ProName + “/mounts”;
"/data/data/ + ProName + /status;

脱壳

这个工具脱壳比较好,一些企业壳也可以脱,如爱加密,360的企业壳。脱的不是完整的但是分析代码已经差不多了。

https://www.52pojie.cn/thread-1781276-1-1.html

踩坑:
1.Android14的手机有问题,读取不到脚本文件
2.一个脚本不行,换其它的试试,(上次虽然是360的壳,但是我没有脱成功,用通用的脚本脱成功了)

好用的脚本

过ssl证书校验抓包

做渗透需要抓包,但是一些app有证书校验,可以采用下面的脚本+burp抓包:
将证书放到脚本里面的路径,然后有反调的需要先过反调


setTimeout(function(){Java.perform(function (){console.log("");console.log("[.] Cert Pinning Bypass/Re-Pinning");var CertificateFactory = Java.use("java.security.cert.CertificateFactory");var FileInputStream = Java.use("java.io.FileInputStream");var BufferedInputStream = Java.use("java.io.BufferedInputStream");var X509Certificate = Java.use("java.security.cert.X509Certificate");var KeyStore = Java.use("java.security.KeyStore");var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");var SSLContext = Java.use("javax.net.ssl.SSLContext");// Load CAs from an InputStreamconsole.log("[+] Loading our CA...")var cf = CertificateFactory.getInstance("X.509");try {var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt");//***********************证书路径*******************************}catch(err) {console.log("[o] " + err);}var bufferedInputStream = BufferedInputStream.$new(fileInputStream);var ca = cf.generateCertificate(bufferedInputStream);bufferedInputStream.close();var certInfo = Java.cast(ca, X509Certificate);console.log("[o] Our CA Info: " + certInfo.getSubjectDN());// Create a KeyStore containing our trusted CAsconsole.log("[+] Creating a KeyStore for our CA...");var keyStoreType = KeyStore.getDefaultType();var keyStore = KeyStore.getInstance(keyStoreType);keyStore.load(null, null);keyStore.setCertificateEntry("ca", ca);// Create a TrustManager that trusts the CAs in our KeyStoreconsole.log("[+] Creating a TrustManager that trusts the CA in our KeyStore...");var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);tmf.init(keyStore);console.log("[+] Our TrustManager is ready...");console.log("[+] Hijacking SSLContext methods now...")console.log("[-] Waiting for the app to invoke SSLContext.init()...")SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) {console.log("[o] App invoked javax.net.ssl.SSLContext.init...");SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c);console.log("[+] SSLContext initialized with our custom TrustManager!");}});},0);

反调的脚本

这个是我在github上找到的,然后加了很多注释,根据需要修改。

//检测: 
//    /proc/25896/maps
//    /proc/25896/status    TracerPID Check
//
//
var ProName = ProcessName();
const currentPid = Process.id;
console.log(currentPid);
function ProcessName() {//libc.so是系统的文件,里面加载着打开,读取,关闭等操作文件的c函数,jni在调用so层时会用到打开,读取等。(下面还用到了pthread_creeate)var openPtr = Module.getExportByName('libc.so', 'open');var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);var readPtr = Module.getExportByName('libc.so', 'read');var read = new NativeFunction(readPtr, 'int', ['int', 'pointer', 'int']);var closePtr = Module.getExportByName('libc.so', 'close');var close = new NativeFunction(closePtr, 'int', ['int']);var path = Memory.allocUtf8String('/proc/self/cmdline');//父进程名检测var fd = open(path, 0);if (fd != -1) {var buffer = Memory.alloc(0x1000);var result = read(fd, buffer, 0x1000);close(fd);result = ptr(buffer).readCString();return result;}return -1;
}
//假设一个libxyz.so文件,追踪libxyz.so库,自己修改
//var ourlib = "libexec.so";
//获取pthread_create函数的地址
//var p_pthread_create = Module.findExportByName("libc.so", "pthread_create");
//var pthread_create = new NativeFunction(p_pthread_create, "int", ["pointer", "pointer", "pointer", "pointer"]);
//拦截和替换 pthread_create 函数
/*
Interceptor.replace(p_pthread_create, new NativeCallback(function(ptr0, ptr1, ptr2, ptr3) {//函数原型//int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);//thread:一个指向 pthread_t 类型的指针,用于存储新创建线程的标识符。//attr:一个指向 pthread_attr_t 类型的指针,用于指定新线程的属性(例如堆栈大小、调度策略等),通常可以传入 NULL 使用默认属性。//start_routine:一个函数指针,指向新线程将要执行的函数,该函数必须具有 void * 类型的参数并返回 void * 类型的指针。//arg:传递给 start_routine 函数的参数。var ret = ptr(0);if (gmn(ptr0) == ourlib) {console.log("Thread Created ptr0 : ", gmn(ptr0), Mod, ptr0.sub(Mod));}if (gmn(ptr1) == ourlib) {var Mod = Module.findBaseAddress(ourlib)console.log("Thread Created ptr1 : ", gmn(ptr1), Mod, ptr1.sub(Mod));Interceptor.attach(Mod.add(ptr1.sub(Mod)), {onEnter: function(args) {console.log("New Thread Func", ptr1.sub(Mod), "arg : ", args[0], args[1]);},onLeave: function(retval) {console.log("New Thread Func Return : ", retval);}});}if (gmn(ptr2) == ourlib) {var Mod = Module.findBaseAddress(ourlib)console.log("Thread Created ptr2 : ", gmn(ptr2), Mod, ptr2.sub(Mod));Interceptor.attach(Mod.add(ptr2.sub(Mod)), {onEnter: function(args) {console.log("New Thread Func", ptr2.sub(Mod), "arg : ", args[0], args[1]);},onLeave: function(retval) {console.log("New Thread Func Return : ", retval);}});}if (gmn(ptr3) == ourlib) {var Mod = Module.findBaseAddress(ourlib)console.log("Thread Created ptr3 : ", gmn(ptr3), Mod, ptr3.sub(Mod));Interceptor.attach(Mod.add(ptr3.sub(Mod)), {onEnter: function(args) {console.log("New Thread Func", ptr3.sub(Mod), "arg : ", args[0], args[1]);},onLeave: function(retval) {console.log("New Thread Func Return : ", retval);}});}if (ptr1.isNull() && ptr3.isNull()) {console.warn("loading fake pthread_create");// return -1 if you not want to create that thread return pthread_create(ptr0, ptr1, ptr2, ptr3);// return -1;} else {       return pthread_create(ptr0, ptr1, ptr2, ptr3);;}}, "int", ["pointer", "pointer", "pointer", "pointer"]));function gmn(fnPtr) {if (fnPtr != null) {try {//获取函数所在模块的名字          return Process.getModuleByAddress(fnPtr).name;          } catch (e) {console.error(e);}            }
}*/// 检测frida
/*
inet_aton
作用: 将一个 IPv4 地址的字符串表示转换为网络字节序的整数表示。
参数: addrs 是 IPv4 地址的字符串指针;structure 是一个 in_addr 结构体的指针,用于存放转换后的结果。
返回值: 成功返回 1,失败返回 0。
popen
作用: 打开一个管道,通过调用 shell 命令来执行一个进程,并返回一个标准 I/O 流。
参数: path 是要执行的 shell 命令的字符串;type 是打开模式(如 "r" 或 "w")。
返回值: 成功返回指向文件流的指针,失败返回 NULL。
symlink
作用: 创建一个符号链接。
参数: target 是要链接到的目标路径;path 是要创建的符号链接路径。
返回值: 成功返回 0,失败返回 -1。
symlinkat
作用: 在指定的文件描述符(目录)下创建一个符号链接。
参数: target 是要链接到的目标路径;fd 是目录文件描述符;path 是要创建的符号链接路径。
返回值: 成功返回 0,失败返回 -1。
inet_addr
作用: 将一个点分十进制的 IPv4 地址转换为网络字节序的整数表示。
参数: path 是点分十进制 IPv4 地址的字符串。
返回值: 成功返回一个无符号 32 位整数表示的 IP 地址,失败返回 INADDR_NONE。
socket
作用: 创建一个套接字。
参数: domain 是地址族(如 AF_INET 表示 IPv4);type 是套接字类型(如 SOCK_STREAM 表示流套接字);proto 是协议(如 0 表示自动选择合适的协议)。
返回值: 成功返回一个文件描述符,表示创建的套接字;失败返回 -1。
connect
作用: 建立与远程套接字的连接。
参数: fd 是套接字的文件描述符;addr 是指向目标地址结构的指针;len 是地址结构的长度。
返回值: 成功返回 0,失败返回 -1。
send
作用: 发送数据到套接字。
参数: socksfd 是套接字的文件描述符;msg 是指向要发送数据的缓冲区的指针;slen 是要发送的数据的长度;flag 是附加标志。
返回值: 成功返回发送的字节数,失败返回 -1。
sendto
作用: 发送数据到指定的套接字地址。
参数: socksfd 是套接字的文件描述符;msg 是指向要发送数据的缓冲区的指针;slen 是要发送的数据的长度;flag 是附加标志;daddr 是目标地址的指针;dlen 是目标地址的长度。
返回值: 成功返回发送的字节数,失败返回 -1。
open
作用: 打开或创建一个文件或其他资源。
参数: pathname 是要打开的文件路径;flag 是打开标志(如 O_RDONLY 表示只读)。
返回值: 成功返回文件描述符,失败返回 -1。
read
作用: 从文件描述符读取数据。
参数: fd 是文件描述符;buffer 是用于接收数据的缓冲区的指针;count 是要读取的最大字节数。
返回值: 成功返回实际读取的字节数,可能会少于请求的字节数;失败返回 -1。
*/var inet_atonPtr = Module.findExportByName(null, "inet_aton");
console.log(`inet_atonPtr: ${inet_atonPtr}`);
var inet_aton = new NativeFunction(inet_atonPtr, 'int', ['pointer', 'pointer']);Interceptor.replace(inet_atonPtr, new NativeCallback(function(addrs, structure) {var retval = inet_aton(addrs, structure);//console.log(1);//console.log("inet_aton : ", addrs.readCString())return retval;
}, 'int', ['pointer', 'pointer']))var popenPtr = Module.findExportByName("libc.so", "popen");
var popen = new NativeFunction(popenPtr, 'pointer', ['pointer', 'pointer']);
Interceptor.replace(popenPtr, new NativeCallback(function(path, type) {var retval = popen(path, type);//console.log(2);//console.log("popen : ", path.readCString());return retval;
}, 'pointer', ['pointer', 'pointer']))var symlinkPtr = Module.findExportByName("libc.so", "symlink");
var symlink = new NativeFunction(symlinkPtr, 'int', ['pointer', 'pointer']);
Interceptor.replace(symlinkPtr, new NativeCallback(function(target, path) {var retval = symlink(target, path);//console.log(3);//console.log("symlink: ", target.readCString(), path.readCString());return retval;
}, 'int', ['pointer', 'pointer']))var symlinkatPtr = Module.findExportByName("libc.so", "symlinkat");
var symlinkat = new NativeFunction(symlinkatPtr, 'int', ['pointer', 'int', 'pointer']);
Interceptor.replace(symlinkatPtr, new NativeCallback(function(target, fd, path) {var retval = symlinkat(target, fd, path);//console.log(4);//console.log("symlinkat : ", target.readCString(), path.readCString());return retval;
}, 'int', ['pointer', 'int', 'pointer']))var inet_addrPtr = Module.findExportByName("libc.so", "inet_addr");
var inet_addr = new NativeFunction(inet_addrPtr, 'int', ['int']);
Interceptor.replace(inet_addrPtr, new NativeCallback(function(path) {var retval = inet_addr(path);//console.log(5);//console.log("inet_addr : ", path.readCString())return retval;
}, 'int', ['int']))var socketPtr = Module.findExportByName("libc.so", "socket");
var socket = new NativeFunction(socketPtr, 'int', ['int', 'int', 'int']);
Interceptor.replace(socketPtr, new NativeCallback(function(domain, type, proto) {var retval = socket(domain, type, proto);//console.log(6);//console.warn("socket  : ", domain, type, proto, "Return : ", retval)return retval;
}, 'int', ['int', 'int', 'int']))var connectPtr = Module.findExportByName("libc.so", "connect");
var connect = new NativeFunction(connectPtr, 'int', ['int', 'pointer', 'int']);
Interceptor.replace(connectPtr, new NativeCallback(function(fd, addr, len) {var retval = connect(fd, addr, len);var family = addr.readU16();var port = addr.add(2).readU16();//port = ((port & 0xff) << 8) | (port >> 8);//console.log(7);//console.warn("Connect : ", family, "Port : ", port, "Return : ", retval);return retval;
}, 'int', ['int', 'pointer', 'int']))var sendPtr = Module.findExportByName("libc.so", "send");
var send2 = new NativeFunction(sendPtr, 'int', ['int', 'pointer', 'int', 'int']);
Interceptor.replace(sendPtr, new NativeCallback(function(socksfd, msg, slen, flag, daddr, dlen) {var retval = send2(socksfd, msg, slen, flag);//console.log(8);//console.log("send : ", socksfd, msg.readCString(), slen, flag);return retval;
}, 'int', ['int', 'pointer', 'int', 'int']))var sendtoPtr = Module.findExportByName("libc.so", "sendto");
var sendto = new NativeFunction(sendtoPtr, 'int', ['int', 'pointer', 'int', 'int', 'pointer', 'int']);
Interceptor.replace(sendtoPtr, new NativeCallback(function(socksfd, msg, slen, flag, daddr, dlen) {var retval = sendto(socksfd, msg, slen, flag, daddr, dlen);//console.log(9);//console.log("sendto : ",socksfd,msg.readCString(),slen,flag,daddr,dlen);                                       return retval;
}, 'int', ['int', 'pointer', 'int', 'int', 'pointer', 'int']))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"]);//这一段就是hookopen函数,将记录了文件是否被调试的文件进行了重定向
//ProName:进程名
var FakeMaps = "/data/data/" + ProName + "/maps";
var FOpenMaps = "/data/data/" + ProName + "/fmaps";
var FakeTask = "/data/data/" + ProName + "/task";
var FakeExE = "/data/data/" + ProName + "/exe";
var FakeMounts = "/data/data/" + ProName + "/mounts";
var FakeStatus = "/data/data/" + ProName + "/status";
var MapsFile = new File(FakeMaps, "w");
var TaskFile = new File(FakeTask, "w");
var ExEFile = new File(FakeExE, "w");
var FMapsFile = new File(FOpenMaps, "w");
var FMountFile = new File(FakeMounts, "w");
var StatusFile = new File(FakeStatus, "w");
var MapsBuffer = Memory.alloc(512);
var TaskBuffer = Memory.alloc(512);
var ExEBuffer = Memory.alloc(512);
var FopenBuffer = Memory.alloc(512);
var MountBuffer = Memory.alloc(512);
var StatusBuffer = Memory.alloc(512);
var Open64MapsBuffer = Memory.alloc(512);
//openptr在前面申明了,是open函数的地址
Interceptor.replace(openPtr, new NativeCallback(function(pathname, flag) {//pathname = "/proc/" + currentPid + "/maps";var FD = open(pathname, flag);var ch = pathname.readCString();//如果路径是/proc/xxx/mapsif (ch.indexOf("/proc/") >= 0 && ch.indexOf("maps") >= 0) {console.log("open : ", pathname.readCString(),11111) //parseInt:将字符串转换成整数while (parseInt(read(FD, MapsBuffer, 512)) !== 0) {//读取打开的文件的字符串var MBuffer = MapsBuffer.readCString();//将所有调试文件的名字替换//console.log(1);MBuffer = MBuffer.replaceAll("/data/local/tmp/re.frida.server/frida-agent-64.so", "FakingMaps");MBuffer = MBuffer.replaceAll("re.frida.server", "FakingMaps");MBuffer = MBuffer.replaceAll("re.frida", "FakingMaps");MBuffer = MBuffer.replaceAll("re.", "FakingMaps");MBuffer = MBuffer.replaceAll("frida.", "FakingMaps");MBuffer = MBuffer.replaceAll("frida-agent-64.so", "FakingMaps");MBuffer = MBuffer.replaceAll("rida-agent-64.so", "FakingMaps");MBuffer = MBuffer.replaceAll("agent-64.so", "FakingMaps");MBuffer = MBuffer.replaceAll("frida-agent-32.so", "FakingMaps");MBuffer = MBuffer.replaceAll("frida-helper-32", "FakingMaps");MBuffer = MBuffer.replaceAll("frida-helper", "FakingMaps");MBuffer = MBuffer.replaceAll("frida-agent", "FakingMaps");MBuffer = MBuffer.replaceAll("pool-frida", "FakingMaps");MBuffer = MBuffer.replaceAll("frida", "FakingMaps");MBuffer = MBuffer.replaceAll("frida-", "FakingMaps");MBuffer = MBuffer.replaceAll("/data/local/tmp", "/data");MBuffer = MBuffer.replaceAll("server", "FakingMaps");MBuffer = MBuffer.replaceAll("frida-server", "FakingMaps");MBuffer = MBuffer.replaceAll("linjector", "FakingMaps");MBuffer = MBuffer.replaceAll("gum-js-loop", "FakingMaps");MBuffer = MBuffer.replaceAll("frida_agent_main", "FakingMaps");MBuffer = MBuffer.replaceAll("gmain", "FakingMaps");MBuffer = MBuffer.replaceAll("frida", "FakingMaps");MBuffer = MBuffer.replaceAll("magisk", "FakingMaps");MBuffer = MBuffer.replaceAll(".magisk", "FakingMaps");MBuffer = MBuffer.replaceAll("/sbin/.magisk", "FakingMaps");MBuffer = MBuffer.replaceAll("libriru", "FakingMaps");MBuffer = MBuffer.replaceAll("xposed", "FakingMaps");MapsFile.write(MBuffer);//console.log("MBuffer : ",MBuffer);                                     }var filename = Memory.allocUtf8String(FakeMaps);return open(filename, flag);}//如果路径是/proc/xxx/task,检测正在运行的任务if (ch.indexOf("/proc") >= 0 && ch.indexOf("task") >= 0) {// console.log("open : ", pathname.readCString()) while (parseInt(read(FD, TaskBuffer, 512)) !== 0) {var buffer = TaskBuffer.readCString();buffer = buffer.replaceAll("re.frida.server", "FakingTask");buffer = buffer.replaceAll("frida-agent-64.so", "FakingTask");buffer = buffer.replaceAll("rida-agent-64.so", "FakingTask");buffer = buffer.replaceAll("agent-64.so", "FakingTask");buffer = buffer.replaceAll("frida-agent-32.so", "FakingTask");buffer = buffer.replaceAll("frida-helper-32", "FakingTask");buffer = buffer.replaceAll("frida-helper", "FakingTask");buffer = buffer.replaceAll("frida-agent", "FakingTask");buffer = buffer.replaceAll("pool-frida", "FakingTask");buffer = buffer.replaceAll("frida", "FakingTask");buffer = buffer.replaceAll("/data/local/tmp", "/data");buffer = buffer.replaceAll("server", "FakingTask");buffer = buffer.replaceAll("frida-server", "FakingTask");buffer = buffer.replaceAll("linjector", "FakingTask");buffer = buffer.replaceAll("gum-js-loop", "FakingTask");buffer = buffer.replaceAll("frida_agent_main", "FakingTask");buffer = buffer.replaceAll("gmain", "FakingTask");buffer = buffer.replaceAll("magisk", "FakingTask");buffer = buffer.replaceAll(".magisk", "FakingTask");buffer = buffer.replaceAll("/sbin/.magisk", "FakingTask");buffer = buffer.replaceAll("libriru", "FakingTask");buffer = buffer.replaceAll("xposed", "FakingTask");buffer = buffer.replaceAll("pool-spawner", "FakingTask");buffer = buffer.replaceAll("gdbus", "FakingTask");            TaskFile.write(buffer);// console.log(buffer);}var filename2 = Memory.allocUtf8String(FakeTask);return open(filename2, flag);}//如果路径是/proc/xxx/mountsif (ch.indexOf("/proc/") >= 0 && ch.indexOf("mounts") >= 0) {console.log("open : ", pathname.readCString())while (parseInt(read(FD, MountBuffer, 512)) !== 0) {var MNTBuffer = MountBuffer.readCString();MNTBuffer = MNTBuffer.replaceAll("magisk", "StaySafeStayHappy");MNTBuffer = MNTBuffer.replaceAll("/sbin/.magisk", "StaySafeStayHappy");MNTBuffer = MNTBuffer.replaceAll("libriru", "StaySafeStayHappy");MNTBuffer = MNTBuffer.replaceAll("xposed", "StaySafeStayHappy");MNTBuffer = MNTBuffer.replaceAll("mirror", "StaySafeStayHappy");MNTBuffer = MNTBuffer.replaceAll("system_root", "StaySafeStayHappy");MNTBuffer = MNTBuffer.replaceAll("xposed", "StaySafeStayHappy")FMountFile.write(MNTBuffer);// console.log("MNTBuffer : ",MNTBuffer);                                     }var mountname = Memory.allocUtf8String(FakeMounts);return open(mountname, flag);}if (ch.indexOf("/proc/") >=0 && ch.indexOf("status") >=0) {     console.log("open : ", pathname.readCString()) while (parseInt(read(FD, StatusBuffer, 512)) !== 0) {var PStatus = StatusBuffer.readCString();   if (PStatus.indexOf("TracerPid:") > -1) {StatusBuffer.writeUtf8String("TracerPid:\t0");console.log("Bypassing TracerPID Check");               }StatusFile.write(PStatus);                                                }var statusname = Memory.allocUtf8String(FakeStatus);return open(statusname, flag);  }if (ch.indexOf("/proc") >= 0 && ch.indexOf("exe") >= 0) {console.log("open : ", pathname.readCString())while (parseInt(read(FD, ExEBuffer, 512)) !== 0) {var buffer = ExEBuffer.readCString();//  console.warn(buffer)buffer = buffer.replaceAll("frida-agent-64.so", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-agent-32.so", "StaySafeStayHappy");buffer = buffer.replaceAll("re.frida.server", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-helper-32", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-helper", "StaySafeStayHappy");buffer = buffer.replaceAll("pool-frida", "StaySafeStayHappy");buffer = buffer.replaceAll("frida", "StaySafeStayHappy");buffer = buffer.replaceAll("/data/local/tmp", "/data");buffer = buffer.replaceAll("frida-server", "StaySafeStayHappy");buffer = buffer.replaceAll("linjector", "StaySafeStayHappy");buffer = buffer.replaceAll("gum-js-loop", "StaySafeStayHappy");buffer = buffer.replaceAll("frida_agent_main", "StaySafeStayHappy");buffer = buffer.replaceAll("gmain", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-agent", "StaySafeStayHappy");ExEFile.write(buffer);}var filename3 = Memory.allocUtf8String(FakeExE);return open(filename3, flag);}return FD;
}, 'int', ['pointer', 'int']))
var fgetsPtr = Module.findExportByName("libc.so", "fgets");
var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
Interceptor.replace(fgetsPtr, new NativeCallback(function(buf, size, fp) {//var retval = fgets(buf, size, fp);var buffer = buf.readCString();buffer = buffer.replaceAll("re.frida.server", "FakingGets");buffer = buffer.replaceAll("frida-agent-64.so", "FakingGets");buffer = buffer.replaceAll("rida-agent-64.so", "FakingGets");buffer = buffer.replaceAll("agent-64.so", "FakingGets");buffer = buffer.replaceAll("frida-agent-32.so", "FakingGets");buffer = buffer.replaceAll("frida-helper-32", "FakingGets");buffer = buffer.replaceAll("frida-helper", "FakingGets");buffer = buffer.replaceAll("frida-agent", "FakingGets");buffer = buffer.replaceAll("pool-frida", "FakingGets");buffer = buffer.replaceAll("frida", "FakingGets");buffer = buffer.replaceAll("/data/local/tmp", "/data");buffer = buffer.replaceAll("server", "FakingGets");buffer = buffer.replaceAll("frida-server", "FakingGets");buffer = buffer.replaceAll("linjector", "FakingGets");buffer = buffer.replaceAll("gum-js-loop", "FakingGets");buffer = buffer.replaceAll("frida_agent_main", "FakingGets");buffer = buffer.replaceAll("gmain", "FakingGets");buffer = buffer.replaceAll("magisk", "FakingGets");buffer = buffer.replaceAll(".magisk", "FakingGets");buffer = buffer.replaceAll("/sbin/.magisk", "FakingGets");buffer = buffer.replaceAll("libriru", "FakingGets");buffer = buffer.replaceAll("xposed", "FakingGets");buf.writeUtf8String(buffer);//  console.log(buf.readCString());return fgets(buf, size, fp);
}, 'pointer', ['pointer', 'int', 'pointer']))var readlinkPtr = Module.findExportByName("libc.so", "readlink");
var readlink = new NativeFunction(readlinkPtr, 'int', ['pointer', 'pointer', 'int']);
Interceptor.replace(readlinkPtr, new NativeCallback(function(pathname, buffer, bufsize) {var retval = readlink(pathname, buffer, bufsize);  //从内存中读取字符串,判断是否含有特征字符if(buffer.readCString().indexOf("frida")!==-1 ||buffer.readCString().indexOf("gum-js-loop")!==-1||buffer.readCString().indexOf("gmain")!==-1 ||buffer.readCString().indexOf("linjector")!==-1 || buffer.readCString().indexOf("/data/local/tmp")!==-1 || buffer.readCString().indexOf("pool-frida")!==-1 || buffer.readCString().indexOf("frida_agent_main")!==-1 ||buffer.readCString().indexOf("re.frida.server")!==-1 || buffer.readCString().indexOf("frida-agent")!==-1 ||buffer.readCString().indexOf("frida-agent-64.so")!==-1 ||buffer.readCString().indexOf("frida-agent-32.so")!==-1 ||buffer.readCString().indexOf("frida-helper-32.so")!==-1 ||buffer.readCString().indexOf("frida-helper-64.so")!==-1                        ){console.log(buffer.readCString(), "Check in readlink");buffer.writeUtf8String("/system/framework/services.jar");            return readlink(pathname, buffer, bufsize);  }//    console.log("readlink : ", pathname.readCString(), buffer.readCString());return retval;   
}, 'int', ['pointer', 'pointer', 'int']))var readlinkatPtr = Module.findExportByName("libc.so", "readlinkat");
var readlinkat = new NativeFunction(readlinkatPtr, 'int', ['int', 'pointer', 'pointer', 'int']);
Interceptor.replace(readlinkatPtr, new NativeCallback(function(dirfd, pathname, buffer, bufsize) {var retval = readlinkat(dirfd, pathname, buffer, bufsize);if(buffer.readCString().indexOf("frida")!==-1 ||buffer.readCString().indexOf("gum-js-loop")!==-1||buffer.readCString().indexOf("gmain")!==-1 ||buffer.readCString().indexOf("linjector")!==-1 || buffer.readCString().indexOf("/data/local/tmp")!==-1 || buffer.readCString().indexOf("pool-frida")!==-1 || buffer.readCString().indexOf("frida_agent_main")!==-1 ||buffer.readCString().indexOf("re.frida.server")!==-1 || buffer.readCString().indexOf("frida-agent")!==-1 ||buffer.readCString().indexOf("frida-agent-64.so")!==-1 ||buffer.readCString().indexOf("frida-agent-32.so")!==-1 ||buffer.readCString().indexOf("frida-helper-32.so")!==-1 ||buffer.readCString().indexOf("frida-helper-64.so")!==-1                              ){console.log(buffer.readCString(), "Check in readlinkat");buffer.writeUtf8String("/system/framework/services.jar");           return readlinkat(dirfd, pathname, buffer, bufsize);}//   console.log("readlinkat : ", pathname.readCString(), buffer.readCString());return retval;
}, 'int', ['int', 'pointer', 'pointer', 'int']))/*
Interceptor.attach(Module.findExportByName(null, "strstr"),{onEnter: function(args){this.frida = false;console.log(3);var str1 = args[0].readCString();var str2 = args[1].readCString();      if(str1.indexOf("frida")!==-1  || str2.indexOf("frida")!==-1 ||str1.indexOf("gum-js-loop")!==-1 || str2.indexOf("gum-js-loop")!==-1 ||str1.indexOf("gmain")!==-1 || str2.indexOf("gmain")!==-1 ||str1.indexOf("linjector")!==-1  || str2.indexOf("linjector")!==-1 ||str1.indexOf("/data/local/tmp")!==-1  || str2.indexOf("/data/local/tmp")!==-1 ||str1.indexOf("pool-frida")!==-1  || str2.indexOf("pool-frida")!==-1 ||str1.indexOf("frida_agent_main")!==-1  || str2.indexOf("frida_agent_main")!==-1 ||str1.indexOf("re.frida.server")!==-1  || str2.indexOf("re.frida.server")!==-1 ||str1.indexOf("frida-agent")!==-1  || str2.indexOf("frida-agent")!==-1 ||str1.indexOf("pool-spawner")!==-1  || str2.indexOf("pool-spawner")!==-1 ||str1.indexOf("frida-agent-64.so")!==-1  || str2.indexOf("frida-agent-64.so")!==-1 ||str1.indexOf("frida-agent-32.so")!==-1  || str2.indexOf("frida-agent-32.so")!==-1 ||str1.indexOf("frida-helper-32.so")!==-1  || str2.indexOf("frida-helper-32.so")!==-1 ||str1.indexOf("frida-helper-64.so")!==-1  || str2.indexOf("frida-helper-64.so")!==-1  ||str1.indexOf("/sbin/.magisk")!==-1  || str2.indexOf("/sbin/.magisk")!==-1  ||str1.indexOf("libriru")!==-1  || str2.indexOf("libriru")!==-1  ||str1.indexOf("magisk")!==-1  || str2.indexOf("magisk")!==-1  ){          this.frida = true;console.log("检测到:strstr : ",str1,str2);}},onLeave: function(retval){if (this.frida) {retval.replace(ptr("0x0"));}}
});
*///Enabling it might give crash on some apps 
/*
Interceptor.attach(Module.findExportByName("libc.so", "read"), {onEnter: function(args) {try {var buffer = args[1].readCString();if (buffer.indexOf("frida") >= 0) {buffer = buffer.replaceAll("re.frida.server", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-agent-64.so", "StaySafeStayHappy");buffer = buffer.replaceAll("rida-agent-64.so", "StaySafeStayHappy");buffer = buffer.replaceAll("agent-64.so", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-agent-32.so", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-helper-32", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-helper", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-agent", "StaySafeStayHappy");buffer = buffer.replaceAll("pool-frida", "StaySafeStayHappy");buffer = buffer.replaceAll("frida", "StaySafeStayHappy");buffer = buffer.replaceAll("/data/local/tmp", "/data");buffer = buffer.replaceAll("server", "StaySafeStayHappy");buffer = buffer.replaceAll("frida-server", "StaySafeStayHappy");buffer = buffer.replaceAll("linjector", "StaySafeStayHappy");buffer = buffer.replaceAll("gum-js-loop", "StaySafeStayHappy");buffer = buffer.replaceAll("frida_agent_main", "StaySafeStayHappy");buffer = buffer.replaceAll("gmain", "StaySafeStayHappy");buffer = buffer.replaceAll("magisk", "StaySafeStayHappy");buffer = buffer.replaceAll(".magisk", "StaySafeStayHappy");buffer = buffer.replaceAll("/sbin/.magisk", "StaySafeStayHappy");buffer = buffer.replaceAll("libriru", "StaySafeStayHappy");buffer = buffer.replaceAll("xposed", "StaySafeStayHappy");args[1].writeUtf8String(buffer);}} catch (e) {//console.error(e);}}
});
*//*
var memcpyPtr = Module.findExportByName("libc.so", "memcpy");
var memcpy = new NativeFunction(memcpyPtr, 'pointer', ['pointer', 'pointer', 'int']);
Interceptor.replace(memcpyPtr, new NativeCallback(function(dest, src, len) {var retval = memcpy(dest, src, len);if(dest.readCString() != null && src.readCString() != null && (dest.readCString().indexOf("frida")>=0 || src.readCString().indexOf("frida")>=0) ){//console.warn("memcpy : ",dest.readCString(),src.readCString());var buffer = dest.readCString();var buffer2 = src.readCString();buffer = buffer.replaceAll("re.frida.server","StaySafeStayHappy");                                                         buffer = buffer.replaceAll("frida-agent-64.so","StaySafeStayHappy");buffer = buffer.replaceAll("rida-agent-64.so","StaySafeStayHappy");buffer = buffer.replaceAll("agent-64.so","StaySafeStayHappy");        buffer = buffer.replaceAll("frida-agent-32.so","StaySafeStayHappy");       buffer = buffer.replaceAll("frida-helper-32","StaySafeStayHappy");        buffer = buffer.replaceAll("frida-helper","StaySafeStayHappy"); buffer = buffer.replaceAll("frida-agent","StaySafeStayHappy");        buffer = buffer.replaceAll("pool-frida","StaySafeStayHappy");            buffer = buffer.replaceAll("frida","StaySafeStayHappy");buffer = buffer.replaceAll("/data/local/tmp","/data");buffer = buffer.replaceAll("server","StaySafeStayHappy");buffer = buffer.replaceAll("frida-server","StaySafeStayHappy");buffer = buffer.replaceAll("linjector","StaySafeStayHappy");buffer = buffer.replaceAll("gum-js-loop","StaySafeStayHappy");buffer = buffer.replaceAll("frida_agent_main","StaySafeStayHappy");buffer = buffer.replaceAll("gmain","StaySafeStayHappy");buffer2 = buffer2.replaceAll("re.frida.server","StaySafeStayHappy");                                                         buffer2 = buffer2.replaceAll("frida-agent-64.so","StaySafeStayHappy");buffer2 = buffer2.replaceAll("rida-agent-64.so","StaySafeStayHappy");buffer2 = buffer2.replaceAll("agent-64.so","StaySafeStayHappy");        buffer2 = buffer2.replaceAll("frida-agent-32.so","StaySafeStayHappy");       buffer2 = buffer2.replaceAll("frida-helper-32","StaySafeStayHappy");        buffer2 = buffer2.replaceAll("frida-helper","StaySafeStayHappy"); buffer2 = buffer2.replaceAll("frida-agent","StaySafeStayHappy");        buffer2 = buffer2.replaceAll("pool-frida","StaySafeStayHappy");            buffer2 = buffer2.replaceAll("frida","StaySafeStayHappy");buffer2 = buffer2.replaceAll("/data/local/tmp","/data");buffer2 = buffer2.replaceAll("server","StaySafeStayHappy");buffer2 = buffer2.replaceAll("frida-server","StaySafeStayHappy");buffer2 = buffer2.replaceAll("linjector","StaySafeStayHappy");buffer2 = buffer2.replaceAll("gum-js-loop","StaySafeStayHappy");buffer2 = buffer2.replaceAll("frida_agent_main","StaySafeStayHappy");buffer2 = buffer2.replaceAll("gmain","StaySafeStayHappy");dest.writeUtf8String(buffer);src.writeUtf8String(buffer2);// console.log(buffer,buffer2);return memcpy(dest, src, len);}return retval;
}, 'pointer', ['pointer', 'pointer', 'int']))
*/

打印堆栈

将函数加在代码中,然后在hook的函数中调用printStack();即可。


// 日志打印和调用堆栈输出函数
// 日志输出
function LOG(sth)
{console.log(sth);
}
// 打印调用堆栈的函数
function printStack()
{Java.perform(function(){var Exception = Java.use("java.lang.Exception"); //加载Java类 java.lang.Exceptionvar ins = Exception.$new("Exception");// Exception构造方法调用var straces = ins.getStackTrace();// 调用Exception对象的getStackTrace方法if (straces != undefined && straces != null) {var strace = straces.toString();var replaceStr = strace.replace(/,/g, "\n");LOG("============================= 调用堆栈开始 =======================\n");LOG(replaceStr);LOG("============================= 调用堆栈结束 ==========================\n");Exception.$dispose();}}   );
}

bilibili反调的脚本

在网上找到的,可以绕过bilibili的反调。

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 = 0console.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 dlsyminterceptor.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("libmsaoaidsec.so") > -1) {hook_dlsym()}}}})return interceptor
}// 创建虚假pthread_create
var fake_pthread_create = create_fake_pthread_create()
var dlopen_interceptor = hook_dlopen()

这篇关于Android逆向(反调,脱壳,过ssl证书脚本)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1150082

相关文章

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR