下载本节例子程序和源代码 (5.21 KB) |
;********************************************************* ;程序名称:用 SEH 技术实现 API Hook ;适用系统:Win NT/2000/XP ;作者:罗聪 ;日期:2002-11-22 ;出处:http://www.LuoCong.com(老罗的缤纷天地) ;注意事项:如欲转载,请保持本程序的完整,并注明: ;转载自“老罗的缤纷天地”(http://www.LuoCong.com) ;********************************************************* .386 .model flat, stdcall option casemap:none include /masm32/include/windows.inc include /masm32/include/kernel32.inc include /masm32/include/user32.inc includelib /masm32/lib/kernel32.lib includelib /masm32/lib/user32.lib WndProc proto :DWORD, :DWORD, :DWORD, :DWORD Error_Handler proto :DWORD, :DWORD, :DWORD, :DWORD SetHook proto .const IDI_LC equ 1 IDC_CHECKBUTTON_HOOK equ 3000 IDC_BUTTON_ABOUT equ 3001 IDC_BUTTON_EXIT equ 3002 .data szDlgName db "lc_dialog", 0 szMsgAbout db "-= SEH for API Hook =-", 13, 10, 13, 10,/ "作者:罗聪([email protected])", 13, 10, 13, 10,/ "老罗的缤纷天地", 13, 10,/ "http://www.LuoCong.com", 13, 10, 0 szMyText db 13, 10, 13, 10, "(哈哈,看到有什么不同了吗?)", 0 szMsgHooked db "MessageBoxIndirectA() has been hooked!",/ 13, 10, 13, 10,/ "即将改变原来的 MessageBoxIndirectA() 的参数,", 13, 10,/ "请注意后面的对话框跟没有 Hook 之前有什么不同……", 0 szCaption db "SEH for API Hook by LC", 0 szLibUser db "user32", 0 szProcMsgBoxInd db "MessageBoxIndirectA", 0 dwAddress dd 0 dwOldProtect dd 0 bOldByte db 0 dwRetAddr dd 0 .data? hInstance HINSTANCE ? mbp MSGBOXPARAMS <> szText db 1024 dup(?) .code main: ; 设置 SEH 链: assume fs:nothing push offset Error_Handler push fs:[0] mov fs:[0], esp invoke GetModuleHandle, NULL mov hInstance, eax invoke DialogBoxParam, hInstance, offset szDlgName, 0, WndProc, 0 ; 恢复原来的 SEH 链: pop fs:[0] pop eax invoke ExitProcess, 0 WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .if uMsg == WM_CLOSE invoke EndDialog, hWnd, 0 .elseif uMsg == WM_INITDIALOG mov eax, hWnd mov [mbp.hwndOwner], eax invoke LoadIcon, hInstance, IDI_LC invoke SendMessage, hWnd, WM_SETICON, ICON_SMALL, eax ; 储存 API 的原入口地址: invoke GetModuleHandle, addr szLibUser invoke GetProcAddress, eax, addr szProcMsgBoxInd mov [dwAddress], eax ; 保存原对话框的输出文字: invoke lstrcpy, addr szText, addr szMsgAbout .elseif uMsg == WM_COMMAND mov eax, wParam mov edx, eax shr edx, 16 movzx eax, ax .if edx == BN_CLICKED .if eax == IDC_BUTTON_EXIT || eax == IDCANCEL invoke EndDialog, hWnd, NULL .elseif eax == IDC_BUTTON_ABOUT || eax == IDOK mov [mbp.cbSize], sizeof mbp mov eax, hInstance mov [mbp.hInstance], eax mov [mbp.lpszText], offset szMsgAbout mov [mbp.lpszCaption], offset szCaption mov [mbp.dwStyle], MB_OK or MB_APPLMODAL or MB_USERICON mov [mbp.lpszIcon], IDI_LC invoke MessageBoxIndirect, addr mbp .elseif eax == IDC_CHECKBUTTON_HOOK ; 把内存保护设置成 可读/可写/可执行: invoke VirtualProtect, [dwAddress], 1, PAGE_EXECUTE_READWRITE, addr dwOldProtect invoke IsDlgButtonChecked, hWnd, IDC_CHECKBUTTON_HOOK mov edx, [dwAddress] test eax, eax .if zero? ; uninstall hook mov cl, [bOldByte] ; bOldByte = API 原入口地址 mov byte ptr [edx], cl ; 恢复 API 的原入口地址 invoke lstrcpy, addr szMsgAbout, addr szText ; 恢复原对话框的输出文字: .else ; re-install hook mov cl, byte ptr [edx] ; byte ptr [edx] = API 原入口地址 mov byte ptr [edx], 0CCh ; 断点异常(INT 3 指令) mov [bOldByte], cl ; 储存 API 的原入口地址 invoke lstrcat, addr szMsgAbout, addr szMyText ; 改变原对话框的输出文字: .endif .endif .endif .else mov eax, FALSE ret .endif mov eax, TRUE ret WndProc endp ;**************************************** ; 函数功能:处理异常错误 ;**************************************** Error_Handler proc uses ecx lpExceptRecord:DWORD, lpFrame:DWORD, lpContext:DWORD, lpDispatch:DWORD ; 输出 "API hooked": invoke MessageBox, [mbp.hwndOwner], addr szMsgHooked, addr szCaption,/ MB_OK or MB_ICONINFORMATION ; 储存并改变 SetHook 函数的返回值:(经过修正) ; (想不明白?呵呵,用调试器跟踪一下吧,我也说不清楚,只能意会不能言传……) mov eax, [lpContext] mov eax, [eax][CONTEXT.regEsp] mov ecx, [eax] mov [eax], offset SetHook mov [dwRetAddr], ecx ; 把 API 原入口地址写回去,以便继续运行原 API: ; (跟踪一下吧,我实在是不知道怎么才能说得清楚……) mov eax, [dwAddress] mov cl, [bOldByte] mov byte ptr [eax], cl ; 继续下一个 Execution: mov eax, ExceptionContinueExecution ret Error_Handler endp ;**************************************** ; 函数功能:设置 API Hook ;**************************************** SetHook proc uses ecx mov eax, [dwAddress] mov cl, [eax] mov byte ptr [eax], 0CCh ; 断点异常(INT 3 指令) mov [bOldByte], cl jmp [dwRetAddr] ; 跳回经过 Hook 之后的 API 的返回地址(很重要!) SetHook endp end main ;******************** over ******************** ;by LC |
#include "resource.h" #define IDI_LC 1 #define IDC_CHECKBOX_HOOK 3000 #define IDC_BUTTON_ABOUT 3001 #define IDC_BUTTON_EXIT 3002 #define IDC_STATIC -1 IDI_LC ICON "lc.ico" LC_DIALOG DIALOGEX 10, 10, 200, 50 STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "SEH for API Hook by LC, 2002-11-22" FONT 8, "MS Sans Serif" BEGIN AUTOCHECKBOX "&Hook MessageBoxIndirectA", IDC_CHECKBOX_HOOK, 5, 5, 190, 12 PUSHBUTTON "关于(&A)", IDC_BUTTON_ABOUT, 5, 30, 90, 14, BS_FLAT | BS_CENTER PUSHBUTTON "退出(&X)", IDC_BUTTON_EXIT, 105, 30, 90, 14, BS_FLAT | BS_CENTER END |