逆向實用干貨分享,Hook技術第一講,之Hook Windows API
作者:IBinary
出處:http://www.cnblogs.com/iBinary/
版權所有,歡迎保留原文鏈接進行轉載:)
一丶什么是Hook,以及Hook能干啥
首先這一個小標題主要介紹神馬是Hook,如果知道的,則不用看了.
這里我偷襲啊懶,貼出Hook的意思 https://baike.baidu.com/item/%E9%92%A9%E5%AD%90%E7%A8%8B%E5%BA%8F
Hook,英文單詞中成為鈎子,鐵鈎的意思,在我們編程中就是掛鈎的意思
我們要HookApi,則是要把這個API進行掛鈎,讓其執行我們的代碼,然后執行完我們的代碼之后,在執行API的代碼,當然執行不執行使我們說了算.
二丶Hook API的原理,以及思路
現在我們要知道我們要怎么Hook API
假設我們程序現在要調用一個MessageBox函數,那么我們把這個API Hook了,變為我們的API去執行,執行完我們的代碼之后再去執行它的的函數.
具體看下我們的草圖:
其實相當於就是我們在這個API之前,跳轉到我們的函數執行了,然后跳轉之后,我們執行完畢之后,可以選擇是否在跳轉回去,但是這里注意,跳轉回去則跳轉到msg的return處位置即可.
eax可以給一個值,讓它返回.
利用這個技術,我們可以監控API,比如應用程序會調用loadLibrary,那我們把它Hook了,把Dll路徑改成我們的,那加載的就是我們的dll了,當然 Hook的API很多,因為只要是Windows的API都能HOOK
因為JMP的時候占五個字節,而WindowsAPI也是頭部弄了五個字節,猜想可能是Windows自己留作Hook的.
三丶Hook的步驟(Hook自己)
首先說下步驟
/* 思路: 我們要獲取MessageBoxA的函數地址,在獲取之前我們要進行下面幾個步驟 1.調用GetModuleHandlle,獲取Dll模塊(user32.dll的)的基地址 2.通過基地址,調用GetProcAddress獲得Msg的函數地址 3.修改Msg函數地址的保護屬性,調用virtualProtect 4.重定位跳轉地址 Dest - MsgCode = offset -5 jmp 跳轉到這個偏移即可 5.跳轉回來的時候則是 dest + offset + 5 = Msgcode +5的位置 */
看上面,很暈,一步一步代碼實現.
注意: 這里只是簡單實現,並且說下思路,代碼復制過去你不能運行,因為比如下方,我寫 offset g_szUser32...等等的,
其實都是在.const中定義的,最下面會貼出完整代碼,那么是可以運行的.
第一步,獲得Msg的地址,首先調用GetModuleHandle
;1.獲得Msg的地址,先調用GetmoudulHandle invoke GetModuleHandle,offset g_szUser32 ;獲得模塊地址
mov @hUserHand,eax ;返回值給局部變量保存
;其中g_szUser32在常量區是 user32.dll的字符串
第二步:通過模塊地址,獲得Msg函數的地址
invoke GetProcAddress,@hUserHand,offset g_szMsgName mov @MsgProcAddrs,eax
;代碼同上
第三步:修改Msg函數地址的內存保護屬性,方便一會我們把JMP的二進制寫進去好修改
invoke VirtualProtect,@MsgProcAddrs,1000h,PAGE_EXECUTE_READWRITE,addr @hOldProtect
修改大小是1000(4096)個字節
權限是 可讀可寫可執行
是否保存舊的權限屬性: 是 ,這里必須保存,雖然你不用,否則API會失敗
還有就是,因為要保存以前的,所以我們必須把地址給他,要加上Addr才可以
第四步: OD查看Msg位置,尋找5個字節位置
這個時候我們可以在我們的代碼中寫個int 3,打開的時候OD會斷下,我們在GetprocAddress的位置下斷點,
看下獲取到的Msg的地址是多少
我們在反匯編窗口中跟隨到Msg的位置.
可以看到上圖的位置,剛好五個字節, mov edi,edi是沒用的指令,但是windows還是保留了
也就是說可能就是以為了自己去監控API留下的.那么這個時候我們可以在這個位置,寫入
JMP的指令 JMP 我們的API位置
我們如果跳轉到我們API的位置后,執行的代碼前邊這三條還是這個,因為一會我們還要在跳轉到當前的MSG + 5
的位置處繼續執行,(當然,隨你便,你也可以跳轉到Msg的Return位置)
第五步: 寫入Jmp,JMP到我們的函數的位置
首先我們知道 JMP的二進制是 E9
所以我們要 E9 xxxxxx xxx使我們函數的地址
但是JMP 的時候,這個地方是個偏移
那么我們要JMP到我們函數的偏移位置,就要進行地址重定位了.
怎么重定位,很簡單,小學數學
計算Msg的下一條執行的位置
code + offset = dest 當前的Msg的下條位置計算 帶入則是 7595FDAE + 5 = 7595FDB3 也正好是我們跳轉回來的位置
計算跳轉到我們函數地址
dest - code = offset 目標地址我們知道,就是我們的函數地址,開始跳轉的地址也知道了,所以帶入帶
我們的函數地址 - Code(當前的Msg地址) = offset 偏移,那么 JMP 這個偏移即可.
定義我們的函數
函數寫成下面的那樣
最下面的label中的內容則是 JMP 00000000 其中這個地址是我們要重定位寫進去的
第六步:實現代碼,寫入JMP
從這里開始我直接寫實現代碼了
mov eax,@MsgProcAddrs ;code mov ebx,NewMsgBox ;dest sub ebx,eax ;dest - code = offset sub ebx,5 ;得出的偏移需要-5,別忘了jmp占五個字節,這樣才可以跳轉到你的地址執行 mov [eax],byte ptr 0e9h ;寫入Jmp mov [eax +1],ebx ;寫入跳轉的地址
首先獲得msg的位置,也就是Code
然后獲得 自己函數的位置,也就是Dest
現在我們要求出中間的偏移是多少 dest - code = offset
然后因為JMP跳轉要占五個字節,所以接着-5個字節大小
現在我們要把Msg函數的位置,改為JMP,我們要JMP我們的地址,我們看下OD分析
1.首先找到Msg函數位置,看下數據窗口中跟隨
2.單步走,然后執行到第一個把二進制改為E9H的地址
現在我們接着反匯編窗口中去看看Msg的地址,看下是否改為了JMP了
現在是改為了JMP,但是偏移是不對了,不過我們的偏移已經計算出了了,所以寫到E9后面即可
3.修改偏移OD查看.
,反匯編窗口中看下Msg
,現在顯示不知是否正確,那么我們現在去反匯編窗口中看下00401000是不是我們的NewMsg位置
可以看出,代碼正是我們寫的.
也正好是JMP 000000000的位置,那么我們就可以在我們的代碼中寫了,劫持真正的MsgBox函數的執行
我們知道, 因為是jmp過來的,所以ebp - c 還是Msg的第二個參數,我們把里面的內容改了
注意,這個在劫持代碼里面寫.
四丶我們還有修改跳轉回來的位置,這個是同理了
看下代碼:
invoke VirtualProtect,label1,1000h,PAGE_EXECUTE_READWRITE,addr @hOldProtect mov eax,offset label1 ;code 我們要修改的地址是標號的地址,所以他是code mov ebx,@MsgProcAddrs ;dest 我們要跳轉到Msg的地址,所以他是Dest sub ebx,eax ;dest - code = offset 帶入公式咋得到ebx是偏移 mov [eax +1],ebx ;eax標號的位置+1后面,也就是JMP 00 00 00 00 把00 00 00 00 寫成偏移,咋跳轉回來Msg的位置繼續執行 invoke MessageBoxA,NULL,offset g_szMsgTitle,NULL,MB_OK
第一,我們要修改的跳轉位置是標號1的位置,所以他是code
第二,我們要跳轉到哪里,所以他是dest
第三,根據公式, dest - code = offset 求得了偏移
第四,我們把dset +1的位置,也就是JMP 00 00 00 00 修改位了偏移,咋又跳轉回來了.
看下OD分析
看下OD,我們也可以看出,我們單步走,單步走到 mov dword ptr[eax +0x1]的位置,看下是否把標號1的偏移修改了
在內存中我們已經看到了,我們的偏移修改了.
那么我們反匯編窗口看下,當前我們的API ,也就是JMP 00 00 00 00 的位置是否修改了
可以看出,確實修改了,那么我們看下JMP 后面的地址是哪里把
正好使我們調用MsgBox的位置 +5的下面,也就是說,上面JMP到我們的API執行了,下面咋通過JMP有跳轉回來了,此時因為我們已經保存了 棧底環境,所以運行是沒有出錯的
看下不調試,正常運行
通過HOOK技術,我們把本來應該輸出 Hello 看雪,變成了我們自己想要的字符串.
四丶總結
總結來說. HOOK 需要記住一個公式以及硬編碼即可. 公式 目的地址 - 源地址 -指令長度(如果是JMP則是5)
JMP 硬編碼是E9 E9 00000000 后邊四個0我們定位到我們要執行代碼的位置. 用公式計算機課. 目的 - 源 - JMP(5) == 偏移. 偏移寫入這里即可.
HOOK 別人程序也是這樣去做.
因為代碼是RadAsm工程的,所以這里打包發到百度雲盤
鏈接:http://pan.baidu.com/s/1kVBWalp 密碼:luz8
作者:IBinary
出處:http://www.cnblogs.com/iBinary/
版權所有,歡迎保留原文鏈接進行轉載:)
如果覺着好,請推薦,加關注,如果覺着哪里寫的不好,請批評改正.謝謝大家.如果看不懂,請評論一下給點動力,其實寫博客最主要的還是自己整理,每天都堅持.把最好的獻給大家.