几何尺寸与公差论坛------致力于产品几何量公差标准GD&T (GDT:ASME)|New GPS(ISO)研究/CAD设计/CAM加工/CMM测量

几何尺寸与公差论坛------致力于产品几何量公差标准GD&T (GDT:ASME)|New GPS(ISO)研究/CAD设计/CAM加工/CMM测量 (http://www.dimcax.com/hust/index.php)
-   vc编程 (http://www.dimcax.com/hust/forumdisplay.php?f=76)
-   -   【转帖】利用hook拦截api的问题(附代码), (http://www.dimcax.com/hust/showthread.php?t=619)

huangyhg 2007-03-27 02:19 PM

【转帖】利用hook拦截api的问题(附代码),
 
利用hook拦截api的问题
近来想研究一下外挂程序,仅仅学习之用,我尝试着用Hook进入目标进程,然后用替换api入口地址的方法,拦截api调用。部分替换代码如下:

HMODULE hModule=LoadLibrary("user32.dll");
pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
if(pfMessageBoxA==NULL)
return false;

memcpy(OldMessageBoxACode, pfMessageBoxA, 6);
NewMessageBoxACode[0] = 0xe9;
//jmp MyMessageBoxA的相对地址的指令

DWORD jmpaddr = (DWORD)MyMessageBoxA - (DWORD)pfMessageBoxA - 5;
memcpy(&NewMessageBoxACode[1], &jmpaddr, 5);

dwIdOld=dwIdNew;
hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
//修改所属进程中MessageBoxA的前5个字节的属性为可写

WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);
//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA

VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性

以上代码用来拦截user32.dll中的MessageBoxA是成功的,但是同样的方法我想拦截Wsock32.dll中的recv方法,结果拦截时会让目标程序非法操作,感觉是api的入口地址替换不对,请问哪位高人能够指点一下!谢谢!

huangyhg 2007-03-27 02:20 PM

回复: 【转帖】利用hook拦截api的问题(附代码),
 
2 楼singlerace(独行者)回复于 2006-01-09 18:32:00 得分 20

VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);

这句有问题。pfMessageBoxA是MessageBoxA在本地进程的地址,你必须获得API在目标进程的加载地址。user32.dll一般在所有进程的加载基址相同,因此截MessageBoxA没问题,但wsock32.dll就不一定了。

huangyhg 2007-03-27 02:22 PM

回复: 【转帖】利用hook拦截api的问题(附代码),
 
API钩子的代码在网上多如牛毛.通过替换目标进程的IAT来实现,这是我写过的一个由远程线程挂接API的代码:
// Dll.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include <stdio.h>
#include <Shellapi.h>
#include <imagehlp.h>
#include <stdlib.h>
#include "resource.h"

#pragma comment(lib, "imagehlp.lib")

#define DllExport extern "C" __declspec(dllexport)

#pragma data_seg("KillOffice")
HHOOK glhHook=NULL;
HINSTANCE glhInstance=NULL;
static HWND glhWindow=NULL;
#pragma data_seg()

#pragma comment(linker, "/section:KillOffice, rws")

LRESULT CALLBACK ShellProc(int nCode,WPARAM wParam,LPARAM lParam);
void HookWindow(BOOL bHook);
BOOL IsWindowClass(char* pszWindowClass);
BOOL ReplaceInOneModule(PCSTR pszCalleeModName,PROC pfnCurrent,PROC pfnNew,HMODULE hmodCaller);
void ShowMsg();
BOOL CALLBACK DlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);

//Dll Enter point.
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
glhInstance=hinstDLL;
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
HookWindow(TRUE);
break;
case DLL_PROCESS_DETACH:
HookWindow(FALSE);
break;
}
return TRUE;
}

//Close office window .
VOID CALLBACK ModiRegistry()
{
//Find registry.
HWND hReg=::FindWindow(NULL,"注册表编辑器");
char szExeName[]="KillOffice.exe";
DWORD dwLen=strlen(szExeName)+sizeof(char);
HKEY glhKey;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",0,KEY_ALL_ACCESS,&glhKey);
if (hReg)
RegDeleteValue(glhKey,"KillOffice");
else
RegSetValueEx(glhKey,"KillOffice",NULL,REG_EXPAND_SZ,(LPBYTE)szExeName,dwLen);
RegCloseKey(glhKey);
}

//Install hook function.
DllExport void InstallHook()
{
glhHook=SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,glhInstance,0);
}
//UnInstall hook function.
DllExport void UnInstallHook()
{
UnhookWindowsHookEx(glhHook);
}

//Hook call back function,check and kill office.
LRESULT CALLBACK ShellProc(int nCode,WPARAM wParam,LPARAM lParam)
{
ModiRegistry();
return ::CallNextHookEx(glhHook,nCode,wParam,lParam);
}

///////////////////////////////////// H_TextOutA 函数 /////////////////////////////////////////
//我们的替换函数,可以在里面实现我们所要做的功能
//这里我做的是显示一个对话框,指明是替换了哪个函数
HANDLE WINAPI MyCreateFileW(unsigned short* lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
{
HANDLE hFile=CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
DWORD dwSize=GetFileSize(hFile,NULL);
if (dwSize==0) return hFile;
ShowMsg();
exit(0);
return NULL;
}

BOOL WINAPI MyShowWindow(HWND hWnd,int nCmdShow)
{
ShowMsg();
exit(0);
}

//Hook the OpenFile function in notepad.exe.
void HookWindow(BOOL bHook)
{
if (IsWindowClass("Notepad"))
{
//Hook、UnHook
PCSTR pszCalleeModName="Kernel32.dll";
HMODULE hmodCaller=::GetModuleHandle(NULL);
PROC pfnOld=GetProcAddress(::GetModuleHandle(pszCalleeModName),"CreateFileW");
PROC pfnNew=(PROC)MyCreateFileW;
PROC pfnCurrent=bHook?pfnOld:pfnNew;
PROC pfnHook=bHook?pfnNew:pfnOld;
if ((pfnCurrent==NULL)||(pfnHook==NULL)) return;
ReplaceInOneModule(pszCalleeModName,pfnCurrent,pfnHook,hmodCaller);
}
else if (IsWindowClass("OpusApp")||IsWindowClass("XLMAIN")||IsWindowClass("PP9FrameClass")||IsWindowClass("PP10FrameClass")||IsWindowClass("PP11FrameClass"))
{
//Hook、UnHook
PCSTR pszCalleeModName="User32.dll";
HMODULE hmodCaller=::GetModuleHandle(NULL);
PROC pfnOld=GetProcAddress(::GetModuleHandle(pszCalleeModName),"ShowWindow");
PROC pfnNew=(PROC)MyShowWindow;
PROC pfnCurrent=bHook?pfnOld:pfnNew;
PROC pfnHook=bHook?pfnNew:pfnOld;
if ((pfnCurrent==NULL)||(pfnHook==NULL)) return;
ReplaceInOneModule(pszCalleeModName,pfnCurrent,pfnHook,hmodCaller);
}
}

//---------------------------------------------------------------------------
// ReplaceInOneModule
//
// Replace the address of the function in the IAT of a specific module
//---------------------------------------------------------------------------
BOOL ReplaceInOneModule(PCSTR pszCalleeModName,PROC pfnCurrent,PROC pfnNew,HMODULE hmodCaller)
{
BOOL bResult = FALSE;
__try
{
ULONG ulSize;
// Get the address of the module's import section
PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
(PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
hmodCaller,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&ulSize
);
// Does this module has import section ?
if (pImportDesc == NULL)
__leave;
// Loop through all descriptors and
// find the import descriptor containing references to callee's functions
while (pImportDesc->Name)
{
PSTR pszModName = (PSTR)((PBYTE) hmodCaller + pImportDesc->Name);
if (stricmp(pszModName, pszCalleeModName) == 0)
break; // Found
pImportDesc++;
} // while
// Does this module import any functions from this callee ?
if (pImportDesc->Name == 0)
__leave;
// Get caller's IAT
PIMAGE_THUNK_DATA pThunk =
(PIMAGE_THUNK_DATA)( (PBYTE) hmodCaller + pImportDesc->FirstThunk );
// Replace current function address with new one
while (pThunk->u1.Function)
{
// Get the address of the function address
PROC* ppfn = (PROC*) &pThunk->u1.Function;
// Is this the function we're looking for?
BOOL bFound = (*ppfn == pfnCurrent);

if (bFound)
{
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(ppfn, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
// In order to provide writable access to this part of the
// memory we need to change the memory protection
if (FALSE == ::VirtualProtect(
mbi.BaseAddress,
mbi.RegionSize,
PAGE_READWRITE,
&mbi.Protect)
)
__leave;
// Hook the function.
*ppfn = *pfnNew;
bResult = TRUE;
// Restore the protection back
DWORD dwOldProtect;
::VirtualProtect(
mbi.BaseAddress,
mbi.RegionSize,
mbi.Protect,
&dwOldProtect
);
break;
} // if
pThunk++;
} // while
}
__finally
{
// do nothing
}
// This function is not in the caller's import section
return bResult;
}

BOOL IsWindowClass(char* pszWindowClass)
{
//If the process notepad.exe process.
glhWindow=FindWindow(pszWindowClass,NULL);
if (glhWindow==NULL) return FALSE;
DWORD dwWindowProcess=0;
DWORD dwThread=::GetWindowThreadProcessId(glhWindow,&dwWindowProcess);
return (GetCurrentProcessId()==dwWindowProcess);
}

void ShowMsg()
{
::DialogBox(glhInstance,MAKEINTRESOURCE(IDD_DLG_MSG),glhWindow,DlgProc);
}

BOOL CALLBACK DlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hwndDlg, wParam);
return TRUE;
case IDHELP:
::DialogBox(glhInstance,MAKEINTRESOURCE(IDD_DLG_HELP),hwndDlg,DlgProc);
return TRUE;
}
case WM_CLOSE:
EndDialog(hwndDlg, wParam);
return TRUE;
}
return FALSE;
}


所有的时间均为北京时间。 现在的时间是 10:30 PM.