Android hook、检测及对抗相关

这篇具有很好参考价值的文章主要介绍了Android hook、检测及对抗相关。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

内存读写断点 

var code = null
var text_access = null
var data_access = null
var base = null
var size = null

function set_bp(basee , sizee , offset){
    base = basee
    size = sizee
    data_access = Process.getRangeByAddress(base.add(offset))
    //console.log('data_access : ' + data_access)
    var ret = Memory.protect(base.add(offset) , size , 'r--')
    if(!ret){
        console.log('Target addr changne false ')
    }else{
        console.log('Init target addr protect succeed , addr : ' + base.add(offset))
    }
    
    
    // 处理异常回调函数
    Process.setExceptionHandler(function(details){
        console.log('---------------Exception func---------------')

        if(details.type == 'access-violation'){
            console.log('details.type : ' + details.type)
            console.log('Exception from addr : ' + details.address)

            if(details.memory.address >= base.add(offset) && details.memory.address < base.add(offset + size)){
                console.log('Target addr accessed : ' + details.address)
                console.log(hexdump(details.address.add(-0x10)))
                return false;

            }else if(details.memory.address > base.add(offset - 0x1000) && details.memory.address < base.add(offset + 0x1000) ){
                console.log('Target addr memory page accessed , addr : ' + details.memory.address)
                if(data_access.protection == null){
                    console.log('data_access.protection don\'t init')
                    return false
                }
                var ret = Memory.protect(base.add(offset) , size , data_access.protection)
                console.log('Change base.add(offset) protection : ' + data_access.protection)
                if(!ret){
                    console.log('Memory page revert fail')
                }

                text_access = Process.getRangeByAddress(details.address.add(4))
                Memory.protect(details.address.add(4) , 4 , 'rwx')
                console.log('Exception data : ' + details.address.readU32())
                code = details.address.add(4).readU32()
                console.log('Save code : ' + code.toString(16))
                details.address.add(4).writeS32(0xcccccccc)
                console.log('Write cc at : ' + details.address.add(4))
                return true;

            }else{
                console.log('Other Exception , Exception addr : ' + details.memory.address)
                return false;
            }

        }else if( details.type == 'illegal-instruction'){
            console.log(hexdump(details.address.add(-0x10)))
            console.log('details.type : ' + details.type)
            console.log('Exception from addr : ' + details.address)
            console.log('Exception code : ' + details.address.readU64())
            if(details.address.readU32() != 0xcccccccc){
                console.log('Process oneself illegal-instruction Exception')
                return false;
            }

            console.log('Write code : ' + code.toString(16))
            console.log('text_access.protection : ' + text_access.protection)
            details.address.writeU32(code)
            Memory.protect(details.address , 4 , text_access.protection)
            Memory.protect(base.add(offset) , size , 'r--')
            return true;
        }else{
            console.log('details.type : ' + details.type)
            return false;
        }

    });
        

        
};


function main() {
    var symbols = Module.enumerateSymbols("linker64");
    for(var i = 0; i < symbols.length; i++){
        if(symbols[i].name.indexOf("find_libraries") >= 0){
            Interceptor.attach(symbols[i].address, {
                onEnter: function(args){
                    
                    if(args[3] != 1){
                        console.log("More than one ELF loaded simultaneously,Path : ")
                        for(var i = 0; i < args[3]; i++){
                            console.log( ptr(args[2]).add(i * Process.pointerSize ).readPointer().readCString())
                        }
                        console.log("\n")
                    }else{
                        var path = ptr(args[2]).readPointer().readCString()
                        if(path.indexOf('your_so_name.so') > 0){
                            this.hook = 1
                            console.log(' ')
                            console.log("ELF_LoadPath : " + ptr(args[2]).readPointer().readCString())
                        }
                    }
                }, onLeave(retval){
                    if(!this.hook) return;
                    var lib = Process.findModuleByName('your_so_name.so')
                    if(lib != null){
                        console.log('your_so_name base : ' + lib.base)
                        set_bp(lib.base , 8 , 0x123456)
                    }else{
                        console.log('get your_so_name base final')
                    }
                }

            })
            break;
        }
    }



}
setImmediate(main)

Xposed hook多个dex

//hook 多dex
            XposedHelpers.findAndHookMethod(Application.class, "attach",
                    Context.class, new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            ClassLoader cl = ((Context) param.args[0]).getClassLoader();
                            Class<?> hookclass = null;
                            try {
                                hookclass = cl.loadClass("com.kuaishou.android.security.kfree.a");
                            } catch (Exception e) {
                                Log.e("DEBUG", "load class error", e);
                                return;
                            }
                            Log.i("DEBUG", "load success");
                            XposedHelpers.findAndHookMethod(hookclass, "invoke", Object.class, Method.class, Object[].class,
                                    new XC_MethodHook() {
                                        //TODO: 相关hook操作
                                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

                                            super.beforeHookedMethod(param);

                                            Log.d("cxa", " has Hooked!");

                                        }

                                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                                            Object[] ars = (Object[]) param.args[2];
                                            Log.d("cxa", ars[0].toString());

                                        }
                                    });
                        }
                    });

firda hook libart.so文件导出函数(专治各种静态找不到)

Java.perform(function(){

    console.log(" ");
	console.log("-------------------------------BagaBoy-------------------------------------");
    

	// libart.so 所有导出函数表
    var symbols = Module.enumerateSymbolsSync("libart.so");
    var addr_register = null;
    for(var i = 0; i < symbols.length; i++){
        var symbol = symbols[i];
        var method_name = symbol.name;
        if(method_name.indexOf("art") >= 0){

            if(method_name.indexOf("_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi") >= 0){
                addr_register = symbol.address;
            }
        }
    }

    // 开始hook
    if(addr_register){
        Interceptor.attach(addr_register, {
            onEnter: function(args){
                var methods = ptr(args[2]);
                var method_count = args[3];
                console.log("[RegisterNatives] method_count:", method_count);
                for(var i = 0; i < method_count; i++){
                    var fn_ptr = methods.add(i * Process.pointerSize * 3 + Process.pointerSize * 2).readPointer();
                    var find_module = Process.findModuleByAddress(fn_ptr);
                    if(i == 0){
                        console.log("module name :", find_module.name);
                        console.log("module base :", find_module.base);
                    }
                    console.log("\t method_name  :", methods.add(i * Process.pointerSize * 3).readPointer().readCString());
                    console.log("\t method_sign  :", methods.add(i * Process.pointerSize * 3 + Process.pointerSize).readPointer().readCString());
                    console.log("\t method_fnPtr :", fn_ptr);
                    console.log("\t method offset:", fn_ptr.sub(find_module.base));
                }
            }, onLeave(retval){

            }
        })
    }



    //hook 系统 fork 函数
    var pthread_create_addr = null;
	var symbols = Process.findModuleByName("libc.so").enumerateSymbols();
	for (var i = 0; i < symbols.length; i++){
		if (symbols[i].name === "fork"){
			console.log("Find fork is OK");
			pthread_create_addr = symbols[i].address;
		};
	};

	Interceptor.attach(pthread_create_addr,{
		onEnter: function(args){
			//console.log("args is ->" + args[0], args[1], args[2],args[3]);
		},
		onLeave: function(retval){
			console.log("原始retval :" , retval);
			if(!retval)
			{
				retval = 0x666;
			    console.log("fork retval change :" , retval);
			}
		}
	});


	console.log("-------------------------------BagaBoy-------------------------------------");











});
hook liblinker.so
function hook() {
    //call_function("DT_INIT", init_func_, get_realpath());
    var linkermodule = Process.getModuleByName("linker");
    var linker_function_addr = null;
    var symbols = linkermodule.enumerateSymbols();
    for (var i = 0; i < symbols.length; i++) {
        var symbol = symbols[i];
        if (symbol.name.indexOf("__dl__ZL13call_functionPKcPFviPPcS2_ES0_") != -1) {
            linker_function_addr = symbol.address;
        }
    }
    Interceptor.attach(linker_function_addr, {
        onEnter: function (args) {
            var type = ptr(args[0]).readUtf8String();
            var address = args[1];
            var sopath = ptr(args[2]).readUtf8String();
            console.log("path:" + sopath + "--addr:" + address + "--type:" + type);
            if (sopath.indexOf("YourSoName") != -1) {
                var soAddr = Process.getModuleByName("YourSoName");
                //后续修改或hook操作
            }
        }
    })
}
Java.perform(function() {
  hook();
}
hook init_array中的函数,

需要指定so名称,且会hook之后的所有so的init_array中的函数,可以通过hook_init函数中for循环,使用函数偏移过滤。

function hook_init(){

var symbols = Module.enumerateSymbols("linker64");
    var init_hook = 0
    var init_addr = 0
    for(var i = 0; i < symbols.length; i++){
        if(symbols[i].name.indexOf("call_constructors") >= 0){
            init_addr = symbols[i].address
        }
    }
    if(init_addr){
        Interceptor.attach(init_addr, {
            onEnter: function(args){
                var func_addr = ptr(args[0]).add(0x98).readPointer()
                var func_num  = ptr(args[0]).add(0xA0).readPointer()
                if(func_num > 0 ){
                    console.log("init_arry func num: " + func_num )
                    console.log("ELF addr: " + Module.findBaseAddress("libjrcejx.so") )
                    for(var i = 0; i < func_num ; i++){
                        var a = func_addr.add(i * Process.pointerSize).readPointer()
                        console.log("func addr : " + a)
                        //可以在此处过滤,init_array中的函数地址a - libjrcejx.so的基址,是目标偏移在执行下面的hook
                        Interceptor.attach(a, {
                            onEnter: function(args){
                                console.log("hook func " + i)
                            }
                        })
                        
    
                    }
                }

                
                

            }
        })
    }

}


Java.perform(function() {
    console.log(" "  )
    var symbols = Module.enumerateSymbols("linker64");
    for(var i = 0; i < symbols.length; i++){
        if(symbols[i].name.indexOf("find_libraries") >= 0){
            Interceptor.attach(symbols[i].address, {
                onEnter: function(args){
                    var ELF_Path = ptr(args[2]).readPointer().readCString();
                    if(ELF_Path.indexOf("libjrcejx.so") >= 0){
                        hook_init()
                    }
                }
            })
        }
    }

})

通过libc.so的底层dlopen函数实现dump so

/*
  dump so
  // init 和 initarray 已经执行完成  JNI_Onload 没被执行 
  soSavePath: /data/data/cn.ishansong/ 保存so文件的路径(可能遇到权限问题)
  soName: libDexHelper.so 保存so文件的名称
 */
function android_dlopen_ext_dunpso(soSavePath, soName){

    var android_dlopen_extPtr = Module.findExportByName('libc.so','android_dlopen_ext')
    Interceptor.attach(android_dlopen_extPtr,{
        onEnter: function(args){
            console.log(`android_dlopen_ext(path="${args[0].readUtf8String()}")`);
            if (args[0].readUtf8String().indexOf(soName)){
                this.isdump = true;
            }
        },onLeave: function(retval){
            if(this.isdump){
                var libSo = Process.findModuleByName(soName)
                if (libSo != null){
                    console.log('---------- start dump : '+soName)
                    var file = new File(soSavePath+soName,'w')
                    Memory.protect(ptr(libSo.base),libSo.size,'rwx')
                    var buffer = ptr(libSo.base).readByteArray(libSo.size)
                    file.write(buffer)
                    file.close()
                }
            }
        }
    })
}
Xposed模块

新建Android项目,识别为Project,在main文件夹下添加lib文件夹,导入jar包,右键jar包,点击线面的add****(将该文件添加为项目的依赖)。

在main目录下新建assets文件夹,新建init文件,填写插件的入口类的路径

Android hook、检测及对抗相关

打印堆栈
XposedBridge.log("Dump Stack: " + "---------------start----------------");
                                Throwable ex = new Throwable();
                                StackTraceElement[] stackElements = ex.getStackTrace();
                                if (stackElements != null) {
                                    for (int i = 0; i < stackElements.length; i++) {

                                        XposedBridge.log("Dump Stack" + i + ": ");
                                        XposedBridge.log(stackElements[i].getClassName()
                                                + "----" + stackElements[i].getFileName()
                                                + "----" + stackElements[i].getLineNumber()
                                                + "----" + stackElements[i].getMethodName());
                                    }


                                }

Inline-Hook和SandHook 

        都是基于inline-hook基础,通过修改函数的跳转地址实现hook,br  mycode_addr;据说inline主要用于32位hook,sandhook主要用于64位hook。

PLT/GOT hook

        全局偏移表(GOT)和动态链接表(PLT),主要通过解析so文件,将导出表函数地址替换为自己的native函数地址实现hook,导入表hook本质上和导出表hook原理相同,只不过hook的是系统so或者其他so的导出表,优点是相比于Inline-hook稳定性更好,缺点是只能hook导入导出表

Unicorn hook(没太看懂,貌似很牛逼)

        跨平台的模拟框架,通过模拟不同平台的cpu实现,内部并没有函数的概念,只是一个单纯执行指令的cpu,可以实现指令级hook

 Xposed hook

        原理:Java函数执行时会调用到dvmCallMethodV判断是Java层还是native层函数,xposed通过修改dvmCallMethod的accessFlags值来欺骗虚拟机为调用native层函数,再将nativeFunc指针指向自己实现的native方法();

                Android版本高于5.0时,使用xposed需要刷入框架,替换系统的

        1.重写系统的Zygote,加入一段代码,所有从zygote fork出的进程都注入XposedBridge.jar ,使用XposedHelpers.findAndHookMethod 方法hook系统函数。

        2.通过反射机制找到Method,判断安卓版本,初始化参数与返回值类型。

        3.修改函数指针。

万物皆可 Hook,探究 Xposed 框架 Hook 原理 - 知乎 (zhihu.com) (hook代码及xposed检测)

Frida hook

        原理:和Xopsed类似,也是欺骗虚拟机执行自己的native函数,修改accessflags,函数指针,函数执行模式。

        1.函数是否 为AOT 编译的热点函数,是则直接执行。

        2.Java层函数调用,未经过AOT编译,ARTMethod 的值为artQuickToInterpreterBridge(快速编译代码的入口点),从二进制执行模式(AOT)切换到边解释边执行(JIT)模式

        3.Native层函数调用,未经过AOT编译,ARTMethod的值为artQuickGenericJniTrampoline 

        所以Frida会更改ARTmethod结构中的:

        access_flags_(执行的是Java层还是Native层)
        entry_point_from_jni_
        art_quick_generic_jni_trampoline
        artInterpreterToCompiledCodeBridge

        检测:frida开启的端口、被注入进程中是否存在frida-agent-32.so模块、检测进程是否有frida-server、探测端口通信D-bus协议。

Xposed 与 frida 的区别:

        Xposed是通过修改字节码实现hook,因此只能搞Java层函数,且安装需要root权限,稳定性较好。

        frida是通过向程序注入JavaScript脚本,动态二进制插桩实现,所以native层函数也可以搞,不用root,上去就是干,但是稳定性较差,没事就崩给你看。

APK简单对抗

1.Java层混淆:jadx -> 工具 -> 反混淆

2.资源加密:特点 直接用Android killer打开,反编译失败,资源文件报错;在手机MT管理器中更改代码。

3.签名校验:

         java层:关键API getPackageManager(获取包管理器)  getPackageInfo(获取包信息)  packageInfo.signatures(包签名信息)   

        so层:先找到执行签名校验的so文件,拖入IDA,查看导出表,check_sign jni_onload(动态注册) java_(静态注册)等关键函数,分析校验逻辑更改so或者java层文件。 

通过Java反射机制调用签名校验Java反射机制详解_杨 戬的博客-CSDN博客。

PackageInfo packageInfo = getPackageManager().getPackageInfo(

            getPackageName(),

            PackageManager.GET_SIGNATURES);

Signature[] signs = packageInfo.signatures;

4.模拟器检测:检测蓝牙,电话信息权限,已安装的APK,CPU框架等。

5.类抽取:将dex文件中的函数指令转为NOP,程序跑起来时在so层填充该函数指令。

正向还原:第一种是通过读取/proc/<pid>/maps文件获取加载的DEX文件地址,然后对DEX文件进行解析,找到NOP指令进行还原;第二种方法就是通过Hook系统函数(最简单的就是dexFindClass函数)然后进行指令还原。

逆向还原:最终解密出的Java函数还是要在内存中的,使用IDA动态调试拿到原本的函数字节码,填充回dex,或者同样hook系统函数,等程序填充后在dump dex。

dex方法还原:

        使用 010Editor 找到该方法的类(在class区段中找)

Android hook、检测及对抗相关

         选中并打开类数据标签(2),打开方法列表(3,下图中有两个列表),在列表中找到参数类型与返回值类型与咱们的目标函数相同的方法,此次实验目标为public void org.a.a.m.c.a(char[], int, int)方法。Android hook、检测及对抗相关

         按照下图打开选项卡,找到方法对应的16进制数据,进行填充或者删除,最后还需要更改dex文件头中的SHA1(或者其他的?)校验信息。Android hook、检测及对抗相关

 Android hook、检测及对抗相关Android hook、检测及对抗相关

6.第四代VMP壳:程序启动时,将加密后的dex文件解密,加载到内存;在内存中创建一个虚拟机,将dex转换为vmp虚拟指令集;再将指令集转换为Dalvik字节码执行(用到那个dex中的方法就解密哪个,不是一次性将dex转为Dalvik字节码)

7.函数级加密:

        在应用程序运行时,解密函数会被调用来解密每个被加密的函数,然后将其加载到内存中,并在执行时动态解密。

        静态函数级加密:每个函数加密方式同,拿到解密函数还原。

         动态函数级加密:每个函数加密方式同;动态函数级加密中,每个函数使用不同的密钥进行加密,获取每个函数对应的密钥;找出解密函数,解密函数使用密钥对每个函数进行解密。

8.不落地加载壳:

        先执行壳程序,在内存中解密程序本身的dex,在so层调用系统 libdvm.so 中的 openDexFile 函数加载内存中的dex,该函数的返回类型为int类型的cookie。

9.so加壳:

        通过加壳器对原始so文件进行混淆与加密,运行时在解密,详见 Android杂项 中的自定义linker

10.ollvm混淆:

        控制流平坦化:听起来好像很难懂,其实就是把原本直接的函数调用,前面加上各种 if 、for、switch、while等分支判断的逻辑,加大逆向分析的时间开销,函数逻辑变得混乱。

  • (1)函数的开始地址为序言的地址;
  • (2)序言的后继块为主分发器;
  • (3)后继为主分发器的块为预处理器;
  • (4)后继为预处理器的块为真实块;
  • (5)无后继的块为retn块;
  • (6)剩下的为无用块。

下图为经过ollvm控制流平坦化处理的函数

Android hook、检测及对抗相关

         去混淆的思路就是去除无用块及确定真实块执行的先后顺序。

        指令替换:将程序原本简单的二元运算(加 减 乘 除 异或 与 等等),替换为更加复杂的运算,但结果和原本一样(PS:纯纯有病,技术不行,cpu来凑?)

        控制流伪造:和平坦化差不多,就是 if 、for、switch、while 循环的替换,加大分析难度,让cpu更容易冒烟。

Android反调试

1.关键文件检测:改文件名。

2.调试端口检测:更改ida,frida等默认连接端口;

3.进程名检测:android_server gdbserver gdb等进程名检测;父进程名检测,桌面启动的父进程名应为zygote,hook 或修改smali 

4.Java层反调试:android.os.Debug.isDebuggerConnected(),killer中搜索函数更改;xml中applicationInfo属性中添加android:debuggable=“true”。hook该函数让其返回1;

5.ptrace检测(相当于Windows中的attch):手动跟踪到ptrace函数修改返回值;编写新的ptrace函数so文件放到app的lib下并设置环境变量;hook大法,

6.TracerPid 检测:基本同上,检测/proc/self/status的TracerPid 值。不为0就是被调试了,通过修改内核文件/dev/block/mmcblk0/boot中TracerPid函数硬编码实现;程序建立子线程附加自己,如果TracerPid值为0则退出;。

7.断点检测:rtld_db_dlactivity函数:这个函数默认情况下为空函数,这里的值应该为0,而当有调试器时,这里会被改为断点指令;获取该函数地址,将其nop。

8.时间检测,单步调试陷阱:app主动设置断点,并在代码中注册断点信号处理函数,未被调试(执行断点发出信号—进入处理信号函数—NOP替换断点—退回PC),被调试,执行调试程序的处理函数,他会恢复目标处指令失败,然后回退PC,进入死循环。

9.利用ida先截获信号的特性:将关键函数放在信号处理函数中,未被执行则被调试。

10.双进程守护:主进程a,fork子进程b,b进程ptrace a的所有线程;修改安卓源码;

11.通过修改so文件程序头的特征,so二进制文件开头一般是.ELF,frida执行前会检测该二进制数据是否为.ELF,但是该数据在so执行中并不会使用,所以可以通过将so文件程序头中的.ELF特征更改,这样在frida使用attch方式附加时会直接崩溃;通过frida -U -f app_packeageName --no-pause启动app,原因是frida代码文件校验模式问题。

12.通过frida中findExportByName函数校验漏洞:frida在使用该函数时会获取linker中的__dl__Z17solist_get_somainv的返回值,并且未经过为空校验直接使用,所以将该函数返回值改为0,frida脚本中只要使用到了findExportByName就会崩溃(frida在hookJava函数时一定会调用),该函数在正常程序执行中大概率不会用到。

Java层的双进程通过xposed hook应该可以解决(xposed是通过重写zygote进程实现hook,理论上可以拦截所有Java层的操作);so层的可以在该so刚加载时就附加,然后修改fork操作(未实践)。或者编写一个so库,里面重写ptrace和dlopen函数,重写的函数里面最后在调用真正的系统函数,加载该库。

分类:

frida检测:

1.TracerPid 检测          2.进程名检测        3.端口检测        4.已加载库文件检测: /proc/self/maps 目录是否包含frida关键字       

5.通过获取 libart.so 的函数遍历函数表(该函数包含每个so函数的地址),判断每个加载的so函数开头是否为0xd61f020058000050(firda实现hook是通过inline hook插入的代码特征)       

6.java层检测:frida hook java层API是通过将其转换为native函数在进行hook,可以判断java函数的属性是否为native函数来检测

Android风控

        风险控制,为了解决和预防将要发生,或者可能发生的一些危险情况,从而减轻损失。

        注:并不完全是新内容,选读,因为近期面试遇到过不少,所以自己学学之后打算写个笔记加深一下印象。

蜜罐数据:当发现作弊以后返回的数据是非正常的数据,可能存在埋点等信息,比如在视频的随机帧中添加标识,水印等,返回错误,重复的数据。

IP限制:当一个IP请求过量或过于频繁时,返回错误数据或者蜜罐数据。

设备指纹:设备指纹的核心是使用设备的唯一识别码,就像每个人的身份证号码一样。

java函数获取:Settings. Secure / Global .getString(context.getContentResolver(),Settings.Secure.ANDROID_ID)

黑灰产通过协议逆向,实现批量注册等“薅羊毛”行为,可通过网络数据包中的设备指纹判断,是否为同一设备,短时间内大量注册账号,从而判定是否遭到黑产攻击。

App环境信息:可以通过该设备运行环境的信息,将用户划分为 可疑设备 与 黑产设备。

1.root检测:su权限,文件检测;扫描 magisk 关键字;maps检测等。

2.Hook检测:主流hook框架Frida与xposed检测上报。

3.沙箱检测:判断APK的私有路径是否为 /data/data/包名;

Android hook、检测及对抗相关

4.自定义rom检测:需要有手机的驱动源码才能自定义rom,通过对比md5值等检测是否存在自定义rom。

5.查杀分离:当当前设备被服务器判定为黑产时,不会立即封杀,而是延时几小时或者几天在封杀,防止黑产一次一步步摸清风控判断依据。

6.心跳包&用户行为检测:在app刚跑来就与服务器建立socket连接,每隔一段时间发送一个心跳包,如果通过单纯的逆向网络协议实现算法接口,再通过PC发送数据的话,服务端在长时间没有收到用户的心跳包后,就可以将此设备判定为黑产设备。用户通过逆向字节写的点击框架,可能没有一点多余的操作,如正常用户的滑动屏幕,点击时间间隔,屏幕点击坐标等,也可以以此作为风控判定标准。

7.异常&行为埋点:正常用户点击登入接口时,在之前肯定会打开app的登入页面,可以在登入页面设置埋点,发送特定的数据包给服务器,如果用户只发送了登入的数据包,或者发送的埋点数据不足时,可以此判定该设备为黑产设备。

Android 进程注入

动态注入      

        由于Linux的进程机制,每个进程在安装后都会分配一个独享的UID,所以要想达到进程注入,需要拿到系统的root权限,之后总体流程和PC端大同小异;

获取进程pid

附加进程                    :Attch(pid)

保存目标进程寄存器  :GetRegs(pid,&SaveRegister)

目标进程内申请空间  :通过mmap映射申请,与binder差不太多

写入shell                    :

修改PC寄存器,

执行shell。

静态注入

        通过修改ELF文件实现,文章来源地址https://www.toymoban.com/news/detail-456887.html

到了这里,关于Android hook、检测及对抗相关的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • android 如何进行内存泄漏检测及解决方法

    内存泄漏是在Android开发中常见的问题之一,它可能导致应用的内存占用逐渐增加,最终影响应用的性能和稳定性。以下是一些常见的方法来进行内存泄漏检测和解决: 1. 使用工具进行内存泄漏检测: Android Profiler: Android Studio提供的Android Profiler工具可以帮助您监视应用的内

    2024年02月07日
    浏览(49)
  • Android 源码浅析:Leakcanary 内存泄漏检测的好帮手

    我们一起来分析一下大名鼎鼎的 Leakcanary, 想必作为 Android 开发都多多少少接触过,新版本的 Leakcanary 也用 Kotlin 重写了一遍,最近详细查看了下源码,分享一下。 tips:本来是只想分析下内存泄漏检测部分,但写着写着就跑偏了,因为内存泄漏的检测难点在于对对象生命周期

    2024年02月02日
    浏览(43)
  • 第116天:免杀对抗-EDR&Syscall-hook&DLL反射注入&白加黑&隐写分离&加载器

    知识点 演示案例: 总结

    2024年02月16日
    浏览(44)
  • 和MATLAB相关的设置断点的快捷键

    一个朋友在修改错误的时候,有个操作震惊到我了。 他把迭代次数从1000减小到100,就可以快速仿真完。 废话不多说,直接上快捷键。 F12:设置或者清楚断点。 F5:运行 F10和F11都是步进,但是两者有区别。 F10在步进时不进入函数调用。 F11在步进时进入函数调用。 shift+F11:

    2024年02月01日
    浏览(35)
  • OpenCV——八邻域断点检测

    OpenCV——八邻域断点检测由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 图1 八邻域示意图 图2 八邻域对应坐标关系   首先将图像进行二值化,然后检测以 P 1 P_1 P 1 ​ 为中心的它的八个领域, P 2 + P 3 + P 4 + P 5 + P 6

    2024年01月19日
    浏览(28)
  • CVPR2023对抗攻击相关论文

    Feature Separation and Recalibration for Adversarial Robustness 论文链接:http://arxiv.org/abs/2303.13846v1 代码地址:GitHub - wkim97/FSR: Feature Separation and Recalibration (CVPR 2023) 摘要:由于特征层面的扰动积累,深度神经网络容易受到对抗性攻击,许多研究通过停用导致模型错误预测的非鲁棒特征激活

    2024年02月09日
    浏览(42)
  • React 中与生命周期相关的 Hooks 及其使用示例

    React 16.8 引入了 Hooks 的概念,使得函数组件也可以使用 state 和生命周期等特性。与生命周期相关的 Hooks 主要有以下三个: useEffect useEffect 是最常用的一个 Hook,它可以用来替代 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 这三个生命周期函数。useEffect 的作

    2024年04月14日
    浏览(31)
  • 生成对抗网络与计算机视觉:提升对象检测与识别能力

    计算机视觉技术在过去的几年里取得了显著的进展,这主要是由于深度学习技术的蓬勃发展。深度学习技术在计算机视觉领域的应用主要集中在以下几个方面: 对象检测:通过在图像中识别和定位特定的对象,如人脸、车辆、建筑物等。 图像分类:通过将图像分为多个类别

    2024年02月22日
    浏览(43)
  • 【爬虫JS逆向-工具篇】浏览器内存漫游加密参数Hook实战教程

    【作者主页】: 吴秋霖 【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作! 【作者推荐】:对JS逆向感兴趣的朋友可以关注《爬虫JS逆向实战》,对分布式爬虫平台感兴趣的朋友可以关注《分布式爬虫平台搭建

    2024年02月22日
    浏览(50)
  • Android Hook技术学习——常见的hook技术方案

    最近一段时间在研究Android加壳和脱壳技术,其中涉及到了一些hook技术,于是将自己学习的一些hook技术进行了一下梳理,以便后面回顾和大家学习。 本文第二节主要讲述编译原理,了解编译原理可以帮助进一步理解hook技术 本文第三节主要讲述NDK开发的一些基础知识 本文第四

    2024年02月12日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包