日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )

發(fā)布時間:2025/6/17 Android 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 ) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 一、DexPrepare.cpp 中 rewriteDex() 方法分析
  • 二、DvmDex.cpp 中 dvmDexFileOpenPartial() 方法分析 ( 脫殼點 )
  • 三、DexFile.cpp 中 dexFileParse() 方法分析 ( 脫殼點 )

前言


上一篇博客 【Android 逆向】整體加固脫殼 ( DEX 優(yōu)化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函數(shù)分析 ) 中 , 分析了 DexPrepare.cppdvmContinueOptimizati() 方法 , 在其中調(diào)用了 rewriteDex() 方法 , 重寫 DEX 文件 ;

本篇博客繼續(xù)分析 DexPrepare.cpprewriteDex() 方法 ;





一、DexPrepare.cpp 中 rewriteDex() 方法分析



第一個參數(shù) u1* addr 是加載到內(nèi)存中的 dex 文件的首地址 ;

第二個參數(shù) int len 是內(nèi)存中的 dex 文件的字節(jié)長度 ;

static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,DexClassLookup** ppClassLookup, DvmDex** ppDvmDex)

dvmDexFileOpenPartial 函數(shù)是 脫殼點 函數(shù) , 通過該函數(shù)定位脫殼點 , 然后進行脫殼操作 ;

/** 既然可以直接讀取DEX文件,那么創(chuàng)建一個DexFile結(jié)構(gòu)* 為了它。*/if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) {ALOGE("Unable to create DexFile");goto bail;}

DexPrepare.cpp 中 rewriteDex() 方法源碼 :

/** 對內(nèi)存映射的DEX文件執(zhí)行就地重寫。* * 如果這是從短期子進程(dexopt)調(diào)用的,我們可以* 瘋狂地加載類和分配內(nèi)存。當(dāng)天氣好的時候* 調(diào)用以準(zhǔn)備字節(jié)數(shù)組中提供的類,我們可能需要* 要保守一點。* * 如果“ppClassLookup”為非空,則為指向新分配的* DexClassLookup將在成功時返回。* * 如果“ppDvmDex”為非空,則將創(chuàng)建新分配的DvmDex結(jié)構(gòu)* 成功返回。*/ static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,DexClassLookup** ppClassLookup, DvmDex** ppDvmDex) {DexClassLookup* pClassLookup = NULL;u8 prepWhen, loadWhen, verifyOptWhen;DvmDex* pDvmDex = NULL;bool result = false;const char* msgStr = "???";/* 如果索引的字節(jié)順序錯誤,請立即交換它 */if (dexSwapAndVerify(addr, len) != 0)goto bail;/** 既然可以直接讀取DEX文件,那么創(chuàng)建一個DexFile結(jié)構(gòu)* 為了它。*/if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) {ALOGE("Unable to create DexFile");goto bail;}/** 創(chuàng)建類查找表。這最終將被追加* 直到最后。奧德克斯。* * 我們從DexFile創(chuàng)建一個臨時鏈接,以便* 類加載,如下所示。*/pClassLookup = dexCreateClassLookup(pDvmDex->pDexFile);if (pClassLookup == NULL)goto bail;pDvmDex->pDexFile->pClassLookup = pClassLookup;/** 如果我們不打算驗證或優(yōu)化這些類,* 加載它們沒有任何價值,所以盡早退出。*/if (!doVerify && !doOpt) {result = true;goto bail;}prepWhen = dvmGetRelativeTimeUsec();/** 加載在此DEX文件中找到的所有類。如果它們無法加載* 由于某些原因,它們不會得到驗證(這是應(yīng)該的)。*/if (!loadAllClasses(pDvmDex))goto bail;loadWhen = dvmGetRelativeTimeUsec();/** 創(chuàng)建字節(jié)碼優(yōu)化器使用的數(shù)據(jù)結(jié)構(gòu)。* 我們需要在幾個類中查找方法,因此這可能會導(dǎo)致* 一點類加載。我們通常在VM初始化期間執(zhí)行此操作,但是* 對于dexopt on core。jar操作的順序變得有點棘手,* 所以我們把它推遲到這里。*/if (!dvmCreateInlineSubsTable())goto bail;/** 驗證并優(yōu)化DEX文件(命令行)中的所有類* (如果允許的話)。* * 這是最大的努力,所以dexopt真的沒有辦法* 在這一點上失敗。*/verifyAndOptimizeClasses(pDvmDex->pDexFile, doVerify, doOpt);verifyOptWhen = dvmGetRelativeTimeUsec();if (doVerify && doOpt)msgStr = "verify+opt";else if (doVerify)msgStr = "verify";else if (doOpt)msgStr = "opt";ALOGD("DexOpt: load %dms, %s %dms, %d bytes",(int) (loadWhen - prepWhen) / 1000,msgStr,(int) (verifyOptWhen - loadWhen) / 1000,gDvm.pBootLoaderAlloc->curOffset);result = true;bail:/** 成功后,歸還來電者要求的物品。*/if (pDvmDex != NULL) {/* break link between the two */pDvmDex->pDexFile->pClassLookup = NULL;}if (ppDvmDex == NULL || !result) {dvmDexFileFree(pDvmDex);} else {*ppDvmDex = pDvmDex;}if (ppClassLookup == NULL || !result) {free(pClassLookup);} else {*ppClassLookup = pClassLookup;}return result; }

源碼路徑 : /dalvik/vm/analysis/DexPrepare.cpp





二、DvmDex.cpp 中 dvmDexFileOpenPartial() 方法分析 ( 脫殼點 )



該函數(shù)中的 參數(shù) const void* addr 是 dex 文件在內(nèi)存中的起始地址 ;

在調(diào)用的 dexFileParse 函數(shù)中 , 也可以獲取到 dex 文件在內(nèi)存中的首地址 ;


DvmDex.cpp 中 dvmDexFileOpenPartial() 方法源碼 :

/** 為“部分”DEX創(chuàng)建DexFile結(jié)構(gòu)。這是一個在* 被優(yōu)化的過程。優(yōu)化標(biāo)頭未完成* 我們沒有任何輔助數(shù)據(jù)表,所以我們必須這樣做* 初始化過程略有不同。* * 錯誤時返回非零。*/ int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex) {DvmDex* pDvmDex;DexFile* pDexFile;int parseFlags = kDexParseDefault;int result = -1;/* -- 文件不完整,尚未計算新校驗和if (gDvm.verifyDexChecksum)parseFlags |= kDexParseVerifyChecksum;*/pDexFile = dexFileParse((u1*)addr, len, parseFlags);if (pDexFile == NULL) {ALOGE("DEX parse failed");goto bail;}pDvmDex = allocateAuxStructures(pDexFile);if (pDvmDex == NULL) {dexFileFree(pDexFile);goto bail;}pDvmDex->isMappedReadOnly = false;*ppDvmDex = pDvmDex;result = 0;bail:return result; }

源碼路徑 : /dalvik/vm/DvmDex.cpp





三、DexFile.cpp 中 dexFileParse() 方法分析 ( 脫殼點 )



/** 解析優(yōu)化或未優(yōu)化的。存儲在內(nèi)存中的dex文件。這是* 在字節(jié)排序和結(jié)構(gòu)對齊修復(fù)后調(diào)用。* * 成功后,返回新分配的文件。*/ DexFile* dexFileParse(const u1* data, size_t length, int flags) {DexFile* pDexFile = NULL;const DexHeader* pHeader;const u1* magic;int result = -1;if (length < sizeof(DexHeader)) {ALOGE("too short to be a valid .dex");goto bail; /* bad file format */}pDexFile = (DexFile*) malloc(sizeof(DexFile));if (pDexFile == NULL)goto bail; /* alloc failure */memset(pDexFile, 0, sizeof(DexFile));/** Peel off the optimized header.*/if (memcmp(data, DEX_OPT_MAGIC, 4) == 0) {magic = data;if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {ALOGE("bad opt version (0x%02x %02x %02x %02x)",magic[4], magic[5], magic[6], magic[7]);goto bail;}pDexFile->pOptHeader = (const DexOptHeader*) data;ALOGV("Good opt header, DEX offset is %d, flags=0x%02x",pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags);/* parse the optimized dex file tables */if (!dexParseOptData(data, length, pDexFile))goto bail;/* ignore the opt header and appended data from here on out */data += pDexFile->pOptHeader->dexOffset;length -= pDexFile->pOptHeader->dexOffset;if (pDexFile->pOptHeader->dexLength > length) {ALOGE("File truncated? stored len=%d, rem len=%d",pDexFile->pOptHeader->dexLength, (int) length);goto bail;}length = pDexFile->pOptHeader->dexLength;}dexFileSetupBasicPointers(pDexFile, data);pHeader = pDexFile->pHeader;if (!dexHasValidMagic(pHeader)) {goto bail;}/** 驗證校驗和。這相當(dāng)快,但確實需要* 觸摸DEX文件中的每個字節(jié)。基本校驗和在* 字節(jié)交換和索引優(yōu)化。*/if (flags & kDexParseVerifyChecksum) {u4 adler = dexComputeChecksum(pHeader);if (adler != pHeader->checksum) {ALOGE("ERROR: bad checksum (%08x vs %08x)",adler, pHeader->checksum);if (!(flags & kDexParseContinueOnError))goto bail;} else {ALOGV("+++ adler32 checksum (%08x) verified", adler);}const DexOptHeader* pOptHeader = pDexFile->pOptHeader;if (pOptHeader != NULL) {adler = dexComputeOptChecksum(pOptHeader);if (adler != pOptHeader->checksum) {ALOGE("ERROR: bad opt checksum (%08x vs %08x)",adler, pOptHeader->checksum);if (!(flags & kDexParseContinueOnError))goto bail;} else {ALOGV("+++ adler32 opt checksum (%08x) verified", adler);}}}/** 驗證SHA-1摘要。(通常我們不想這樣做--* 摘要用于唯一標(biāo)識原始DEX文件,以及* 無法在索引被字節(jié)交換后計算以進行驗證* (并進行了優(yōu)化。)*/if (kVerifySignature) {unsigned char sha1Digest[kSHA1DigestLen];const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum) +kSHA1DigestLen;dexComputeSHA1Digest(data + nonSum, length - nonSum, sha1Digest);if (memcmp(sha1Digest, pHeader->signature, kSHA1DigestLen) != 0) {char tmpBuf1[kSHA1DigestOutputLen];char tmpBuf2[kSHA1DigestOutputLen];ALOGE("ERROR: bad SHA1 digest (%s vs %s)",dexSHA1DigestToStr(sha1Digest, tmpBuf1),dexSHA1DigestToStr(pHeader->signature, tmpBuf2));if (!(flags & kDexParseContinueOnError))goto bail;} else {ALOGV("+++ sha1 digest verified");}}if (pHeader->fileSize != length) {ALOGE("ERROR: stored file size (%d) != expected (%d)",(int) pHeader->fileSize, (int) length);if (!(flags & kDexParseContinueOnError))goto bail;}if (pHeader->classDefsSize == 0) {ALOGE("ERROR: DEX file has no classes in it, failing");goto bail;}/** Success!*/result = 0;bail:if (result != 0 && pDexFile != NULL) {dexFileFree(pDexFile);pDexFile = NULL;}return pDexFile; }

源碼路徑 : /dalvik/libdex/DexFile.cpp

總結(jié)

以上是生活随笔為你收集整理的【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 别揉我奶头一区二区三区 | 精品人妻一区二区三区四区不卡 | 国产情侣露脸自拍 | 久久三级 | 欧美一级片a | 日日草草 | 丁香花电影免费播放电影 | 深田咏美在线x99av | 中文字幕成人在线视频 | av成人在线免费观看 | 在线观看成人 | 成人做爰免费视频免费看 | 九九九久久久 | 丁五月 | 波多野一区 | 亚洲国产欧美一区 | 琪琪色在线视频 | 蜜桃一二三区 | 日日操夜夜操天天操 | 精品无码久久久久久久久果冻 | 91人妻一区二区三区蜜臀 | 黄色激情视频在线观看 | 丰满少妇一区二区 | 国产午夜精品无码一区二区 | 国产亚洲小视频 | 高跟鞋和丝袜猛烈xxxxxx | 国产欧美视频一区 | 最新中文字幕在线观看 | 日韩欧美高清视频 | 亚洲综合日韩在线 | 女女高潮h冰块play失禁百合 | 成人在线视频免费 | 香蕉视频黄色在线观看 | 国产污视频在线 | 欧美一二三区在线观看 | 久久b | 日韩av网站在线观看 | 精品国产免费一区二区三区 | 成人看片免费 | xxx国产在线观看 | 欧美激情在线观看一区 | 欧美成人免费在线观看视频 | 美女娇喘 | 亚洲第九十九页 | 一区二区免费在线观看 | 亚洲精品色 | 成年人爱爱视频 | 大黄网站在线观看 | 欧美成人一区二免费视频软件 | 日韩在线播放视频 | 成人在线观看小视频 | 婷婷色图 | 涩色网站 | 欧美一级α片 | 成人tv| 午夜精品久久久久久久蜜桃 | 欧美xxxxxhd| 日韩一区二区三免费高清在线观看 | 国产九色在线 | 久久成人在线视频 | 欧美第三页| 男女草逼视频 | 激情综合网婷婷 | www.蜜桃av.com| 东方欧美色图 | 97超视频在线观看 | 免费又黄又爽又色的视频 | 色五夜| 日韩精品极品视频免费观看 | 国产乱子伦一区二区 | 国产成人精品视频一区二区 | 插综合 | 欧美精品一二 | 黄色激情毛片 | 狠狠干b | 亚洲天堂久久久久 | 中国女人av | 国产女主播视频 | 国内自拍第一页 | 深夜视频一区二区三区 | 中文字幕无线码一区 | 香港三级日本三级韩国三级 | 国产精品三级在线观看无码 | 成人久久精品人妻一区二区三区 | 亚洲精品乱码久久久久久蜜桃91 | va在线视频 | 少妇毛片一区二区三区粉嫩av | 日本人的性生活视频 | 日本高清不卡二区 | 亚洲精品国产精品国自产网站按摩 | 四虎影视最新网址 | 一本加勒比波多野结衣 | 美攻壮受大胸奶汁(高h) | 伊人天天干 | 亚洲成av人片 | 1000部国产精品成人观看 | 午夜视频 | av免费网| 日韩午夜激情电影 |