成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Android逆向之路---脫殼360加固原理解析

ysl_unh / 3412人閱讀

摘要:如何使用呢,可以見我的的上一篇文章點(diǎn)我逆向之路脫殼加固與注意事項(xiàng)寫在最后偶爾聊聊技術(shù),偶爾聊聊逆向,偶爾聊聊生活不能總聊技術(shù)呀,下次一起聊點(diǎn)輕松的。

前言

眾所周知,上次說(shuō)到了如何脫殼360加固,大致意思就是安裝一個(gè)xposed插件,然后自動(dòng)就會(huì)脫殼了,那么這個(gè)插件是如何工作的呢,本次重點(diǎn)說(shuō)說(shuō)這個(gè)。

上次說(shuō)道了dumpDex脫殼360加固,其實(shí)先說(shuō)個(gè)大概,就是從ndk層和java層,適配不同的系統(tǒng),hook關(guān)鍵函數(shù),然后在運(yùn)行時(shí)將dex文件dump出來(lái)。

如果僅僅想知道如何使用,可以參見上一篇

點(diǎn)我:Android逆向之路---脫殼360加固、與xposed hook注意事項(xiàng)

需要的環(huán)境

無(wú),看文章就可以了解大致了

(當(dāng)然你要是想編譯下dumpDex項(xiàng)目,需要如下工具)

Android Studio

sdk ndk

入口

所有的程序執(zhí)行的時(shí)候都是有個(gè)入口的,dumpDex工程也不例外。
由于是個(gè)xposed插件,所以我們先看com.wrbug.dumpdex.XposedInit類。

public class XposedInit implements IXposedHookLoadPackage {

    //--------略---------

    @Override
    public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {
        PackerInfo.Type type = PackerInfo.find(lpparam);
        if (type == null) {
            return;
        }
        final String packageName = lpparam.packageName;
        //這里主要是各個(gè)app只管解析各個(gè)app自己的進(jìn)程的程序
        if (lpparam.packageName.equals(packageName)) {
            //首先在當(dāng)前app的指定目錄,創(chuàng)建好目錄,以便于一會(huì)兒脫殼存放dex文件
            String path = "/data/data/" + packageName + "/dump";
            File parent = new File(path);
            if (!parent.exists() || !parent.isDirectory()) {
                parent.mkdirs();
            }
            log("sdk version:" + Build.VERSION.SDK_INT);
            
            if (DeviceUtils.isOreo()) {
                //api為27或27版本的執(zhí)行下面一行,進(jìn)行脫殼
                OreoDump.init(lpparam);
            } else {
                //低版本api執(zhí)行下面一行進(jìn)行脫殼
                LowSdkDump.init(lpparam,type);
            }

        }
    }
}

已經(jīng)加好注釋,值得注意的就是,此處程序有分叉了,分別是 OreoDump.init()和LowSdkDump.init()
我們先看OreoDump.init方法

public class OreoDump {

    //--------略---------

    public static void init(final XC_LoadPackage.LoadPackageParam lpparam) {
        Native.dump(lpparam.packageName);
    }
}

跟著進(jìn)入Native.dump(),

注:不會(huì)android ndk也沒關(guān)系,可以繼續(xù)往下看

Native hook

以下可以先粗略的說(shuō)一下,主要就是進(jìn)入了ndk層進(jìn)行hook,然后進(jìn)行dump
進(jìn)入native.cpp文件里面找到JNICALL Java_com_wrbug_dumpdex_Native_dump方法。

由于切換到了c語(yǔ)言,所以我會(huì)幫大家刪除一些代碼的細(xì)枝末節(jié),只看主干。

再次聲明下,以下方法實(shí)在當(dāng)android版本為26或27的時(shí)候,會(huì)默認(rèn)進(jìn)行Native層脫殼

JNIEXPORT void JNICALL Java_com_wrbug_dumpdex_Native_dump
        (JNIEnv *env, jclass obj, jstring packageName) {

    //在這里作者考慮到了防止每次app啟動(dòng)的時(shí)候都會(huì)dump,因此保存了一個(gè)變量is_hook來(lái)記錄,如果hook過了的話就會(huì)退出程序
    static bool is_hook = false;
    char *p = (char *) env->GetStringUTFChars(packageName, 0);
    if (is_hook) {
        __android_log_print(ANDROID_LOG_INFO, TAG, "hooked ignore");
        return;
    }
    init_package_name(p);
    env->ReleaseStringChars(packageName, (const jchar *) p);
    

    //這里由于使用了第三方庫(kù),所以先執(zhí)行第三方庫(kù)的初始化操作,具體第三方庫(kù),見下文  
    ndk_init(env);
    
    //下面就是重點(diǎn)了,首先以RTLD_NOW模式打開動(dòng)態(tài)庫(kù)libart.so,拿到句柄
    void *handle = ndk_dlopen("libart.so", RTLD_NOW);
    if (handle == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, TAG, "Error: unable to find the SO : libart.so");
        return;
    }
    //根據(jù)不同的版本,拿到不同的對(duì)應(yīng)的加載的符號(hào)
    void *open_common_addr = ndk_dlsym(handle, get_open_function_flag());

    //--------略---------
    //略掉很多分支,多帶帶說(shuō)一個(gè),見下文
    if (registerInlineHook((uint32_t) open_common_addr, (uint32_t) get_new_open_function_addr(),
                           (uint32_t **) get_old_open_function_addr()) != ELE7EN_OK) {
        __android_log_print(ANDROID_LOG_ERROR, TAG, "register1 hook failed!");
        return;
    } else {
        __android_log_print(ANDROID_LOG_ERROR, TAG, "register1 hook success!");
    }
    //設(shè)置hook標(biāo)記為true
    is_hook = true;
}
registerInlineHook(
    (uint32_t) open_common_addr, (uint32_t) get_new_open_function_addr(),
                           (uint32_t **) get_old_open_function_addr())

已經(jīng)定位到函數(shù)的地址,接下來(lái)就是Hook替換以前的函數(shù),替換成我們自己定義的函數(shù),例如下面的函數(shù)

static void *new_arm64_open_common(uint8_t *base, size_t size, void *location,
                                   uint32_t location_checksum, void *oat_dex_file,
                                   bool verify,
                                   bool verify_checksum,
                                   void *error_meessage, void *verify_result) {
    //--------略---------
    //首先在程序運(yùn)行時(shí),保存dex,完成脫殼
    save_dex_file(base, size);
    //調(diào)用以前的函數(shù),保證程序正確執(zhí)行,
    void *result = old_arm64_open_common(base, size, location, location_checksum,
                                        oat_dex_file, verify, verify_checksum,
                                        error_meessage,
                                        verify_result);
    return result;
}
NDK層hook完畢

到此為止NDK層hook分析完畢,分別用了第三方庫(kù)hook了android指定版本的加載dex函數(shù)的方法,然后在hook的新函數(shù)里面添加到保存到dump目錄的函數(shù),達(dá)到脫殼
的目的。

ndk hook主要用到的庫(kù)

https://github.com/rrrfff/ndk_dlopen

https://github.com/ele7enxxh/Android-Inline-Hook

SDK層hook

回到入口的那個(gè)章節(jié),還記得嗎,還有一個(gè)LowSdkDump.init
這個(gè)是低版本的時(shí)候的邏輯

public static void init(final XC_LoadPackage.LoadPackageParam lpparam, PackerInfo.Type type) {
        //如果sdk是23,24,25,26,27之一,那么繼續(xù)使用native層hook
        if (DeviceUtils.supportNativeHook()) {
            Native.dump(lpparam.packageName);
        }
        //額。。。。。。。??赡馨俣瘸溴X了
        if (type == PackerInfo.Type.BAI_DU) {
            return;
        }
        //見下文說(shuō)明
        XposedHelpers.findAndHookMethod("android.app.Instrumentation", lpparam.classLoader, "newApplication", ClassLoader.class, String.class, Context.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                //執(zhí)行真正的dump方法,然后保存
                dump(lpparam.packageName, param.getResult().getClass());
                attachBaseContextHook(lpparam, ((Application) param.getResult()));
            }
        });
    }

上面的主要就是先檢測(cè)可不可以natvie層hook,可以的話優(yōu)先native層hook,
然后就是百度可能充錢了,當(dāng)然開個(gè)玩笑,這個(gè)可以大家自己嘗試。

接下來(lái)就是java層hook了,hook了加載類Instrumentation類,的newApplication方法,然后進(jìn)行dump.

還有attachBaseContextHook里面也是主要Hook ClassLoader的loadClass方法,

主要看java層的dump函數(shù)

private static void dump(String packageName, Class aClass) {
        Object dexCache = XposedHelpers.getObjectField(aClass, "dexCache");
        log("decCache=" + dexCache);
        Object o = XposedHelpers.callMethod(dexCache, "getDex");
        byte[] bytes = (byte[]) XposedHelpers.callMethod(o, "getBytes");
        String path = "/data/data/" + packageName + "/dump";
        File file = new File(path, "source-" + bytes.length + ".dex");
        if (file.exists()) {
            log(file.getName() + " exists");
            return;
        }
        FileUtils.writeByteToFile(bytes, file.getAbsolutePath());
    }
大功告成

代碼陸陸續(xù)續(xù)的看了一遍,可以嘗試畫一個(gè)流程圖了



后記

其實(shí)文中涉及到的具體的hook的函數(shù),需要我們具體的去看,去研讀android源碼。
這樣才能融匯貫通。

了解了系統(tǒng)是如何加載一個(gè)dex的,才能真真正正的理解如何攔截,如何從內(nèi)存dump出來(lái)。
dump的時(shí)候用的別人的庫(kù),的工具,都還好,主要是思路。如何找到關(guān)鍵點(diǎn),進(jìn)行dump。

如何使用呢,可以見我的的上一篇文章

點(diǎn)我:Android逆向之路---脫殼360加固、與xposed hook注意事項(xiàng)

寫在最后

偶爾聊聊技術(shù),偶爾聊聊逆向,偶爾聊聊生活

不能總聊技術(shù)呀,下次一起聊點(diǎn)輕松的。

博主還是一個(gè)懶散的博主。

關(guān)于我

個(gè)人博客:MartinHan的小站

博客網(wǎng)站:hanhan12312的專欄

知乎:MartinHan01

我的公眾號(hào):
程序技術(shù)指北

(剛開不久,最近在琢磨新東西,謹(jǐn)慎關(guān)注!)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72761.html

相關(guān)文章

  • Android逆向之路---脫殼360加固

    摘要:前言眾所周知,現(xiàn)在軟件在防止逆向采取了混淆,加殼等措施。這兩天在逆向一款的時(shí)候找到了一個(gè)不錯(cuò)的插件推薦給大家,下載地址點(diǎn)我下載前提環(huán)境過的手機(jī)文件下載地址在上方自動(dòng)脫殼安裝完成之后,在里面軟重啟,激活。 前言 眾所周知,現(xiàn)在軟件在防止逆向采取了混淆,加殼等措施。比如360加固,騰訊加固,梆梆加固等等。這兩天在逆向一款app的時(shí)候找到了一個(gè)不錯(cuò)的xposed插件推薦給大家, 下載地址:點(diǎn)...

    pkhope 評(píng)論0 收藏0
  • Android防護(hù)掃盲篇

    摘要:為了防止這種現(xiàn)象,我們可以對(duì)字節(jié)碼進(jìn)行混淆。動(dòng)態(tài)鏈接庫(kù)是目標(biāo)文件的集合,目標(biāo)文件在動(dòng)態(tài)鏈接庫(kù)中的組織方式是按照特殊方式形成的。 一、已知防護(hù)策略 1.不可或缺的混淆 Java 是一種跨平臺(tái)、解釋型語(yǔ)言,Java 源代碼編譯成的class文件中有大量包含語(yǔ)義的變量名、方法名的信息,很容易被反編譯為Java 源代碼。為了防止這種現(xiàn)象,我們可以對(duì)Java字節(jié)碼進(jìn)行混淆?;煜粌H能將代碼中的類...

    CastlePeaK 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

ysl_unh

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<