国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android hook、檢測及對抗相關(guān)

這篇具有很好參考價值的文章主要介紹了Android hook、檢測及對抗相關(guān)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

內(nèi)存讀寫斷點?

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))
    }
    
    
    // 處理異?;卣{(diào)函數(shù)
    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: 相關(guān)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文件導(dǎo)出函數(shù)(專治各種靜態(tài)找不到)

Java.perform(function(){

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

	// libart.so 所有導(dǎo)出函數(shù)表
    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 系統(tǒng) fork 函數(shù)
    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");
                //后續(xù)修改或hook操作
            }
        }
    })
}
Java.perform(function() {
  hook();
}
hook init_array中的函數(shù),

需要指定so名稱,且會hook之后的所有so的init_array中的函數(shù),可以通過hook_init函數(shù)中for循環(huán),使用函數(shù)偏移過濾。

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中的函數(shù)地址a - libjrcejx.so的基址,是目標偏移在執(zhí)行下面的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函數(shù)實現(xiàn)dump so

/*
  dump so
  // init 和 initarray 已經(jīng)執(zhí)行完成  JNI_Onload 沒被執(zhí)行 
  soSavePath: /data/data/cn.ishansong/ 保存so文件的路徑(可能遇到權(quán)限問題)
  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文件夾,導(dǎo)入jar包,右鍵jar包,點擊線面的add****(將該文件添加為項目的依賴)。

在main目錄下新建assets文件夾,新建init文件,填寫插件的入口類的路徑

Android hook、檢測及對抗相關(guān)

打印堆棧
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基礎(chǔ),通過修改函數(shù)的跳轉(zhuǎn)地址實現(xiàn)hook,br? mycode_addr;據(jù)說inline主要用于32位hook,sandhook主要用于64位hook。

PLT/GOT hook

? ? ? ? 全局偏移表(GOT)和動態(tài)鏈接表(PLT),主要通過解析so文件,將導(dǎo)出表函數(shù)地址替換為自己的native函數(shù)地址實現(xiàn)hook,導(dǎo)入表hook本質(zhì)上和導(dǎo)出表hook原理相同,只不過hook的是系統(tǒng)so或者其他so的導(dǎo)出表,優(yōu)點是相比于Inline-hook穩(wěn)定性更好,缺點是只能hook導(dǎo)入導(dǎo)出表

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

? ? ? ? 跨平臺的模擬框架,通過模擬不同平臺的cpu實現(xiàn),內(nèi)部并沒有函數(shù)的概念,只是一個單純執(zhí)行指令的cpu,可以實現(xiàn)指令級hook

?Xposed hook

? ? ? ? 原理:Java函數(shù)執(zhí)行時會調(diào)用到dvmCallMethodV判斷是Java層還是native層函數(shù),xposed通過修改dvmCallMethod的accessFlags值來欺騙虛擬機為調(diào)用native層函數(shù),再將nativeFunc指針指向自己實現(xiàn)的native方法();

? ? ? ? ? ? ? ? Android版本高于5.0時,使用xposed需要刷入框架,替換系統(tǒng)的

? ? ? ? 1.重寫系統(tǒng)的Zygote,加入一段代碼,所有從zygote fork出的進程都注入XposedBridge.jar ,使用XposedHelpers.findAndHookMethod 方法hook系統(tǒng)函數(shù)。

? ? ? ? 2.通過反射機制找到Method,判斷安卓版本,初始化參數(shù)與返回值類型。

? ? ? ? 3.修改函數(shù)指針。

萬物皆可 Hook,探究 Xposed 框架 Hook 原理 - 知乎 (zhihu.com)?(hook代碼及xposed檢測)

Frida hook

? ? ? ? 原理:和Xopsed類似,也是欺騙虛擬機執(zhí)行自己的native函數(shù),修改accessflags,函數(shù)指針,函數(shù)執(zhí)行模式。

? ? ? ? 1.函數(shù)是否 為AOT 編譯的熱點函數(shù),是則直接執(zhí)行。

? ? ? ? 2.Java層函數(shù)調(diào)用,未經(jīng)過AOT編譯,ARTMethod 的值為artQuickToInterpreterBridge(快速編譯代碼的入口點),從二進制執(zhí)行模式(AOT)切換到邊解釋邊執(zhí)行(JIT)模式

? ? ? ? 3.Native層函數(shù)調(diào)用,未經(jīng)過AOT編譯,ARTMethod的值為artQuickGenericJniTrampoline?

? ? ? ? 所以Frida會更改ARTmethod結(jié)構(gòu)中的:

????????access_flags_(執(zhí)行的是Java層還是Native層)
        entry_point_from_jni_
        art_quick_generic_jni_trampoline
        artInterpreterToCompiledCodeBridge

? ? ? ? 檢測:frida開啟的端口、被注入進程中是否存在frida-agent-32.so模塊、檢測進程是否有frida-server、探測端口通信D-bus協(xié)議。

Xposed 與 frida 的區(qū)別:

? ? ? ? Xposed是通過修改字節(jié)碼實現(xiàn)hook,因此只能搞Java層函數(shù),且安裝需要root權(quán)限,穩(wěn)定性較好。

? ? ? ? frida是通過向程序注入JavaScript腳本,動態(tài)二進制插樁實現(xiàn),所以native層函數(shù)也可以搞,不用root,上去就是干,但是穩(wěn)定性較差,沒事就崩給你看。

APK簡單對抗

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

2.資源加密:特點 直接用Android killer打開,反編譯失敗,資源文件報錯;在手機MT管理器中更改代碼。

3.簽名校驗:

?? ? ? ? java層:關(guān)鍵API?getPackageManager(獲取包管理器)??getPackageInfo(獲取包信息)? packageInfo.signatures(包簽名信息)? ?

? ? ? ? so層:先找到執(zhí)行簽名校驗的so文件,拖入IDA,查看導(dǎo)出表,check_sign jni_onload(動態(tài)注冊) java_(靜態(tài)注冊)等關(guān)鍵函數(shù),分析校驗邏輯更改so或者java層文件。?

通過Java反射機制調(diào)用簽名校驗Java反射機制詳解_楊 戩的博客-CSDN博客。

PackageInfo packageInfo = getPackageManager().getPackageInfo(

            getPackageName(),

            PackageManager.GET_SIGNATURES);

Signature[] signs = packageInfo.signatures;

4.模擬器檢測:檢測藍牙,電話信息權(quán)限,已安裝的APK,CPU框架等。

5.類抽?。?/strong>將dex文件中的函數(shù)指令轉(zhuǎn)為NOP,程序跑起來時在so層填充該函數(shù)指令。

正向還原:第一種是通過讀取/proc/<pid>/maps文件獲取加載的DEX文件地址,然后對DEX文件進行解析,找到NOP指令進行還原;第二種方法就是通過Hook系統(tǒng)函數(shù)(最簡單的就是dexFindClass函數(shù))然后進行指令還原。

逆向還原:最終解密出的Java函數(shù)還是要在內(nèi)存中的,使用IDA動態(tài)調(diào)試拿到原本的函數(shù)字節(jié)碼,填充回dex,或者同樣hook系統(tǒng)函數(shù),等程序填充后在dump dex。

dex方法還原:

????????使用 010Editor 找到該方法的類(在class區(qū)段中找)

Android hook、檢測及對抗相關(guān)

? ? ? ? ?選中并打開類數(shù)據(jù)標簽(2),打開方法列表(3,下圖中有兩個列表),在列表中找到參數(shù)類型與返回值類型與咱們的目標函數(shù)相同的方法,此次實驗?zāi)繕藶閜ublic void org.a.a.m.c.a(char[], int, int)方法。Android hook、檢測及對抗相關(guān)

? ? ? ? ?按照下圖打開選項卡,找到方法對應(yīng)的16進制數(shù)據(jù),進行填充或者刪除,最后還需要更改dex文件頭中的SHA1(或者其他的?)校驗信息。Android hook、檢測及對抗相關(guān)

?Android hook、檢測及對抗相關(guān)Android hook、檢測及對抗相關(guān)

6.第四代VMP殼:程序啟動時,將加密后的dex文件解密,加載到內(nèi)存;在內(nèi)存中創(chuàng)建一個虛擬機,將dex轉(zhuǎn)換為vmp虛擬指令集;再將指令集轉(zhuǎn)換為Dalvik字節(jié)碼執(zhí)行(用到那個dex中的方法就解密哪個,不是一次性將dex轉(zhuǎn)為Dalvik字節(jié)碼)

7.函數(shù)級加密:

????????在應(yīng)用程序運行時,解密函數(shù)會被調(diào)用來解密每個被加密的函數(shù),然后將其加載到內(nèi)存中,并在執(zhí)行時動態(tài)解密。

????????靜態(tài)函數(shù)級加密:每個函數(shù)加密方式同,拿到解密函數(shù)還原。

? ? ? ? ?動態(tài)函數(shù)級加密:每個函數(shù)加密方式同;動態(tài)函數(shù)級加密中,每個函數(shù)使用不同的密鑰進行加密,獲取每個函數(shù)對應(yīng)的密鑰;找出解密函數(shù),解密函數(shù)使用密鑰對每個函數(shù)進行解密。

8.不落地加載殼:

? ? ? ? 先執(zhí)行殼程序,在內(nèi)存中解密程序本身的dex,在so層調(diào)用系統(tǒng) libdvm.so 中的 openDexFile 函數(shù)加載內(nèi)存中的dex,該函數(shù)的返回類型為int類型的cookie。

9.so加殼:

? ? ? ? 通過加殼器對原始so文件進行混淆與加密,運行時在解密,詳見?Android雜項?中的自定義linker

10.ollvm混淆:

? ? ? ? 控制流平坦化:聽起來好像很難懂,其實就是把原本直接的函數(shù)調(diào)用,前面加上各種 if 、for、switch、while等分支判斷的邏輯,加大逆向分析的時間開銷,函數(shù)邏輯變得混亂。

  • (1)函數(shù)的開始地址為序言的地址;
  • (2)序言的后繼塊為主分發(fā)器;
  • (3)后繼為主分發(fā)器的塊為預(yù)處理器;
  • (4)后繼為預(yù)處理器的塊為真實塊;
  • (5)無后繼的塊為retn塊;
  • (6)剩下的為無用塊。

下圖為經(jīng)過ollvm控制流平坦化處理的函數(shù)

Android hook、檢測及對抗相關(guān)

? ? ? ? ?去混淆的思路就是去除無用塊及確定真實塊執(zhí)行的先后順序。

? ? ? ? 指令替換:將程序原本簡單的二元運算(加 減 乘 除 異或 與 等等),替換為更加復(fù)雜的運算,但結(jié)果和原本一樣(PS:純純有病,技術(shù)不行,cpu來湊?)

? ? ? ? 控制流偽造:和平坦化差不多,就是 if 、for、switch、while 循環(huán)的替換,加大分析難度,讓cpu更容易冒煙。

Android反調(diào)試

1.關(guān)鍵文件檢測:改文件名。

2.調(diào)試端口檢測:更改ida,frida等默認連接端口;

3.進程名檢測:android_server gdbserver gdb等進程名檢測;父進程名檢測,桌面啟動的父進程名應(yīng)為zygote,hook 或修改smali?

4.Java層反調(diào)試:android.os.Debug.isDebuggerConnected(),killer中搜索函數(shù)更改;xml中applicationInfo屬性中添加android:debuggable=“true”。hook該函數(shù)讓其返回1;

5.ptrace檢測(相當于Windows中的attch):手動跟蹤到ptrace函數(shù)修改返回值;編寫新的ptrace函數(shù)so文件放到app的lib下并設(shè)置環(huán)境變量;hook大法,

6.TracerPid 檢測:基本同上,檢測/proc/self/status的TracerPid 值。不為0就是被調(diào)試了,通過修改內(nèi)核文件/dev/block/mmcblk0/boot中TracerPid函數(shù)硬編碼實現(xiàn);程序建立子線程附加自己,如果TracerPid值為0則退出;。

7.斷點檢測:rtld_db_dlactivity函數(shù):這個函數(shù)默認情況下為空函數(shù),這里的值應(yīng)該為0,而當有調(diào)試器時,這里會被改為斷點指令;獲取該函數(shù)地址,將其nop。

8.時間檢測,單步調(diào)試陷阱:app主動設(shè)置斷點,并在代碼中注冊斷點信號處理函數(shù),未被調(diào)試(執(zhí)行斷點發(fā)出信號—進入處理信號函數(shù)—NOP替換斷點—退回PC),被調(diào)試,執(zhí)行調(diào)試程序的處理函數(shù),他會恢復(fù)目標處指令失敗,然后回退PC,進入死循環(huán)。

9.利用ida先截獲信號的特性:將關(guān)鍵函數(shù)放在信號處理函數(shù)中,未被執(zhí)行則被調(diào)試。

10.雙進程守護:主進程a,fork子進程b,b進程ptrace a的所有線程;修改安卓源碼;

11.通過修改so文件程序頭的特征,so二進制文件開頭一般是.ELF,frida執(zhí)行前會檢測該二進制數(shù)據(jù)是否為.ELF,但是該數(shù)據(jù)在so執(zhí)行中并不會使用,所以可以通過將so文件程序頭中的.ELF特征更改,這樣在frida使用attch方式附加時會直接崩潰;通過frida -U -f app_packeageName --no-pause啟動app,原因是frida代碼文件校驗?zāi)J絾栴}。

12.通過frida中findExportByName函數(shù)校驗漏洞:frida在使用該函數(shù)時會獲取linker中的__dl__Z17solist_get_somainv的返回值,并且未經(jīng)過為空校驗直接使用,所以將該函數(shù)返回值改為0,frida腳本中只要使用到了findExportByName就會崩潰(frida在hookJava函數(shù)時一定會調(diào)用),該函數(shù)在正常程序執(zhí)行中大概率不會用到。

Java層的雙進程通過xposed hook應(yīng)該可以解決(xposed是通過重寫zygote進程實現(xiàn)hook,理論上可以攔截所有Java層的操作);so層的可以在該so剛加載時就附加,然后修改fork操作(未實踐)?;蛘呔帉懸粋€so庫,里面重寫ptrace和dlopen函數(shù),重寫的函數(shù)里面最后在調(diào)用真正的系統(tǒng)函數(shù),加載該庫。

分類:

frida檢測:

1.TracerPid 檢測? ? ? ? ? 2.進程名檢測? ? ? ? 3.端口檢測? ? ? ? 4.已加載庫文件檢測: /proc/self/maps 目錄是否包含frida關(guān)鍵字? ? ? ?

5.通過獲取 libart.so 的函數(shù)遍歷函數(shù)表(該函數(shù)包含每個so函數(shù)的地址),判斷每個加載的so函數(shù)開頭是否為0xd61f020058000050(firda實現(xiàn)hook是通過inline hook插入的代碼特征)? ? ? ?

6.java層檢測:frida hook java層API是通過將其轉(zhuǎn)換為native函數(shù)在進行hook,可以判斷java函數(shù)的屬性是否為native函數(shù)來檢測

Android風(fēng)控

????????風(fēng)險控制,為了解決和預(yù)防將要發(fā)生,或者可能發(fā)生的一些危險情況,從而減輕損失。

? ? ? ? 注:并不完全是新內(nèi)容,選讀,因為近期面試遇到過不少,所以自己學(xué)學(xué)之后打算寫個筆記加深一下印象。

蜜罐數(shù)據(jù):當發(fā)現(xiàn)作弊以后返回的數(shù)據(jù)是非正常的數(shù)據(jù),可能存在埋點等信息,比如在視頻的隨機幀中添加標識,水印等,返回錯誤,重復(fù)的數(shù)據(jù)。

IP限制:當一個IP請求過量或過于頻繁時,返回錯誤數(shù)據(jù)或者蜜罐數(shù)據(jù)。

設(shè)備指紋:設(shè)備指紋的核心是使用設(shè)備的唯一識別碼,就像每個人的身份證號碼一樣。

java函數(shù)獲?。篠ettings. Secure / Global .getString(context.getContentResolver(),Settings.Secure.ANDROID_ID)

黑灰產(chǎn)通過協(xié)議逆向,實現(xiàn)批量注冊等“薅羊毛”行為,可通過網(wǎng)絡(luò)數(shù)據(jù)包中的設(shè)備指紋判斷,是否為同一設(shè)備,短時間內(nèi)大量注冊賬號,從而判定是否遭到黑產(chǎn)攻擊。

App環(huán)境信息:可以通過該設(shè)備運行環(huán)境的信息,將用戶劃分為 可疑設(shè)備 與 黑產(chǎn)設(shè)備。

1.root檢測:su權(quán)限,文件檢測;掃描 magisk 關(guān)鍵字;maps檢測等。

2.Hook檢測:主流hook框架Frida與xposed檢測上報。

3.沙箱檢測:判斷APK的私有路徑是否為 /data/data/包名;

Android hook、檢測及對抗相關(guān)

4.自定義rom檢測:需要有手機的驅(qū)動源碼才能自定義rom,通過對比md5值等檢測是否存在自定義rom。

5.查殺分離:當當前設(shè)備被服務(wù)器判定為黑產(chǎn)時,不會立即封殺,而是延時幾小時或者幾天在封殺,防止黑產(chǎn)一次一步步摸清風(fēng)控判斷依據(jù)。

6.心跳包&用戶行為檢測:在app剛跑來就與服務(wù)器建立socket連接,每隔一段時間發(fā)送一個心跳包,如果通過單純的逆向網(wǎng)絡(luò)協(xié)議實現(xiàn)算法接口,再通過PC發(fā)送數(shù)據(jù)的話,服務(wù)端在長時間沒有收到用戶的心跳包后,就可以將此設(shè)備判定為黑產(chǎn)設(shè)備。用戶通過逆向字節(jié)寫的點擊框架,可能沒有一點多余的操作,如正常用戶的滑動屏幕,點擊時間間隔,屏幕點擊坐標等,也可以以此作為風(fēng)控判定標準。

7.異常&行為埋點:正常用戶點擊登入接口時,在之前肯定會打開app的登入頁面,可以在登入頁面設(shè)置埋點,發(fā)送特定的數(shù)據(jù)包給服務(wù)器,如果用戶只發(fā)送了登入的數(shù)據(jù)包,或者發(fā)送的埋點數(shù)據(jù)不足時,可以此判定該設(shè)備為黑產(chǎn)設(shè)備。

Android 進程注入

動態(tài)注入? ? ??

????????由于Linux的進程機制,每個進程在安裝后都會分配一個獨享的UID,所以要想達到進程注入,需要拿到系統(tǒng)的root權(quán)限,之后總體流程和PC端大同小異;

獲取進程pid

附加進程? ? ????????????????:Attch(pid)

保存目標進程寄存器? :GetRegs(pid,&SaveRegister)

目標進程內(nèi)申請空間? :通過mmap映射申請,與binder差不太多

寫入shell? ? ? ? ? ? ? ? ?? ?:

修改PC寄存器,

執(zhí)行shell。

靜態(tài)注入

? ? ? ? 通過修改ELF文件實現(xiàn),文章來源地址http://www.zghlxwxcb.cn/news/detail-456887.html

到了這里,關(guān)于Android hook、檢測及對抗相關(guān)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • android 如何進行內(nèi)存泄漏檢測及解決方法

    內(nèi)存泄漏是在Android開發(fā)中常見的問題之一,它可能導(dǎo)致應(yīng)用的內(nèi)存占用逐漸增加,最終影響應(yīng)用的性能和穩(wěn)定性。以下是一些常見的方法來進行內(nèi)存泄漏檢測和解決: 1. 使用工具進行內(nèi)存泄漏檢測: Android Profiler: Android Studio提供的Android Profiler工具可以幫助您監(jiān)視應(yīng)用的內(nèi)

    2024年02月07日
    瀏覽(41)
  • Android 源碼淺析:Leakcanary 內(nèi)存泄漏檢測的好幫手

    我們一起來分析一下大名鼎鼎的 Leakcanary, 想必作為 Android 開發(fā)都多多少少接觸過,新版本的 Leakcanary 也用 Kotlin 重寫了一遍,最近詳細查看了下源碼,分享一下。 tips:本來是只想分析下內(nèi)存泄漏檢測部分,但寫著寫著就跑偏了,因為內(nèi)存泄漏的檢測難點在于對對象生命周期

    2024年02月02日
    瀏覽(21)
  • 第116天:免殺對抗-EDR&Syscall-hook&DLL反射注入&白加黑&隱寫分離&加載器

    第116天:免殺對抗-EDR&Syscall-hook&DLL反射注入&白加黑&隱寫分離&加載器

    知識點 演示案例: 總結(jié)

    2024年02月16日
    瀏覽(21)
  • 和MATLAB相關(guān)的設(shè)置斷點的快捷鍵

    一個朋友在修改錯誤的時候,有個操作震驚到我了。 他把迭代次數(shù)從1000減小到100,就可以快速仿真完。 廢話不多說,直接上快捷鍵。 F12:設(shè)置或者清楚斷點。 F5:運行 F10和F11都是步進,但是兩者有區(qū)別。 F10在步進時不進入函數(shù)調(diào)用。 F11在步進時進入函數(shù)調(diào)用。 shift+F11:

    2024年02月01日
    瀏覽(10)
  • OpenCV——八鄰域斷點檢測

    OpenCV——八鄰域斷點檢測

    OpenCV——八鄰域斷點檢測由CSDN點云俠原創(chuàng),爬蟲自重。如果你不是在點云俠的博客中看到該文章,那么此處便是不要臉的爬蟲。 圖1 八鄰域示意圖 圖2 八鄰域?qū)?yīng)坐標關(guān)系 ??首先將圖像進行二值化,然后檢測以 P 1 P_1 P 1 ? 為中心的它的八個領(lǐng)域, P 2 + P 3 + P 4 + P 5 + P 6

    2024年01月19日
    瀏覽(14)
  • CVPR2023對抗攻擊相關(guān)論文

    CVPR2023對抗攻擊相關(guān)論文

    Feature Separation and Recalibration for Adversarial Robustness 論文鏈接:http://arxiv.org/abs/2303.13846v1 代碼地址:GitHub - wkim97/FSR: Feature Separation and Recalibration (CVPR 2023) 摘要:由于特征層面的擾動積累,深度神經(jīng)網(wǎng)絡(luò)容易受到對抗性攻擊,許多研究通過停用導(dǎo)致模型錯誤預(yù)測的非魯棒特征激活

    2024年02月09日
    瀏覽(24)
  • React 中與生命周期相關(guān)的 Hooks 及其使用示例

    React 16.8 引入了 Hooks 的概念,使得函數(shù)組件也可以使用 state 和生命周期等特性。與生命周期相關(guān)的 Hooks 主要有以下三個: useEffect useEffect 是最常用的一個 Hook,它可以用來替代 class 組件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 這三個生命周期函數(shù)。useEffect 的作

    2024年04月14日
    瀏覽(17)
  • 生成對抗網(wǎng)絡(luò)與計算機視覺:提升對象檢測與識別能力

    計算機視覺技術(shù)在過去的幾年里取得了顯著的進展,這主要是由于深度學(xué)習(xí)技術(shù)的蓬勃發(fā)展。深度學(xué)習(xí)技術(shù)在計算機視覺領(lǐng)域的應(yīng)用主要集中在以下幾個方面: 對象檢測:通過在圖像中識別和定位特定的對象,如人臉、車輛、建筑物等。 圖像分類:通過將圖像分為多個類別

    2024年02月22日
    瀏覽(30)
  • 【爬蟲JS逆向-工具篇】瀏覽器內(nèi)存漫游加密參數(shù)Hook實戰(zhàn)教程

    【爬蟲JS逆向-工具篇】瀏覽器內(nèi)存漫游加密參數(shù)Hook實戰(zhàn)教程

    【作者主頁】: 吳秋霖 【作者介紹】:Python領(lǐng)域優(yōu)質(zhì)創(chuàng)作者、阿里云博客專家、華為云享專家。長期致力于Python與爬蟲領(lǐng)域研究與開發(fā)工作! 【作者推薦】:對JS逆向感興趣的朋友可以關(guān)注《爬蟲JS逆向?qū)崙?zhàn)》,對分布式爬蟲平臺感興趣的朋友可以關(guān)注《分布式爬蟲平臺搭建

    2024年02月22日
    瀏覽(23)
  • Android Hook技術(shù)學(xué)習(xí)——常見的hook技術(shù)方案

    Android Hook技術(shù)學(xué)習(xí)——常見的hook技術(shù)方案

    最近一段時間在研究Android加殼和脫殼技術(shù),其中涉及到了一些hook技術(shù),于是將自己學(xué)習(xí)的一些hook技術(shù)進行了一下梳理,以便后面回顧和大家學(xué)習(xí)。 本文第二節(jié)主要講述編譯原理,了解編譯原理可以幫助進一步理解hook技術(shù) 本文第三節(jié)主要講述NDK開發(fā)的一些基礎(chǔ)知識 本文第四

    2024年02月12日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包