<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      GKLBB

      當你經(jīng)歷了暴風雨,你也就成為了暴風雨

      導航

      應用安全 --- PC安全 之 VMP2 IAT修復

      加密工具選擇

      vmp2.13.8

      加密選項

      • 內(nèi)存保護 (是):程序運行時,它的內(nèi)容會放在電腦的內(nèi)存里。這個選項就像是給內(nèi)存里的程序加了一個“障眼法”,防止破解者用特殊工具直接“偷看”內(nèi)存里的內(nèi)容,或者把程序從內(nèi)存里完整地復制出來。

      • 導入表保護 (是):程序需要調(diào)用很多系統(tǒng)功能(比如顯示窗口、讀寫文件),“導入表”就像是程序的功能“通訊錄”。這個選項會把這份通訊錄加密或藏起來,讓破解者搞不清楚你的程序到底調(diào)用了哪些系統(tǒng)功能,增加了分析難度。

      • 資源保護 (是):程序里包含的圖片、圖標、文字等“資源”也會被加密。就像把寶箱里的珠寶都用獨立的小盒子鎖起來,就算寶箱被打開了,里面的東西也拿不走。

      • 壓縮輸出文件 (快速):這個選項會把整個程序文件壓縮變小,就像用真空袋打包衣服一樣。“快速”意味著壓縮和解壓的速度都比較快,能稍微平衡文件大小和運行速度。

      代碼vm  表示啟用了一個“翻譯機”來保護代碼。  

      • 離開虛擬機時加密寄存器 (是):寄存器是CPU里用來臨時存放數(shù)據(jù)的小倉庫。當代碼從“火星文”模式切換回正常模式時,這個選項會立刻把小倉庫里的數(shù)據(jù)鎖起來,防止破解者偷看到關鍵的計算結(jié)果。

      • 檢查虛擬機對象的完整性 (是):這個“翻譯機”本身也會被保護起來。程序會時刻檢查它自己是否被破解者動了手腳,如果被修改了,程序就不干了。

      • 隱藏常量 (是):程序里的一些固定數(shù)值或字符串(比如一個密碼、一個網(wǎng)址)被稱為常量。這個選項會把它們都加密隱藏起來,讓破解者無法輕易在程序文件中找到這些敏感信息。

       

      殼運行到OEP的大致流程

      image

       通過虛假eip進入vmp1段的入口

       

       

      第一階段:尋找OEP(原始入口點)

      核心思路解析

      1. VMP的核心保護機制:VMP殼在程序啟動初期,會做大量的“準備工作”,比如解密自身的代碼、設置反調(diào)試陷阱等。其中非常關鍵的一步,就是使用 VirtualProtect 這個Windows API函數(shù)。

      2.  函數(shù)的作用:這個函數(shù)像一個“權限管家”,可以動態(tài)修改內(nèi)存區(qū)域的讀、寫、執(zhí)行權限。VMP利用它來抹除我們(分析者)在代碼區(qū)段和IAT(導入地址表)上設置的內(nèi)存訪問斷點。如果我們下的斷點被清除了,自然就無法中斷在關鍵位置。

      3. 斷點的不同類型

        • 內(nèi)存斷點:在某個內(nèi)存地址設置,一旦該地址被讀取、寫入或執(zhí)行,就會中斷。這種斷點容易被VirtualProtect清除。

        • 硬件斷點:由CPU直接支持,數(shù)量有限(通常4個),但更底層,更難被檢測。其中,硬件“訪問”和“寫入”斷點不容易被VMP檢測到,但硬件“執(zhí)行”斷點則會被VMP發(fā)現(xiàn)。

      利用以上原理,就可以設計出如下繞過VMP檢測、直達OEP的執(zhí)行流程。

      詳細執(zhí)行流程步驟

      以下是根據(jù)您提供的方法,整理出的完整、詳細的操作步驟:

      前提:使用OD(OllyDbg)或x64dbg等調(diào)試工具載入加了VMP 2.13.8殼的程序。

      第一步:首次運行與定位代碼段尾部

      1. 正常運行程序:直接在調(diào)試器中按 F9 鍵讓程序運行起來。程序會執(zhí)行VMP的外殼代碼,完成初始化,然后停在VMP自身的某個區(qū)段(例如截圖中提到的VMP1區(qū)段)。

      2. 找到代碼段末尾:切換到內(nèi)存窗口,找到程序的 .text(代碼段)。用鼠標滾輪或滾動條向下滾動,找到代碼段中最后一個非零字節(jié)數(shù)據(jù)的位置。

      3. 確定下斷點的位置:記下這個“最后一個有效值”的下一個地址。這個地址是代碼段的末尾,通常是代碼執(zhí)行流程中一個比較靠后的位置。

      第二步:設置硬件斷點并重載

      1. 設置硬件訪問斷點:在剛才記下的那個地址上,右鍵點擊,選擇“斷點” -> “硬件,訪問”。因為這個位置在代碼段的末尾,當VMP外殼代碼即將執(zhí)行完畢,準備跳轉(zhuǎn)到真正的程序代碼(OEP)時,很可能會訪問到這附近區(qū)域。

      2. 重載程序:在調(diào)試器中,點擊“重新開始”或按 Ctrl+F2,讓程序回到最初的加載狀態(tài)。這一步是為了讓我們設置的斷點能在VMP的初始化流程中生效。

      第三步:兩次中斷,繞過干擾

      1. 第一次中斷(F9):按下 F9 運行程序。程序會因為VMP外殼代碼在初始化過程中寫入數(shù)據(jù)到代碼段而觸發(fā)我們設置的硬件斷點,此時程序會中斷下來。

      2. 第二次中斷(F9):再次按下 F9 繼續(xù)運行。這里可能會遇到VMP為了迷惑分析者而故意設置的一些“干擾性”訪問,導致斷點再次被觸發(fā)。根據(jù)原文描述,這次中斷是“斷在干擾時”。我們只需再次忽略,繼續(xù)運行即可。

      第四步:設置內(nèi)存斷點,直達OEP

      1. 設置內(nèi)存訪問斷點:經(jīng)過前兩輪的硬件斷點中斷,VMP的“權限修改”階段(即調(diào)用 VirtualProtect 清除內(nèi)存斷點)很可能已經(jīng)過去了。此時,我們可以在程序的整個代碼段(.text段)上設置一個內(nèi)存訪問斷點。

      2. 最后一次運行(F9):再次按下 F9 運行程序。由于VMP外殼已經(jīng)完成了它的使命,正準備跳轉(zhuǎn)到程序的原始入口點(OEP)去執(zhí)行真正的程序邏輯,這個跳轉(zhuǎn)動作必然會“訪問”到代碼段。

      3. 成功中斷在OEP:此時,我們設置的內(nèi)存訪問斷點會被觸發(fā),程序會精準地停在OEP處。這個時候,調(diào)試器里顯示的代碼就是程序原本的、未被加密的開始代碼了。

      總結(jié):這個流程巧妙地利用了硬件斷點不易被檢測的特性,先讓程序跑過最危險的反調(diào)試和反內(nèi)存斷點階段,然后再利用內(nèi)存斷點覆蓋范圍廣的優(yōu)勢,精準地捕捉到從外殼代碼跳轉(zhuǎn)到原始代碼的那一瞬間,從而成功定位到OEP。

       

      簡要說明

      只要過了這個清除我們在代碼段 和 IAT 設置的內(nèi)存訪問斷點 VirtualProtect 函數(shù)  就可以在代碼段設置訪問斷點了。繞過方法就是設置的 硬件訪問 和 硬件寫入 斷點并不會被殼檢測到,但是硬件執(zhí)行斷點會被檢測到。

      完整執(zhí)行一次程序,程序可以正常運行并自動終止,沒有加反調(diào)試。

      點擊M按鈕在text右鍵在cpu中查看

      將右鍵分析,刪除分析,就可以正常顯示匯編指令

      拖到最后有數(shù)據(jù)的hex的內(nèi)存區(qū)域(最后一個不是00的值),右鍵設置硬件斷點

      重新運行OD中的程序,按下兩次執(zhí)行按鈕(一次斷在寫入時,一次斷在干擾時),繞過vmp段內(nèi)兩次內(nèi)存斷點檢查代碼

      點擊M按鈕在text右鍵設置內(nèi)存訪問斷點

      執(zhí)行后自動斷在OEP位置,完成OEP查找

       

      第二階段:API調(diào)用的類型分析

      1. 識別VMP的調(diào)用模式:發(fā)現(xiàn)VMP(VMProtect的縮寫)主要通過CALLJMPMOV等指令的變體來間接調(diào)用API,這些指令的機器碼長度通常是5到6字節(jié)。

          有這三種

           CALL [IAT]      //以下簡稱十六進制的 FF15

          JMP [IAT]      //FF25

           mov e?? , [iat]   //MOV型

       

      CALL [IAT]:

      加殼前

      image

       后

      image

       從ff15變?yōu)?0e8,后面地址變?yōu)関mp的殼代碼。這里的50就是補碼

      我們觀察到長度不變,因為so文件一處長度發(fā)生改變所有地址偏移都要變化引擎雪崩效應

       

      JMP [IAT]:

      image

      image

       

       mov e??,[IAT]

      image

      image

       

      發(fā)現(xiàn)了一個VMP加殼的細節(jié):對于 mov eax, [地址] 這種5字節(jié)長的API調(diào)用,VMP會用一個同樣是5字節(jié)長的指令去替換它。因為尺寸剛好匹配,所以VMP不需要進行任何“填充”或“補碼”操作。

      如果VMP要用一個5字節(jié)的安保零件去替換一個6字節(jié)的舊零件,那么就會多出1字節(jié)的空隙。為了不讓整個機器“錯位”,VMP就必須用一個沒有意義的“填充物”(專業(yè)術語叫補碼Padding,比如圖中的 nop 指令)把這個空隙填上。

       因為重定向的代碼為E8,是 5 字節(jié)的,因此殼會隨機填充一個字節(jié)。補碼上面或者下面都有可能。

      關鍵的部分就是我們?nèi)绾沃兰用芮暗母袷?/p>

       

      手動一步一步追蹤:

      首先我們先要知道,被重定向的API,進入了 VMP0 區(qū)段,再經(jīng)過一系列的運算,得到真實的API的地址,放入堆棧,然后通過 RET 的方法進入真實的API

      image

       這是重定向CALL ,一直F7就可以到這一步。

      但是手動跟著特工在復雜的“中轉(zhuǎn)站”里一步步走(用F7單步跟蹤)太累了,而且容易跟丟。

       

      所以介紹了一個絕佳的自動化方法繞過vmp代碼:

      使用OD(OllyDbg調(diào)試器)的“跟蹤步入”功能,并設置一個聰明的條件。

      這個條件是:
      EIP 位于范圍外 VMP0段首地址 ... VMP0段尾地址

      這句話的通俗解釋就是告訴調(diào)試器:

      “嘿,老兄!接下來我要追蹤一段代碼。我不關心它在‘VMP0中轉(zhuǎn)站’里面是怎么跑的,里面太復雜了。你就讓它在里面盡情地跑吧。但是,只要它的腳步一踏出‘VMP0中轉(zhuǎn)站’的范圍,你必須立刻停下來,告訴我它跑到了哪里!

      第三步:實際操作流程

      1. 設置好“崗哨”:把上面那個“EIP位于范圍外”的條件設置好。作者強調(diào)這個條件必須全程開啟,因為你的脫殼腳本也要靠它來自動分析。

      2. 找到一個假:隨便找一個被VMP處理過的CALL指令。

      3. 手動 F7 步入:手動按一下F7,你(EIP)就進入了“VMP0中轉(zhuǎn)站”的入口。

      4. 啟動自動追蹤:點擊OD的“跟蹤步入”功能。

      5. 自動完成!:調(diào)試器會飛速執(zhí)行“中轉(zhuǎn)站”里所有的復雜代碼,因為EIP一直在VMP0區(qū)段內(nèi),條件不滿足,所以不會停。直到最后執(zhí)行了那條RET指令,EIP一下子跳出了VMP0區(qū)段,到達了真實的API地址(比如winspool.ClosePrinter)。

        • “啪!” 條件滿足,調(diào)試器立刻停了下來。

      最終效果:OD直接就停在了真實API的第一句代碼上,你根本不需要去關心VMP在中間到底做了什么復雜的運算。

      總結(jié)一下:

      這段話的核心就是教你如何利用調(diào)試器的一個條件跟蹤功能,來跳過VMP復雜、繁瑣的解密過程,實現(xiàn)“一鍵直達”被隱藏的真實API地址。這個方法是編寫自動化脫殼腳本的基礎和關鍵。

       

      這個操作的核心是利用OD的運行跟蹤 (Run trace) 功能,并為其設置一個暫停條件

      第一步:準備工作 - 找到VMP0區(qū)段的地址范圍

      在設置條件之前,你必須先知道“VMP0中轉(zhuǎn)站”的大門和后門在哪里。

      1. 打開內(nèi)存映射窗口:在OD的主界面,點擊頂部菜單欄的 "M" 圖標(Memory Map),或者按快捷鍵 Alt+M

      2. 找到VMP0區(qū)段:在彈出的內(nèi)存窗口中,找到那個名為 .vmp0 或者 VMP0 的區(qū)段。

      3. 記錄地址

        • 記下這一行的 “基址 (Address)”,這就是 “VMP0段首地址”

        • 記下這一行的 “大小 (Size)”

        • 計算出 “VMP0段尾地址”。公式是:基址 + 大小 - 1

        舉例:
        如果基址是 00B50000,大小是 00028000
        那么首地址就是 00B50000
        尾地址就是 00B50000 + 00028000 - 1 = 00B77FFF

        現(xiàn)在你手里就有了設置條件所需的兩個關鍵地址了。

      第二步:設置“跟蹤暫停”條件

      1. 打開調(diào)試選項:點擊OD頂部菜單欄的調(diào)試 ,設置條件

      2. 切換到“跟蹤”選項卡:在彈出的對話框中,點擊 “跟蹤 (Trace)” 選項卡。

      3. 進行設置

        • ① 勾選復選框“EIP 位于范圍外”

        • ② 填入地址:將在第一步中得到的 “VMP0段首地址” 和 “VMP0段尾地址” 填入后面的兩個輸入框中。

        • ③ 確認:點擊“確定 (OK)”保存設置。

        現(xiàn)在,OD就已經(jīng)被你設置成一個聰明的“哨兵”了。

      第三步:執(zhí)行跟蹤

      現(xiàn)在萬事俱備,可以開始實際操作了。

      1. 找到一個重定向CALL:在OD的反匯編窗口(CPU窗口),找到一個被VMP處理過的CALL指令,比如 CALL 00B51234(這個地址在VMP0區(qū)段內(nèi))。

      2. 右鍵設置新的EIP,直接從這里開始執(zhí)行。

      3. 手動步入 (關鍵!):按下鍵盤上的 F7 鍵。這時,你會進入VMP0區(qū)段的內(nèi)部,EIP(指令指針)現(xiàn)在就在“中轉(zhuǎn)站”里面了。這一步是必須的,因為你得先進去,才能談“出來的時候暫停”。

      4. 啟動運行跟蹤:現(xiàn)在EIP已經(jīng)在VMP0區(qū)段內(nèi),你可以啟動自動跟蹤了。

        • 點擊頂部菜單欄的 “調(diào)試 (Debug)” -> “運行跟蹤 (Run trace)” -> “步入 (Into)”

        • 或者直接使用快捷鍵 Ctrl + F11 (這是運行跟蹤的快捷鍵,它會應用你在選項中設置的暫停條件)。 注:原文提到的是“跟蹤步入”,在OD中,“運行跟蹤”是實現(xiàn)這一功能的正式名稱。

      5. 等待自動暫停:按下Ctrl+F11后,OD會開始飛速執(zhí)行代碼。你可能會看到屏幕閃爍,OD會記錄下成千上萬條指令。但你不用管它,因為它會在滿足你設定的條件時自動停下。

        當VMP內(nèi)部的代碼執(zhí)行到最后那條 RET 指令時,EIP會一下子跳出VMP0區(qū)段的范圍,跳到真實的API函數(shù)地址上。

        “啪!” 哨兵發(fā)現(xiàn)EIP跑到了“范圍外”,OD立刻自動暫停

      最終結(jié)果

      此時,OD會停下來,而光標所在的位置,就是那個 ,例如 winspool.ClosePrinter。你就成功地跳過了所有復雜的中間過程,直達目的地。

      記得,如原文所說,這個調(diào)試選項要**“全程開著”**,這樣你就可以對每一個需要分析的CALL重復“F7步入 -> Ctrl+F11運行跟蹤”這個流程,極大地提高脫殼效率。

      image

       

      image

       

       

      腳本自動化追蹤的原理:

      原始call類型判斷

      判斷MOV型

      執(zhí)行上述跟蹤步入步驟,開始執(zhí)行加密call

      執(zhí)行前,將除了ESP,EBP以外的寄存器全部置0

      RET出來的第一句是在代碼段。API放入寄存器的相應位置。

       

      若已知不是MOV型:

      執(zhí)行上述跟蹤步入步驟,開始執(zhí)行加密call

      將 [ESP]置1,[ESP+4]置2,[ESP+8]置3,[ESP+C]置4
      執(zhí)行完vmp后 RET到API,且[ESP]=1:FF25型,補碼在后
      RET到API,且[ESP+4]=2:FF15型,補碼在前
      RET到API,且[ESP+4]=1:FF15型,且補碼在后
      RET到API,且[ESP+4]=3:FF25型,且補碼在前

      若已知是MOV型:
      RET回代碼段,且[ESP]=1:補碼在后
      否則補碼在前

       

      若補碼在前,則在重定向CALL的地址 -1 處開始修改,若補碼在后,則直接從重定向CALL的地址開始修改

       

      運行自動化判斷腳本

      在這個CALL右鍵點擊此處為新EIP,然后運行我寫的判斷類型腳本。就可以知道他的原型和RET出來之后的地址了。

       

      //第一部分:初始化和變量設置
      var text                 //聲明變量 text,用于存放代碼段的起始地址
      var next                     //聲明變量 next,用于記錄當前分析到的指令地址 (EIP)  next 變量是腳本的核心,它像一個游標,指向當前正要分析的指令。
      var iat                 //聲明變量 iat,用于記錄當前IAT表填充到了哪個位置
      var iatbf                  //聲明變量 iatbf,用于存放我們重建的IAT表的起始位置
      var iatep                 //聲明變量 iatep,iat填充進度的備份
      var api                     //聲明變量 api,用于臨時存放找到的API地址
      var oep                 //聲明變量 oep,用于存放程序的原始入口點 (Original Entry Point)
      var vmp0ep                 //聲明變量 vmp0ep,用于存放VMP保護代碼段的入口地址
      var dedao                 //聲明變量 dedao,用作一個標志,判斷當前指令是否是一個API調(diào)用
      
      mov text,401000      //【需要手動填寫】設置代碼段的起始地址為 0x401000
      mov oep,4612d1          //【需要手動填寫】設置OEP為 0x4612D1
      mov vmp0ep,53c000   //【需要手動填寫】設置VMP代碼段的起始地址為 0x53C000
      mov iatbf,481000     //【需要手動填寫】設置新IAT表的起始地址為 0x481000
      
      mov next,text         //讓分析指針 next 從代碼段的頭部開始 
      mov iat,iatbf         //讓IAT填充指針 iat 指向新IAT表的頭部
      mov iatep,iatbf         //備份IAT填充指針
      
      
      //第二部分:主循環(huán)和初步API檢測
      pdlx:                    /// 是主循環(huán)的標簽。
      mov iatep,iatbf      //每次循環(huán)開始時,重置iat進度備份指針
      mov eax,0              //清空通用寄存器,為模擬執(zhí)行做準備
      mov edx,0
      mov ecx,0
      mov ebx,0
      mov esi,0
      mov edi,0
      mov [esp],1            //在棧上設置一些標記值。這些值后面會用來區(qū)分不同的指令類型
      mov [esp+4],2    
      mov [esp+8],3
      STI                      //單步跟蹤指令 (Step Into)
      STI                      //再次單步,可能是為了越過某些VMP的Handler
      TI                     //跟蹤進入 (Trace Into)
      GN eip                 //【關鍵命令】獲取當前EIP指向地址的符號名(通常是已知的Windows API名)
      mov dedao,$RESULT    //將GN命令的結(jié)果($RESULT)存入dedao變量    
      cmp dedao,0             //比較結(jié)果是否為0。如果不為0,說明EIP直接指向一個API    
      je movexx                         ////如果dedao為0 (不是直接的API調(diào)用),則跳轉(zhuǎn)到movexx,檢查是否是mov類型的API調(diào)用  e??型
      jmp ecpd //如果dedao不為0,說明是直接的API調(diào)用,跳轉(zhuǎn)到ecpd進一步判斷是哪種call/jmp
      
      
      //第三部分:mov 類型API調(diào)用檢測   
      movexx:                    //movexx 代碼塊就是用來檢測這種情況的。它挨個檢查每個通用寄存器,看里面存放的是不是API的地址。
      GN eax                 //檢查eax寄存器里的值是不是一個API地址
      cmp $RESULT,0        //如果結(jié)果不為0
      jne eaxiat            //就跳轉(zhuǎn)到eaxiat處理流程
      GN ecx                //檢查ecx...
      cmp $RESULT,0
      jne ecxiat
      GN edx
      cmp $RESULT,0
      jne edxiat
      GN ebx
      cmp $RESULT,0
      jne ebxiat
      GN esi
      cmp $RESULT,0
      jne esiiat
      GN edi
      cmp $RESULT,0
      jne ediiat
      GN ebp
      cmp $RESULT,0
      jne ebpiat
      jmp ecpd             //如果所有寄存器里都不是API地址,說明不是mov型,繼續(xù)跳轉(zhuǎn)到ecpd判斷
      
      //------------------------------------ move??qcf---------------------------------------------
      //第四部分:mov 類型修復和日志記錄
      //-----------------------------------------movxiufu----------------------------------------------
      eaxiat:    
      msg "mov eax,[0x00]"    // //在調(diào)試器日志窗口顯示消息,表明識別到 "mov eax, [api_addr]" 模式
      jmp pdapif                   //跳轉(zhuǎn)到處理流程的末尾,繼續(xù)下一次循環(huán)
      
      
      ecxiat:        //打印補碼在前,mov ecx
      cmp [esp],1   //檢查之前在棧上設置的標記。用來區(qū)分不同的指令編碼或上下文//是1就屬于補碼在后的類型,不是1就是補碼在前的類型。
      je ecxiath
      msg "qian:mov ecx,[0x00]"
      jmp pdapif        
      
      ecxiath:    //打印補碼在后,mov ecx
      msg "hou:mov ecx,[0x00]"        
      jmp pdapif
      
      edxiat:
      cmp [esp],1  //是1就屬于補碼在后的類型,不是1就是補碼在前的類型。
      je edxiath
      msg "qian:mov edx,[0x00]"
      jmp pdapif
      
      edxiath:
      msg "hou:mov edx,[0x00]"
      jmp pdapif
      
      ebxiat:
      cmp [esp],1  //是1就屬于補碼在后的類型,不是1就是補碼在前的類型。
      je ebxiath
      msg "qian:mov ebx,[0x00]"
      jmp pdapif
      
      ebxiath:
      msg "hou:mov ebx,[0x00]"
      jmp pdapif
      
      esiiat:
      cmp [esp],1  //是1就屬于補碼在后的類型,不是1就是補碼在前的類型。
      je esiiath
      msg "qian:mov esi,[0x00]"
      jmp pdapif
      
      esiiath:
      msg "hou:mov esi,[0x00]"
      jmp pdapif
      
      ediiat:
      cmp [esp],1  //是1就屬于補碼在后的類型,不是1就是補碼在前的類型。
      je ediiath
      msg "qian:mov edi,[0x00]"
      jmp pdapif
      
      ediiath:
      msg "hou:mov edi,[0x00]"
      jmp pdapif
      
      ebpiat:
      cmp [esp],1  //是1就屬于補碼在后的類型,不是1就是補碼在前的類型。
      je ebpiath
      msg "qian:mov ebp,[0x00]"
      jmp pdapif
      
      ebpiath:
      msg "hou:mov ebp,[0x00]"
      jmp pdapif
      
      //--------------------------------------------------------------------------------------
      //第五部分:JMP/CALL 類型API調(diào)用判斷 (FF15/FF25)
      ecpd:
      cmp [esp],1
      je ff25h
      cmp [esp+4],2
      je ff15q
      cmp [esp+4],1
      je ff15h
      cmp [esp+4],3
      je ff25q
      
      //------------------------------------ ff 15 ---------------------------------------------
      
      ff15q:
      msg "qian: ff15"
      jmp pdapif
      
      ff15h:
      msg "hou: ff15"
      jmp pdapif
      
      //------------------------------------ ff 25 ---------------------------------------------
      
      ff25q:
      msg "qian: ff25"
      jmp pdapif
      
      ff25h:
      msg "hou: ff25"
      jmp pdapif
      
      //-------------------------判斷填充到哪,下一個有沒有重定向------------------------------------
      // 是一個公共的跳出點,表示當前指令分析成功。
      pdapif:
      ret            //子程序返回,但在此腳本上下文中,可能意味著成功處理一條指令,準備回到主循環(huán)繼續(xù)
      
      //-----------------------------錯誤--------------------------------------------------------
      //cw1, cw2, cw3 是錯誤處理模塊。當腳本遇到無法識別的指令模式時,它會調(diào)用 wrta 命令將當前指令的地址寫入到不同的文本文件中,方便后續(xù)手動分析這些“硬骨頭”。
      cw1:
      wrta "C:\bscdx.txt",next //輸出未修復的
      jmp pdlx
      
      cw2:
      wrta "C:\yichang.txt",next //輸出未修復的
      jmp pdlx
      
      cw3:
      wrta "C:\bushimov.txt",next //輸出未修復的
      jmp pdlx
      
      jieshu:
      msg "ok"
      ret
      
      
      
      
      //總結(jié)
      //這個腳本是一個高度定制化的IAT自動分析和重建工具。它的工作流程如下:
      //配置: 用戶手動填入目標程序的關鍵地址。
      //循環(huán): 從代碼段開始,逐條指令執(zhí)行和分析。
      //識別: 使用 GN 命令和模式匹配,判斷當前指令是否是一個API調(diào)用(無論是直接CALL、JMP,還是間接的MOV+CALL reg)。
      //記錄: 使用 msg 命令在調(diào)試器中打印日志,記錄識別到的API調(diào)用模式。
      //處理失敗: 如果遇到無法識別的指令,將其地址記錄到文本文件中。
      //重建IAT(隱藏邏輯): 雖然腳本中沒有明確的寫入IAT的代碼(例如 mov [iat], api),但可以推斷,這個腳本的主要目的是識別和記錄。完整的工具鏈可能還包含另一部分腳本,該腳本會根據(jù)這個分析腳本的日志或中間結(jié)果,來實際地將解析出的API地址填充到 iatbf 指定的內(nèi)存區(qū)域中,從而完成IAT的重建。

       

       

       

       

       

      第三階段:修復腳本的邏輯

      核心邏輯

      腳本的執(zhí)行流程是一個循環(huán):

      1. 搜索:根據(jù)用戶提供的“特征碼”(機器碼模式),在代碼段中尋找一個加密的CALL指令。

      2. 分析:使用前文提到的“堆棧指紋”方法,精確判斷出這個CALL的原始類型 (CALL/JMP/MOV) 和補碼位置。

      3. 修復將原始的API調(diào)用指令(如 CALL [IAT地址])寫回代碼段。

      4. 重復:繼續(xù)搜索下一個符合條件的CALL,直到找不到為止。對于無法自動修復的調(diào)用,腳本會將其地址記錄在一個C盤文本文件中,供用戶后續(xù)手動處理。

       

      用戶須知:關鍵的手動步驟

      腳本無法直接運行,用戶必須手動完成以下關鍵配置:

      1. 計算“特征碼” (Feature Code)

        • 目的:為了讓腳本能準確地只搜索那些跳轉(zhuǎn)到VMP代碼段的CALL指令。

        • 方法:通過計算程序代碼段的開頭/結(jié)尾到VMP代碼段的結(jié)尾/開頭的CALL指令的相對偏移量,得出一個偏移范圍。這個范圍就是用于搜索的“特征碼”(如 E8????1?00)。

      2. 分批次、多次運行腳本

        • 由于特征碼通常不是一個,而是一組(如 E8????1?00E8????2?00...),用戶必須手動修改腳本中的特征碼,并多次運行腳本

        • 每次運行前,都需要更新腳本里新IAT的起始地址,確保API地址能被依次、正確地填入。

      總而言之,這個腳本將復雜的“堆棧指紋”分析過程自動化了,但仍需要用戶手動計算并提供搜索目標(特征碼),并通過多次運行來完成整個程序的修復工作。

       

      根據(jù)您提供的特征碼生成方法,我來總結(jié)這個VMP特征碼生成和使用的完整流程:

      特征碼生成原理

      1. 確定VMP0區(qū)段范圍

      • VMP0區(qū)段: 53C000 ~ 615000

      • 計算調(diào)用偏移量范圍

      2. 計算極限偏移值

      調(diào)用VMP0段尾(615000):

      text
      地址: 00401000
      指令: E8 FB3F2100
      計算: 00615000 - 00401000 - 5 = 0x213FFB
      小端序: FB 3F 21 00

      調(diào)用VMP0段首(53C000):

      text
      地址: 004801E3  
      指令: E8 18BE0B00
      計算: 0053C000 - 004801E3 - 5 = 0x0BBE18
      小端序: 18 BE 0B 00

      3. 確定偏移量范圍

      • 最小偏移: 0x0BBE18 → 18 BE 0B 00

      • 最大偏移: 0x213FFB → FB 3F 21 00

      關鍵發(fā)現(xiàn): 所有調(diào)用VMP0的CALL指令,其E8后面的4字節(jié)值在 0x0BBE18 到 0x213FFB 之間

      特征碼分類

      按第三字節(jié)分組:

      text
      E8????0B00  // 第三字節(jié) = 0B
      E8????0C00  // 第三字節(jié) = 0C  
      E8????0D00  // 第三字節(jié) = 0D
      E8????0E00  // 第三字節(jié) = 0E
      E8????0F00  // 第三字節(jié) = 0F
      E8????1?00  // 第三字節(jié) = 10-1F
      E8????2?00  // 第三字節(jié) = 20-2F

      為什么不合并?

      • E8????0?00 會匹配到太多非VMP調(diào)用

      • 主要匹配TEXT段內(nèi)的正常調(diào)用,干擾嚴重

      • 分開搜索提高效率和準確性

      腳本執(zhí)行流程

      1. 初始設置

      asm
      mov iat, 481000          // IAT起始地址
      mov 特征碼, "E8????0B00"  // 第一個特征碼

      2. 循環(huán)執(zhí)行過程

      第一次運行:

      • 特征碼: E8????0B00

      • 搜索范圍: 整個代碼段

      • 修復結(jié)果: 修復匹配的VMP調(diào)用

      • IAT更新: 自動推進到下一個空閑位置

      第二次運行:

      asm
      mov iat, [新地址]        // 更新IAT起始
      mov 特征碼, "E8????0C00" // 更換特征碼

      后續(xù)運行:

      重復上述過程,依次使用所有特征碼

      3. 特征碼執(zhí)行順序

      text
      1. E8????0B00
      2. E8????0C00  
      3. E8????0D00
      4. E8????0E00
      5. E8????0F00
      6. E8????1000  // 注意:實際要展開1?00
      7. E8????1100
      ...
      N. E8????2F00  // 最后使用2?00系列

      實際操作步驟

      腳本要依賴 OD 的跟蹤步入,記得設置好條件

      第一步:準備腳本變量

      asm
      var iat_start = 481000    // IAT起始地址
      var current_iat = iat_start
      var patterns = ["E8????0B00", "E8????0C00", ...] // 所有特征碼

      第二步:循環(huán)執(zhí)行

      對于每個特征碼:

      1. 設置當前特征碼

      2. 設置當前IAT位置

      3. 運行搜索修復腳本

      4. 記錄修復結(jié)果

      第三步:處理特殊情況

      OD插件BUG處理:

      • 某些調(diào)用可能第一次搜索不到

      • 可以重復運行同一特征碼

      • 或手動分析遺漏的調(diào)用

      特征碼展開:

      實際上 E8????1?00 和 E8????2?00 需要展開為:

      text
      E8????1000, E8????1100, ..., E8????1F00
      E8????2000, E8????2100, ..., E8????2F00

      技術要點總結(jié)

      1. 理論基礎

      • 利用VMP調(diào)用偏移量的確定范圍

      • 通過小端序分析字節(jié)特征

      • 基于統(tǒng)計學的方法分類特征碼

      2. 實踐優(yōu)勢

      • 精準匹配: 避免大量誤報

      • 漸進修復: 逐步修復所有調(diào)用

      • 容錯處理: 處理OD插件的不穩(wěn)定性

      3. 效率考慮

      • 分批次處理: 避免一次性處理過多特征

      • 內(nèi)存管理: 有序的IAT空間分配

      • 重復利用: 避免重復修復同一API

      4. 注意事項

      • 地址更新: 每次運行前更新IAT指針

      • 特征碼順序: 按字節(jié)值從小到大執(zhí)行

      • 錯誤處理: 記錄無法修復的地址供手動處理

      這個方法通過系統(tǒng)化的特征碼分類和漸進式修復策略,有效解決了VMP IAT修復的復雜性問題,雖然過程較為繁瑣,但是修復效果相對可靠。

       
       
       
       

       

       

      核心思想

      腳本通過搜索CALL指令的特定機器碼模式(特征碼)都落在一個特定范圍內(nèi),因此可以通過這個范圍來生成精確的搜索特征碼,避免全盤掃描,提高效率。

      用戶操作步驟

      這個腳本并非一鍵完成,而是一個需要用戶介入的半自動化、分批次的修復流程:

      1. 第一步:計算特征碼范圍

        • 找到VMProtect代碼段(VMP0)的起始和結(jié)束地址。

        • 通過計算從程序代碼段的頭/尾分別CALL到VMP0段的尾/頭的兩條指令,得到一個相對地址偏移量的最大值和最小值

        • 將這個數(shù)值范圍轉(zhuǎn)換成一組機器碼搜索模式(如 E8????1?00E8????0F00 等),這就是需要用到的特征碼列表。作者特意避開了過于寬泛的模式(如E8????0?00)以防搜索到太多無關指令導致腳本變慢。

      2. 第二步:迭代運行腳本

        • 運行第1次:將第一個特征碼新IAT表的起始地址填入腳本并運行。腳本會修復一批API調(diào)用。

        • 運行第2次:修改腳本,換上第二個特征碼,并且更新IAT地址,使其指向第一個批次修復完后下一個可用的空位。再次運行。

        • 重復此過程:不斷地用列表里新的特征碼替換腳本中的舊特征碼,并同步更新IAT地址,直到所有特征碼都使用過一遍。

      總而言之,用戶需要先親手計算出一組合適的“搜索密碼”(特征碼),然后像“換彈夾”一樣,手動地、分次地把這些密碼喂給腳本,并告知其新的數(shù)據(jù)該存放在哪里,才能最終完成全部修復工作。

       

      我用白話文說明腳本執(zhí)行的示例

      用硬件訪問斷點找到OEP的位置停下,取消所有設置過的斷點,并設置跟蹤步入,修改腳本的默認參數(shù)為你的程序的參數(shù),其中重點介紹的的是計算多個要修改call的hex特征碼,先填入第一個特征碼,右鍵加載od腳本,等待執(zhí)行完成,完成后修改你你現(xiàn)在的IAT地址在腳本中在執(zhí)行一遍直到?jīng)]有可以修復的iat,再次修改特征碼和下一個iat地址搜索修復下一個特征。

      打開c盤查看修復錯誤文件,手動修復。比如476FB8地址就是一個錯誤。打開類型判斷腳本,我們知道了他是ff15,前補碼。RET出來后停在77FE0000。我們復制jmp前的三條指令,到jmp后地址的前面粘貼。我們直接手動在 476FB8-1 這個地址修改就行了。記得將API記錄下來,手動填到IAT中。

       

       

      第四階段:手動修復

      打開C盤找到修復失敗的api文件,手動修復。

      1. 定位疑難API:通過調(diào)試和觀察,找到那些被加密得最深的、或者有反調(diào)試機制的API調(diào)用。比如476FB8位置有一個被加密函數(shù)的api,

      2. 手動修改

        • 上面提供的判斷類型的腳本。可以先知道它的類型。比如,當腳本執(zhí)行完成后發(fā)現(xiàn)是FF15型,補碼在前,RET出來后停在77FE0000。

        • 通過單步步入(F7)和跟蹤步入 進入函數(shù)內(nèi)部,找到真正的調(diào)用函數(shù)地址。比如,就是一個被偷掉開頭的函數(shù),從77FE0000,到77FE0003,就是VMP偷走的函數(shù)頭,下一個JMP就是跳回那個函數(shù)的對應行。我們將這個頭以二進制形式復制下來,然后跟入下面那個CALL,將頭補回去,你就可以知道這個函數(shù)是什么了。就是替換user32.77D2C90D前三個指令為調(diào)用者的前三個指令,并修改eip為 77D2C908

        • 然后手動修改代碼,將原始的混淆指令替換為call user32.某個函數(shù)api。比如我們直接手動在 476FB8-1 這個地址修改就行了。記得將API記錄下來,手動填到IAT中。

      3. Dump內(nèi)存和重建IAT

        • Dump進程:在所有API調(diào)用都修復完成后,使用LordPE等工具完整地Dump出進程內(nèi)存,這是可以運行的但是跨平臺不能運行。

        • :使用ImportREC(導入表重建工具),也修復不了,因為我們修復出來的IAT是亂序的,并不是以一個一個DLL的順序排列好。用ODdump出來的那一份程序進行修改拖進 StudyPE+ x86 ,給它加一個區(qū)段,用于存放我們UIF修復的API。(在原有的IAT進行修復可能會出錯)

        • 修復二次重定位的IAT:
        • 再將添加了區(qū)段的脫殼版 拖進OD,在我們修復的IAT中找到二次重定位的API,將它更改,直接填入真實的API。(因為UIF識別不了重定向的api,會修復錯誤。) 很好找的, 看看數(shù)據(jù)和其他對比一下大小就知道了。(一般有兩個二次重定向)

          image

           

          正常的、已修復的條目:
            • 00481394 77D3C702 user32.DrawTextA

            • 00481398 77D55B05 user32.GrayStringA

            • 0048139C 77F06F5A gdi32.Escape

            請注意它們的第二個數(shù)據(jù)(地址):77D3C70277D55B0577F06F5A。這些都是高地址(以77...開頭),它們就是系統(tǒng)“圖書館”里的**“真實頁碼”**(真實的API地址)。這些都是正確的。

          1. 需要你手動修復的“二次重定位”條目:

            • 004813A4 0041B71D <jmp.&KERNEL32.GetVersion>

            再看這一行,它的第二個數(shù)據(jù)(地址)是 0041B71D

            • “對比大小”: 0041B71D 是一個低地址(以004...開頭),它和其他的 77... 地址一比,數(shù)值差別巨大。這就是作者說的“很好找”的原因。

            • “二次重定位”的含義: 這個 0041B71D 地址不是 GetVersion 函數(shù)的“真實頁碼”。它指向的是程序自己內(nèi)部的某個地方(“書的第5頁”)。這個地方存放了一個“跳轉(zhuǎn)指令”(JMP),它才會第二次跳轉(zhuǎn)到“真實頁碼”。

            • “修復錯誤”的原因: 下一個工具(UIF)看到 0041B71D 就會“懵掉”,它會以為 0041B71D 就是 GetVersion 的真實地址,從而導致排序和修復徹底失敗。

          所以,這個步驟要求你:

          在運行UIF工具之前,你必須手動去 0041B71D 這個地址看一眼,找到它最終跳轉(zhuǎn)到的那個“真實頁碼”(比如是 77E50000),然后回到這里,把 0041B71D 這個值手動改成 77E50000

          這樣,這個“新目錄”里的所有條目就都是“真實頁碼”了,UIF 才能正確地工作。

        • 修復IAT 打開UIF,填入PID,代碼段的頭,代碼段的尾,和我們添加的區(qū)段的頭部地址。勾選修復輸入表。然后點擊修復。修復后,排好了順序

        • image

           

        • 用UIF修復完后,我們就可以直接用REC進行跨平臺修復了。選擇我們加了區(qū)段的脫殼版,填好OEP偏移,和UIF修復后的地址偏移(也就是我們新加的區(qū)段頭地址減去400000)。點獲取。然后修復轉(zhuǎn)存到 你加了區(qū)段的脫殼版 上就可以完美修復了。XP系統(tǒng)下脫殼修復,WIN10上運行:
        • image

           

      總結(jié)

      • 動靜結(jié)合:既有靜態(tài)分析(觀察代碼結(jié)構(gòu)),也有動態(tài)調(diào)試(設置斷點、跟蹤執(zhí)行)。

      • 先自動后手動:首先嘗試用腳本批量解決大部分問題,再對少數(shù)疑難點進行精確的手動修復。

      • 邏輯清晰:從尋找入口點,到分析API,再到編寫腳本和手動修復,最后到Dump和重建,整個流程一氣呵成,邏輯非常清晰。

       

       

       

       

       

       

       

       

       

       

      淺談VMProtect 2.13.8 IAT修復 - 吾愛破解 - 52pojie.cn

      posted on 2025-10-31 07:57  GKLBB  閱讀(8)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 无码国内精品久久人妻蜜桃| 熟女系列丰满熟妇AV| 国产在线无码不卡播放| 久久亚洲av成人一二三区| 亚洲欧美中文字幕日韩一区二区| 国产综合色在线精品| 亚洲欧美日韩综合久久久| 国产360激情盗摄全集| 中文字幕在线不卡一区二区| 国产偷国产偷亚洲高清人| 国产精品久久久久鬼色| 国产成人片无码视频| 新田县| 日本视频一区二区三区1| 国产亚洲精品VA片在线播放| 久久99精品久久久久久齐齐| 亚洲国产一区二区精品专| 樱桃视频影院在线播放| 中文字幕va一区二区三区| 东兴市| 深夜精品免费在线观看| av深夜免费在线观看| 欧美亚洲一区二区三区在线| 女女互揉吃奶揉到高潮视频| 国产精品午夜福利在线观看 | 亚洲国产精品久久久天堂麻豆宅男| 中文字幕av无码一区二区蜜芽三区| 国产AV老师黑色丝袜美腿| 日本亚洲一区二区精品| 久久国产精品二国产人妻| 国产情侣激情在线对白| 天干天干夜啦天干天干国产| 日韩高清视频 一区二区| 久久发布国产伦子伦精品| 国产亚洲一区二区三区四区 | 亚洲男人在线天堂| 亚洲αⅴ无码乱码在线观看性色| 亚洲国产精品一二三四五| 久久99九九精品久久久久蜜桃| 日韩美女亚洲性一区二区| 欧美不卡无线在线一二三区观|