這裡嘗試用熟悉的 Helloworld 來解析 UPX 是如何脫殼的。
這一章我一行一行的檢查,然後猜測……由於經驗不足我無法確定我是正確的,所以程式流程的解說不一定是正確的。
https://github.com/Dinlon5566/IT_Reverse_Engineering/tree/main/Dx12

使用 x64dbg 進入 EP,但這裡只是解壓縮器的 EP,而且位置是在 UPX[ 1 ] 區域。但還不是原本程式的 OEP ( Original Entry Point )。
第一行的 pushad 會將 EAX~EDI 暫存器都存進 Stack。
第二行把 第二個 Section (放壓縮檔的區塊) 起始點設到 ESI。
第三行把 EDI 設到第一個區塊的起始位置。
既然把傳輸位置 ( ESI & EDI )的起始點與終點設成這樣,就可以預見資料會從第二區塊解壓縮到第一區塊,而指令碼始終只會在記憶體中。

ctrl + F8 來連續執行程序,在開始後我發現了循環中的 009A7E03 會將 ESI 貼到 EDI,也是 009A1000 ( Base of UPX[0] )
009A7EBA 設停止點讓他脫離循環,可以發現指令和 009A6000 的 INT 被貼上來了,觀察 EDI 發現他複製到 009A65D4 ( 雖然中間一大部分是空的 )

009A7EC2 到 009A7EEE 的循環,可以發現 call 跟 jmp 的目的位置被修復了。
009A7F39 的循環會根據之前第一次循環設好的名稱等把 ITA 設好。
009A7F39 到 009A7F67 會將字串與 Function Name 附到正確的位置上。
009A7F96,popad 與 pushad 對應。把 stack 推回去後就可以由 009A7FA4 跳到 OEP 了
之後就是快快樂樂地原本的 Helloworld,透過這次實驗也了解了經過 UPX 如何破殼而出。
可以發現在 EP 後有一個 pushad,推測他保存的值會留給原本的程式,所以只需要找到 popad 後的 jmp 就可以知道原本的 OEP 在哪裡。 在 x64dbg 中可以到 EP 後使用 alt+F 搜尋 popad 就可以快速搜尋到該指令。