某個軟體因為有殼,在將殼部分模擬完成後,發現還需要對某個地址SMC,故在解壓縮完成後,
將要跳到真正入口處時,先跳到SMC處執行補丁,然後再跳到真正入口處。採用了增加一個節
的方法擴充SMC程式碼(怎樣增加一個節,因為很簡單,不再做說明)
為什麼不直接脫殼呢?因為這是個DLL,脫殼很麻煩的,要處理引入表、衝定位項,乾脆模擬
透過算了,這樣的問題是要修改某個記憶體地址的時候,需要用SMC,不能直接修改了。。
--------------------------------------------------------------------------------
//要修改的地址Address=1067206h-00029302h=103DF04h開始的5位元組
//要修改的地址將以1067206h作為基準,因為這個基準地址我們可以很容易得到且不受任何
//因素影響,上面為什麼使用“-”,因為我將節加到最後,地址肯定大於原程式中的任何地
//址。
--------------------------------------------------------------------------------
//補丁程式
//1.因為原來程式引入表中沒有"VirtualQuery"函式,所以要先取得
//2.以下用到的其它函式,原來程式引入表中都有,所以直接使用
--------------------------------------------------------------------------------
EAX=00000000 EBX=01067012 ECX=00000000 EDX=01030000
ESI=00000004
EDI=FFFFFFFC EBP=01067206
ESP=016FFBC0 EIP=0106720F o d I s z a P c
CS=0167
DS=016F SS=016F ES=016F FS=3C8F GS=0000
--------------------------------------------------------------------------------
016F:01066FE2 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
016F:01066FF2 00 00 00 00 00 00 00 00-00 00 00 00 00 00 E9 FB ................
016F:01067002 01 00 00 56 69 72 74 75-61 6C 51 75 65 72 79 00 ...VirtualQuery.
016F:01067012 4B 65 72 6E 65 6C 33 32-2E 44 4C 4C 00 00 00 00 Kernel32.DLL....
016F:01067022 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
016F:01067032 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
--------------------------------------------------------------------------------
0167:01067200 PUSHAD
0167:01067201 CALL
01067206
0167:01067206 POP EBP
;此時,ebp = 1067206h
0167:01067207 MOV
EBX,EBP
0167:01067209 SUB EBX,000001F4 ;EBX-1F4h
= "Kernel32.DLL"
0167:0106720F PUSH EBX
0167:01067210
CALL [KERNEL32!GetModuleHandleA]
0167:01067216
TEST EAX,EAX
0167:01067218 JZ
010672AC
0167:0106721E MOV EDX,EAX
0167:01067220 MOV EBX,EBP
0167:01067222 SUB
EBX,00000201 ;EBX-201h 指向"VirtualQuery"
0167:01067228
PUSH EBX
0167:01067229 PUSH
EDX
0167:0106722A NOP
0167:0106722B NOP
0167:0106722C
NOP
0167:0106722D NOP
0167:0106722E NOP
0167:0106722F
NOP
//
0167:01067230 CALL [KERNEL32!GetProcAddress]
;取得VirtualQuery函式地址
0167:01067236 TEST EAX,EAX
0167:01067238 JZ 010672AC
0167:0106723A
MOV EBX,EBP
0167:0106723C SUB
EBX,00000106 ;EBX-106h 指向 VirtualQuery函式引數區(引數設定參考SDK)
0167:01067242
PUSH 1C ;VirtualQuery函式引數區長度
0167:01067244 PUSH EBX
;PMEMORY_BASIC_INFORMATION
0167:01067245 MOV
EBX,EBP
0167:01067247 SUB EBX,00029302 ;要修改的地址Address=EBX-00029302h=103DF04h
0167:0106724D PUSH EBX
;address of region
0167:0106724E CALL EAX
;呼叫VirtualQuery取得Address所屬頁的頁基址
//
0167:01067250
MOV EBX,EBP
0167:01067252 SUB
EBX,000001E6 ;EBX-1e6h = VirtualProtect引數,返回的原來的頁屬性
0167:01067258 PUSH
EBX
0167:01067259 PUSH 00000040
;新的頁屬性(PAGE_EXECUTE_READWRITE)
0167:0106725E MOV
EBX,EBP
0167:01067260 SUB EBX,00000106
;EBX-106h = VirtualProtect引數區,資料來自VirtualQuery
0167:01067266 PUSH DWORD PTR [EBX+0C] ;VirtualProtect引數,size
of the region
0167:01067269 PUSH DWORD PTR [EBX]
;VirtualProtect引數,address of region of committed
;pages
0167:0106726B
NOP
0167:0106726C NOP
0167:0106726D NOP
0167:0106726E
CALL [KERNEL32!VirtualProtect] ;呼叫VirtualProtect改變頁屬性
0167:01067274 MOV EBX,EBP
0167:01067276 SUB
EBX,00029302 ;要修改的地址Address=EBX-00029302h=103DF04h
0167:0106727C
MOV DWORD PTR [EBX],b3b2b1b0 ;將原來4位元組改為b3b2b1b0
0167:01067282 MOV BYTE PTR [EBX+04],XX
;將原來1位元組改為XXh
//下面恢復修改的頁屬性
0167:01067286 MOV
EBX,EBP
0167:01067288 SUB EBX,000001E4
;VirtualProtect引數,原來的頁屬性,此時這個引數對
;我們沒用,但必須有
0167:0106728E PUSH EBX
0167:0106728F
MOV EBX,EBP
0167:01067291 SUB
EBX,000001E6 ;儲存的原來的頁屬性
0167:01067297 PUSH
DWORD PTR [EBX]
0167:01067299 MOV EBX,EBP
0167:0106729B SUB EBX,00000106
;EBX-106h = VirtualProtect引數區,資料來自VirtualQuery
0167:010672A1
PUSH DWORD PTR [EBX+0C] ;VirtualProtect引數,size of the region
0167:010672A4 PUSH DWORD PTR [EBX]
;VirtualProtect引數,address of region of committed
;pages
0167:010672A6 CALL
[KERNEL32!VirtualProtect] ;呼叫VirtualProtect恢復頁屬性
0167:010672AC
POPAD
0167:010672AD JMP XXXXXXXX
;跳轉到原來程式處繼續執行
因為涉及某個國產軟體,恕不說明具體程式。。。
Spring.W
2002/10/20