跨进程API Hook.net
“好柿连连”通过精心收集,向本站投稿了8篇跨进程API Hook.net,下面是小编为大家整理后的跨进程API Hook.net,仅供参考,喜欢可以收藏与分享哟!
篇1:跨进程API Hook.net
跨进程APIHook(初稿) 什么是“跨进程APIHook”? 众所周知 Windows 应用程序的各种系统功能是通过调用API函数来实现,APIHook就是给系统的API附加上一段小程序,它能监视甚至控制应用程序对API函数的调用。所谓跨进程也就是让自己的程序来控制别人程序的AP
跨进程API Hook(初稿)
什么是“跨进程 API Hook”?
众所周知Windows应用程序的各种系统功能是通过调用API函数来实现。API Hook就是给系统的API附加上一段小程序,它能监视甚至控制应用程序对API函数的调用。所谓跨进程也就是让自己的程序来控制别人程序的API调用了。
API Hook 理论
通过对Win32 PE文件的分析(如果你还不熟悉PE文件格式,可以看看Iczelion的PE教程或者LUEVELSMEYER的<
API Hook 的实现
/* 1 */HANDLE hCurrent = GetModuleHandle(NULL);
/* 2 */IMAGE_DOS_HEADER *pidh;
/* 3 */IMAGE_NT_HEADERS *pinh;
/* 4 */IMAGE_DATA_DIRECTORY *pSymbolTable;
/* 5 */IMAGE_IMPORT_DESCRIPTOR *piid;
/* 6 */pidh = (IMAGE_DOS_HEADER *)hCurrent;
/* 7 */pinh = (IMAGE_NT_HEADERS *)((DWORD)hCurrent + pidh->e_lfanew);
/* 8 */pSymbolTable = &pinh->OptionalHeader.DataDirectory[1];
/* 9 */piid =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)hCurrent + pSymbolTable->VirtualAddress);
/*10 */do {
/*11 */ IMAGE_THUNK_DATA *pitd,*pitd2;
/*12 */ pitd = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->OriginalFirstThunk);
/*13 */ pitd2 = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->FirstThunk);
/*14 */ do {
/*15 */ IMAGE_IMPORT_BY_NAME *piibn;
/*16 */ piibn = (IMAGE_IMPORT_BY_NAME *)((DWORD)hCurrent + *((DWORD *)pitd));
/*17 */ PROC *ppfn = (PROC *)(pitd2->u1.Function);
/*18 */ if (!strcmp(“MessageBoxW”,(char *)piibn->Name)) {
/*19 */ oldMsg = (MsgBoxType)(ppfn);
/*20 */ DWORD addr = (DWORD)MyMessage;
/*21 */ DWORD written = 0;
/* 改变内存读写状态 */
/*22 */ DWORD oldAclearcase/“ target=”_blank“ >ccess;
/*23 */ VirtualProtect(&pitd2->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);
/*24 */ APIAddress = (DWORD)&pitd2->u1.Function;
/* 向内存映像写入数据 */
/*25 */ WriteProcessMemory(GetCurrentProcess,&pitd2->u1.Function, &addr,sizeof(DWORD), &written);
/*26 */ }
/*27 */ pitd++;pitd2++;
/*28 */ } while (pitd->u1.Function);
/*29 */ piid++;
/*30 */} while (piid->FirstThunk + piid->Characteristics
+ piid->ForwarderChain + piid->Name + piid->TimeDateStamp);
分析:
寻觅IMPORT TALBE
在/*1*/中我们使用GetModuleHandle(NULL)来返回当前进程在内存中映像的基地址。但这个值在文档中仅仅被描述为”a module handle for the specified module“,虽然他确实是进程内存映像的基地址。如果你不太放心的话也可以使用,GetModuleInformation函数来获得基地址,只不过你要额外包含psapi.h和psapi.lib了(这个库在VC6里没有,所以我就没有用这个函数了)。在/* 6 */里我们先找到IMAGE_DOS_HEADER结构,他的起始地址就是映像的基地址。/*7*/通过IMAGE_DOS_HEADER给出的PE文件头的偏移量,找到IMAGE_NT_HEADERS结构。顺藤摸瓜,IMAGE_NT_HEADERS里的OptionalHeader中的DataDirectory数组里的第二个元素正是指向我们想要的IMPORT TABLE的地址。在/*9*/中我们将其转化为一个IMAGE_IMPORT_DESCRIPTOR的结构指针存入piid中。
替换的API函数入口地址
在/*12*/和/*13*/中我们分别取得OriginalFirstThunk和FirstThunk结构,用于以后得到API函数的名称和入口地址。/*10*/的do循环让我们遍历每一个IMAGE_IMPORT_DESCRIPTOR结构也就是应用程序引用的每个DLL。在/*14*/的循环中我们遍历DLL中的IMAGE_THUNK_DATA结构来一一查询API的信息。/*16*/中我们将OriginalFirstThunk转换为IMAGE_IMPORT_BY_NAME结构用于获得API函数的名称进行比对。在/*18*/我们找到MessageBoxW函数之后,在/*19*/保存其原始入口地址便于以后恢复时使用。在/*23*/我们需要用VirtualProtect改变一下内存区域的读写性,因为一般应用程序的映像都是只读的,直接写入会造成一个非法访问的异常出现。在/*25*/我们写入自己函数的地址。
这样就基本完成一个API函数的重定向。
其他
恢复函数的API入口地址相对比较简单。只要把保存的值再写回去就可以了。上面的程序中/*24*/我用APIAddress保存了存有MessageBoxW入口地址的地方的地址,便于以后调用WriteProcessMemory恢复时使用。
跨进程理论
我们要用自己的函数来替代别人程序里的API函数,但我们的函数与别人的程序处于不同的进程空间内啊。不同的进程空间是不能相互调用函数的。因此我们要想办法把自己的函数放入别人的进程空间去。这时我们就需要使用DLL injection技术了。如果你对她还不是十分熟悉的话,建议看看Jeffrey Richter大师的<
MING APPLICATIONS FOR MICROSOFT WINDOWS>>,也可以参考陈宽达先生的<
简而言之,DLL injection就是想办法让对方的进程加载我们的一个DLL程序,把需要替换的函数放在我们这个DLL里。如此一来,我们的函数就进入了别人的进程空间了。DLL injection方法很多,Richter大师在书中对各方法利弊有详细解释,陈宽大先生的书中也有深入的分析。我在这里使用SetWindowsHookEx函数来达到目的。主要有这几个原因: 1, 不用重新启动系统,调试方便。2, 可以利用消息循环机制进行两个进程之间的通信,可以较好的掌握Hook的状态。便于安装与卸载。
SetWindowsHookEx之所以能完成DLL injection是因为它要给一个应用程序某个环节加上一个Hook,而Hook就要有Hook Procedure也就是Hook函数。如果这个Hook函数在一个DLL中,那么系统就会把这个DLL加载到SetWindowsHookEx的目标进程上。从而也就达到了我们DLL injection的目的了。当然这里我们会用WH_GETMESSAGE的Hook进行injection,因为这个Hook可以用来监视目标进程的消息循环方便我们的进程与目标进程通信。
跨进程的实现和几点注意
/* DllPart.Dll */
#include
#include
#include
#include
typedef (WINAPI *MsgBoxType)(HWND,LPCWSTR,LPCWSTR,UINT);
MsgBoxType oldMsg; /*API原入口地址*/
DWORD APIAddress; /*存储API入口地址的地方的地址*/
int WINAPI MyMessage(HWND hWnd ,LPCWSTR M1,LPCWSTR M2, UINT M3) {
/* 这是用来替换的函数 */
return oldMsg(hWnd,buf,M2,MB_OK);
}
const char szApp[] = ”DllPart.dll“;
HHOOK hHook; /*Hook的句柄*/
HMODULE hInst; /*DLL 模块句柄,用于SetWindowsHookEx函数*/
HWND hTarget; /*目标窗口句柄*/
/*DLL 入口*/
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID lpvReserved)
{
hInst = inst;
switch (reason) {
case DLL_PROCESS_ATTACH:
/*调试信息,表示DLL已经加载*/
MessageBox(NULL,”DLL_PROCESS_ATTACH“,szApp,MB_OK);
break;
case DLL_PROCESS_DETACH:
/*调试信息,表示DLL已经卸载*/
MessageBox(NULL,”DLL_PROCESS_DETACH“,szApp,MB_OK);
break;
}
return true;
}
/*显示GetLastError的信息*/
void showerr(const char *m) {
char message[255];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError()
,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),message,255, 0);
MessageBox(NULL,message,m,MB_OK);
}
//-----------------------
void UnHookApi() {
/*卸载API Hook用*/
}
void HookApi() {
/*加载API Hook同上面介绍的函数一样*/
}
//-----------------------
/*用于WH_GETMESSAGE的Hook Procedure*/
LRESULT CALLBACK GetMsgProc(int nCode,WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION) {
MSG *msg = (MSG *)lParam;
if (msg->message == WM_CHAR) {
if (msg->wParam == 'h') HookApi();
if (msg->wParam == 'u') UnHookApi();
}
}
return CallNextHookEx(hHook,nCode,wParam,lParam);
}
extern ”C“ __declspec(dllexport) SetAPIHook(HWND handle) {
DWORD ThreadId = GetWindowThreadProcessId(handle, NULL);
hTarget = handle;
MessageBox(NULL, ”Enabling CallWndProc Hook“, szApp, MB_OK);
hHook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInst,ThreadId);
if (hHook) {
MessageBox(NULL,”Hook OK!“, szApp, MB_OK);
} else {
showerr(”SetWindowsHookEx“);
}
}
extern ”C“ __declspec(dllexport) UnHookAPIHook() {
MessageBox(NULL, ”Disenabling CallWndProc Hook“, szApp, MB_OK);
if (UnhookWindowsHookEx(hHook)) {
MessageBox(NULL,”UnHook OK!“, szApp, MB_OK);
} else {
showerr(”UnHookWindowsHookEx“);
}
}
分析
几个需要注意的问题
SetAPIHook和UnHookAPIHook是我们自己进程调用的用来加载WH_GETMESSAGE Hook的函数。由于我们的程序要用LoadLibrary加载这个Dll因此这两个函数要用__declspec(dllexport)修饰,使其成为导出函数,才能被GetAddressProc函数找到。加上 extern ”C“是让编译器使用C语言编码方式。因为C++编译器会进行Dynamic Binding(C++函数重载的实现),将函数的参数类型附加到名称上。是函数的导出名看起来像SetAPIHook@XYTZX之类的,不利于GetAddressProc进行引用。因此使用extern ”C“让编译器不使用Dynamic Binding,自然使用extern”C“的函数也就不能被重载了。
不要忘记在GetMsgProc最后要调用CallNextHookEx函数,保证Hook链的完整性。
一定要在Hook Procedure中调用HookApi和UnHookApi函数,因为保存API入口地址的地方在目标进程中,你必须在目标进程的进程空间内完成卸载操作,不能在UnHookAPIHook或是SetAPIHook函数中调用,因为UnHookAPIHook是我们的进程调用的,因此在我们的进程空间中。在这里使用UnHookApi会造成一个非法访问的错误。而使用HookApi会给自己的DLL加上API Hook。
SetWindowsHookEx的最后参数是ThreadId不是Handle,因此要通过调用GetWindowThreadProcessId转换一下。
在跨进程API HOOK时可能用到的其他技术
主进程与目标进程的信息交互和共享
由于使用了WH_GETMESSAGE钩子我们可以利用Windows消息机制实现进程间通讯。需要注意的是应该使用PostThreadMessage来发送让WH_GETMESSAGE得到的消息而不是SendMessage或者PostMessage,因为后两个是用来给窗口发送消息的。而我们的WH_GETMESSAGE是Hook在线程上面的,因此需使用PostThreadMessage.
传递不太大的数据可以使用WM_COPYDATA消息来进行。同样也应该注意,如果使用MFC的窗口过程获得消息就需要用SendMessage发送了。WM_COPYDATA的使用相对简单可以参考MSDN的文档。也可以参考附录里的程序Hook.cpp的showerr函数部分。
如果传递较大的数据或者希望数据共享比较方便可以开辟共享内存来进行数据共享。这里简单分析一下使用共享内存的代码
HANDLE hMap;
switch (reason) {
case DLL_PROCESS_ATTACH:
/*创建/打开共享内存区域*/
hMap = CreateFileMapping((HFILE *)0xFFFFFFFF,NULL,PAGE_READWRITE,0,sizeof(GLOBALDATA),ID_MAP);
pg_data = (GLOBALDATA*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0 ,0 ,0);
if (!pg_data) {
MessageBox(NULL,”无法建立共享内存,程序终止!“,szApp,MB_OK);
if (hMap) {
CloseHandle(hMap);
hMap = NULL;
return 0;
}
}
pg_data->hInst = hInst;
showerr(”共享内存映像文件“);
showerr(”DLL装载中...“,FALSE);
break;
case DLL_PROCESS_DETACH:
if (pg_data) {
UnmapViewOfFile(pg_data);
pg_data = NULL;
}
if (hMap) {
CloseHandle(hMap);
hMap = NULL;
}
break;
}
上面的代码通过CreateFileMapping建立共享区域。将其第一个参数设置为0xFFFFFFFF使其能创建一个内存共享区域而不是文件。并标记为可读写的(PAGE_READWRITE).其大小为我们定义的结构体GLOBALDATA的大小。最后的ID_MAP是一个用来标示这个区域的字符串。打开或者创建完共享区域后,我们用MapViewOfFile来获得这个区域的地址。之后就可以直接使用pg_data来操作共享区域了。不要忘记在DLL退出的时候安全的删除共享区域释放内存。
消息等待与安全卸载
在我们卸载WH_GETMESSAGE钩子之前必须先把目标程序的API调用恢复正常。我们不能再调用UnHookApi之后就立刻调用UnhookWindowsHookEx,因为很有可能UnHookApi还没来得急完成API入口地址的恢复操作,WH_GETMESSAGE钩子就已经被卸载了。因此需要等待一段时间,等UnHookApi完成了恢复操作在调用UnhookWindowsHookEx。以防错误发生。
extern ”C“ __declspec(dllexport) void UnHookAPIHook() {
/*向目标线程发送消息进行API UNHOOK*/
PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOK,(WPARAM)GetCurrentThreadId(),0);
showerr(”WM_DISABLEAPIHOOK“);
/*等待目标进程返回WM_UNHOOKOK消息,确认可以将WH_GETMESSAGE的HOOK去掉*/
MSG Msg;
do {
GetMessage(&Msg,NULL,0,0);
}while(Msg.message != WM_UNHOOKOK);
UnhookWindowsHookEx(pg_data->hHook);
PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOKOK,(WPARAM)GetCurrentThreadId(),0);
showerr(”UnHookWindowsHookEx“);
}
上面的代码中我们使用一个含有GetMessage的循环来等待消息的到达,一旦UnHookApi完成他就会发送WM_UNHOOKOK消息。等我们接收到消息确认一切安全了在来卸载WH_GETMESSAGE钩子。
弄清消息对象
我们一定要清楚代码是在主程序进程空间中执行的还是在目标程序进程空间中执行的。像上面的UnHookAPIHook函数就是通过主程序调用的,因此在主程序进程空间中执行。这样一来用来恢复目标程序API信息的UnHookApi完成后就应该向主程序发送消息,而不是目标程序。
目标进程加载了其他DLL
如果目标进程动态加载了其他的DLL文件,我们必须监视LoadLibrary函数。保证DLL中的API入口地址也被正确修改。防止出现混乱的情况。我从LoadLibrary获得DLL的路径用于GetModuleHandle来取得他的ImageBase的地址。
不知道文章写的如何,希望大家能多给些批评意见。发现问题我马上改正
Email: detrox@yang.com.cn
参考资料
<
>, Jeffrey Richter, Microsoft Press
<
<
<
附:跨进程APIHook的例子
先打开一个记事本程序并输入几个字符,运行下面的程序,加载APIHook.之后在记事本的文件菜单中选择新建就会看到API Hook将MessageBoxW 函数Hook的结果了.
代码在WinXPSP1 + VC6.0测试成功,
下载源代码
(特别感谢老罗的代码着色器,比我自己那个好多了)
这是DLL的程序,Hook.dll
#include
#include
#include
#include
#include ”mydef.h“
const char szApp[] = ”Hook.dll“; /*应用程序名称*/
HANDLE hMap;/*在共享内存映像的句柄*/
GLOBALDATA *pg_data; /*在共享内存中的全局数据*/
LRESULT CALLBACK GetMsgProc(int,WPARAM, LPARAM);
/*显示GetLastError指出的错误*/
void showerr(const char *m, BOOL GetError = TRUE) {
char message[127];
char buf[255];
COPYDATASTRUCT cds;
if (GetError)
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0
,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),message,127, 0);
else
*message = 0;
if (GetCurrentThreadId() != pg_data->idMain)
sprintf(buf,”目标程序空间DLL: %-30s [%-40s]“,m, message);
else
sprintf(buf,”主程序空间DLL : %-30s [%-40s]“,m, message);
cds.lpData = buf;
cds.cbData = sizeof(buf);
cds.dwData = 0;
SendMessage(pg_data->hWndMain,WM_COPYDATA,(WPARAM)pg_data->hWndTarget,(LPARAM)&cds);
SetLastError(0);
}
int WINAPI MyMessageBoxW(HWND hWnd ,LPCWSTR M1,LPCWSTR M2, UINT M3) {
wchar_t buf[255];
swprintf(buf,L”!!这个窗口的API被Hook了!! HWND: 0x%08X Message: %s Caption: %s“
,(DWORD *)hWnd
, M1
, M2);
pg_data->oldAPIFunction(hWnd,buf,M2,MB_OK);
return pg_data->oldAPIFunction(hWnd,M1,M2,M3);
}
/*DLL 入口函数*/
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason,LPVOID lpvReserved)
{
switch (reason) {
case DLL_PROCESS_ATTACH:
/*创建/打开共享内存区域*/
hMap = CreateFileMapping((HFILE *)0xFFFFFFFF,NULL,PAGE_READWRITE,0,sizeof(GLOBALDATA),ID_MAP);
pg_data = (GLOBALDATA*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0 ,0 ,0);
if (!pg_data) {
MessageBox(NULL,”无法建立共享内存,程序终止!“,szApp,MB_OK);
if (hMap) {
CloseHandle(hMap);
hMap = NULL;
return 0;
}
}
pg_data->hInst = hInst;
showerr(”共享内存映像文件“);
showerr(”DLL装载中...“,FALSE);
break;
case DLL_PROCESS_DETACH:
showerr(”DLL卸载中...“,FALSE);
if (pg_data) {
UnmapViewOfFile(pg_data);
pg_data = NULL;
}
if (hMap) {
CloseHandle(hMap);
hMap = NULL;
}
break;
}
return true;
}
/*卸载API Hook*/
void UnHookApi() {
DWORD written = 0;
DWORD oldaddrAPIFunction = (DWORD)pg_data->oldAPIFunction;
WriteProcessMemory(GetCurrentProcess(),(DWORD *)pg_data->addrAPIEntryPoint
, &oldaddrAPIFunction,sizeof(DWORD), &written);
showerr(”WriteProcessMemory on UnHook“);
/*向主线程发送 API UNHOOK 处理完毕的消息*/
PostThreadMessage(pg_data->idMain,WM_UNHOOKOK,0,0);
}
/*加载API Hook*/
void HookApi(const char* szApiName, tAPIFunction newAddr, DWORD ImageBase) {
/*这段代码请参考文章中的分析*/
IMAGE_DOS_HEADER *pidh;
IMAGE_NT_HEADERS *pinh;
IMAGE_DATA_DIRECTORY *pSymbolTable;
IMAGE_IMPORT_DESCRIPTOR *piid;
pidh = (IMAGE_DOS_HEADER *)ImageBase;
pinh = (IMAGE_NT_HEADERS *)((DWORD)ImageBase + pidh->e_lfanew);
pSymbolTable = &pinh->OptionalHeader.DataDirectory[1];
piid =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)ImageBase + pSymbolTable->VirtualAddress);
do {
IMAGE_THUNK_DATA *pitd_org,*pitd_1st;
pitd_org = (IMAGE_THUNK_DATA *)((DWORD)ImageBase + piid->OriginalFirstThunk);
pitd_1st = (IMAGE_THUNK_DATA *)((DWORD)ImageBase + piid->FirstThunk);
do {
IMAGE_IMPORT_BY_NAME *piibn;
piibn = (IMAGE_IMPORT_BY_NAME *)((DWORD)ImageBase + *((DWORD *)pitd_org));
PROC *pAPIFunction = (PROC *)(pitd_1st->u1.Function);
if (!strcmp(szApiName,(char *)piibn->Name)) {
DWORD addrNewAPIFunction = (DWORD)MyMessageBoxW;
DWORD written = 0;
DWORD oldAccess;
pg_data->oldAPIFunction = (tAPIFunction)(pAPIFunction);
/*Change Memeory State*/
VirtualProtect(&pitd_1st->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);
showerr(”VirtualProtect“);
pg_data->addrAPIEntryPoint = (DWORD)&pitd_1st->u1.Function;
/*Write Process Memory*/
WriteProcessMemory(GetCurrentProcess(),&pitd_1st->u1.Function
, &addrNewAPIFunction,sizeof(DWORD), &written);
showerr(”WriteProcessMemory on Hook“);
}
pitd_org++;
pitd_1st++;
} while (pitd_1st->u1.Function);
piid++;
} while (piid->FirstThunk + piid->Characteristics
+ piid->ForwarderChain + piid->Name + piid->TimeDateStamp);
}
//-----------------------
extern ”C“ __declspec(dllexport) BOOL SetAPIHook(HWND _target) {
pg_data->hHook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,pg_data->hInst,pg_data->idTarget);
showerr(”SetWindowsHookEx“);
/*向目标线程发送消息进行API HOOK*/
if (pg_data->hHook) {
PostThreadMessage(pg_data->idTarget,WM_ENABLEAPIHOOK,0,0);
} else {
return FALSE;
}
showerr(”WM_ENABLEAPIHOOK“);
return TRUE;
}
extern ”C“ __declspec(dllexport) void UnHookAPIHook() {
/*向目标线程发送消息进行API UNHOOK*/
PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOK,(WPARAM)GetCurrentThreadId(),0);
showerr(”WM_DISABLEAPIHOOK“);
/*等待目标进程返回WM_UNHOOKOK消息,确认可以将WH_GETMESSAGE的HOOK去掉*/
MSG Msg;
do {
GetMessage(&Msg,NULL,0,0);
}while(Msg.message != WM_UNHOOKOK);
UnhookWindowsHookEx(pg_data->hHook);
PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOKOK,(WPARAM)GetCurrentThreadId(),0);
showerr(”UnHookWindowsHookEx“);
}
LRESULT CALLBACK GetMsgProc(int nCode,WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION) {
MSG *msg = (MSG *)lParam;
if (msg->message == WM_ENABLEAPIHOOK) {
HookApi(”MessageBoxW“,MyMessageBoxW,(DWORD)GetModuleHandle(NULL));
}
if (msg->message == WM_DISABLEAPIHOOK) {
UnHookApi();
}
if (msg->message == WM_DESTROY) {
showerr(”目标进程退出!“,FALSE);
}
}
return CallNextHookEx(pg_data->hHook,nCode,wParam,lParam);
}
这个是主程序的关键部分 HookGui.cpp
用MFC建立一个窗口程序,包含两个按钮和一个ListBox
typedef void (*PUnHookAPIHook)();
typedef BOOL (*PSetAPIHook)(HWND);
HMODULE hDll = NULL;
HWND hNotePad = NULL;
PSetAPIHook SetAPIHook;
PUnHookAPIHook UnHookAPIHook;
GLOBALDATA *pg_data; /*在共享内存中的全局数据*/
HANDLE hMap; /*在共享内存映像的句柄*/
int CHookGUIDlg::showerr(const char* m) {
char message[127];
char buf[255];
int errId = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0
,errId,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),message,127, 0);
sprintf(buf,”主程序 : %-30s [%-40s] “,m, message);
c_List1.InsertString(c_List1.GetCount(),buf);
UpdateData(FALSE);
return errId;
}
void CHookGUIDlg::OnSetapihook()
{
// TODO: Add your control notification handler code here
hDll = LoadLibrary(”Hook.dll“);
showerr(”LoadLibrary“);
hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,false,ID_MAP);
showerr(”OpenFileMapping“);
pg_data = (GLOBALDATA *)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);
showerr(”MapViewOfFile“);
if (!pg_data) {
MessageBox(”不能打开共享内存程序终止!“);
return;
}
SetAPIHook = (PSetAPIHook)GetProcAddress(hDll,”SetAPIHook“);
showerr(”GetProcAddress-SetAPIHOOK“);
pg_data->hWndTarget = ::FindWindow(”NotePad“,NULL);
pg_data->hWndMain = m_hWnd;
pg_data->idMain = GetWindowThreadProcessId(m_hWnd,NULL);
pg_data->idTarget = GetWindowThreadProcessId(pg_data->hWndTarget,NULL);
if (!showerr(”FindWindow“)) {
if (SetAPIHook) {
if (SetAPIHook(hNotePad))
PostThreadMessage(pg_data->idTarget
, WM_SETCALLERID,(LPARAM)GetCurrentThreadId(),0);
else {
MessageBox(”SetWindowHookEx时出错,程序终止!“);
return;
}
} else {
MessageBox(”无法取得SetAPIHook函数!程序终止!“);
}
} else {
MessageBox(”内存中没有找到NOTEPAD.EXE“);
}
c_SetApiHook.EnableWindow(FALSE);
c_UnsetApiHook.EnableWindow();
}
void CHookGUIDlg::OnUnsetapihook()
{
// TODO: Add your control notification handler code here
if (hDll) {
if ( !IsWindow(pg_data->hWndTarget)) {
MessageBox(”目标进程不在内存中“);
return;
}
UnHookAPIHook = (PUnHookAPIHook)GetProcAddress(hDll,”UnHookAPIHook“);
showerr(”GetProcAddress-UnHookAPIHook“);
if (UnHookAPIHook)
UnHookAPIHook();
FreeLibrary(hDll);
showerr(”FreeLibrary“);
hDll = NULL;
} else {
MessageBox(”请先加载DLL");
}
c_SetApiHook.EnableWindow();
c_UnsetApiHook.EnableWindow(FALSE);
}
void CHookGUIDlg::OnOK()
{
// TODO: Add extra validation here
if (hDll) {
OnUnsetapihook();
}
CDialog::OnOK();
}
BOOL CHookGUIDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
// TODO: Add your message handler code here and/or call default
c_List1.InsertString(c_List1.GetCount(),(char *)pCopyDataStruct->lpData);
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
原文转自:www.ltesting.net
篇2:如何跨进程发送字符串?(收藏)数据库教程
进程|字符串
如何跨进程发送字符串?
问题描述:
如何跨进程发送字符串?
解决方案:
参考:
blog.csdn.net/wu_07/archive//11/26/194814.aspx
community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=205761
个人:
有两种办法:
一是向目标对象发送wm_settext消息
参考:
www.ttian.net/article/show.php?id=132
community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=204580
www.vchelp.net/itbookreview/view_paper.asp?paper_id=1198
dev.csdn.net/article/58/58647.shtm
dev.19xz.com/soft/60230.htm
二是先将要发送的内容复制到剪贴板,再向目标对象发送wm_paste消息
www.blogcup.com/read_yang119345_5312.html
www.zdnet.com.cn/developer/code/story/0,081534,39156949,00.htm
两种方法都必须首先用FindWindowEx等函数首先枚举到目标对象的句柄,下面操作就简单了,
如何跨进程发送字符串?(收藏)数据库教程
,
篇3:Windows CE跨进程内存注入的原理
近日,由于程序设计需要,我对WincowsCE 的内存布局进行了研究,由于发现国内在这方面的文档资料较少,于是在研究告一段落之际,形成这篇示例文档,以望抛砖引玉,得到别的高手的指正,
一、程序实现的先决条件
由于Windows系统的窗体消息总是投递至一个特定进程的指定窗体消息函数中。于是在本地进程(自己的应用程序)中取得属于其它进程的窗体的消息必须实现以下两个部分:
1、将需要挂接窗体的代码放到目标进程的地址空间中去。
2、执行这一段代码,并获得目标进程窗体的消息。
这两步看起来很简单,但在实现过程中就比较困难。由于Windows CE作为嵌入式移动设备操作系统,与Windows 98/2000/XP等桌面操作系统在内核的设计理念以及API的支持上有极大的区别。这就直接导致了常规的桌面系统利用全局鼠标钩子注入/远程线程注入等方法在CE中完全得不通。不过可喜的是,微软在开发工具中提供的remotexxx等远程调试程序使我清楚这个目标并不是不可能的任务,微软既然可以做到,那就是说在CE的内部一定有一套完整的跨进程内存访问/代码注入的机制。
二、程序实现的基本原理
经过两天的google 搜索,在网上我发现了一个没有在微软文档中声明的有趣的API函数:PerformCallBack4,传说中这个函数可以在自己的应用程序中执行指定的进程中的一个函数,So Cool!这好象正是我所需要的东西。虽然网上也传闻这个函数在wm5不受支持,其实经过实践这个传闻只是谣传而已!
PerformCallBack4函数的定义:
public static extern uint PerformCallBack4(ref CallBackInfo CallBackInfo,
IntPtr ni_pVoid1,IntPtr ni_pVoid2,IntPtr ni_pVoid3);
其中函数的参数CallBackInfo结构定义:
public struct CallBackInfo
{
public IntPtr hProc; //远程的目标进程
public IntPtr pfn; //指向远程目标进程的函数地址的指针
public IntPtr pvArg0; //函数的需要的第一个参数
}//end struct
而PerformCallback4的 ni_pVoid1、ni_pVoid2、ni_pVoid3为传递到远程目标进程执行函数的其它三个参数,
至于将代码放到目标进程的内存空间,我们可以利用CE设计上的一个特性:
1、为了节约内存使用,CE将所有程序调用的动态链接库(DLL)都映射到同一个内存地址中。
2、CE的内存布局中划分有一个slot0的内存位置,这个内存位置是由正在执行的进程所占有的,每一个特定的时间片,只能有一个进程可以占有这个内存空间。在进程要求执行时,系统并不直接执行进程所处内存位置的代码,而是将该进程的执行代码复制到slot0的内存位置中产生一个副本执行。也就是说进程在执行时内存将会有进程执行代码的两个完全一样的版本:存在于slot0中正在执行的进程代码和进程本身所处的内存中的代码。
在这个特性下,可以得到结论:如果进程A通过LoadLibrary函数装载Test.dll,而进程B也通过LoadLibrary函数装载同一个Test.dll,这个Test.dll的所有函数在进程A和进程B中执行时,相对于slot0中的进程执行代码都会得到同一地址。
3、在CE中,系统在内存中划分出33个slot,slot0保留给正在执行的进程,然后在进程启动时将所有的代码放到除slot0以外的一个slot中(这就是臭名昭著的CE系统中内存最多只能有不多于32个程序执行的限制的来由)。在进程执行时,每个应用程序的内存访问默认只能访问slot0内存空间中的地址以及进程所处的slot内存空间的地址。 但为使设备驱动程序可以访问到它们所需的其它应用程序数据,CE提供了两个函数以打破这个限制,SetKmode和SetProcPermission,SetKmode函数告诉系统,当前运行的进程是否需要在内核模式中执行;SetProcPermission函数可以接受一个位掩码,每一位代码一个slot的访问控制,1代表可以访问该slot的内存内容。0表示不能访问该slot的内存内容。这两个函数在msdn中有帮助文档,可参阅msdn的文档说明。
篇4:进程通信
两个并行进程可以通过互相发送消息进行合作,消息是通过消息缓冲而在进程之间相互传递的,
进程通信
,
篇5:explorer.exe是什么进程
explorer.exe是什么进程
1. 什么是Explorer.exe进程
打开的电脑的任务管理器,可以看到这个进程,占用内存不大,大约10MB左右。结束这个进程后,打开的几个窗口都关闭了,而且桌面上的图标也全没有了。
之所以出现这个情况,正是Explorer.exe在发挥作用。简单地说,Explorer.exe进程就是操作系统的程序管理器,也就是我们平时说的资源管理器,用于管理操作系统之家的图形界面,包括开始菜单、任务栏,桌面和文件管理。该进程随系统一起启动,直到系统关闭或者人为结束该进程。可以通过下面的操作恢复桌面到正常状态:在“任务管理器”中,依次单击“文件”-“新建任务(运行)”菜单。在打开的窗口中输入“Explorer.exe”进程名单击“确定”按钮即可完成重建进程的过程了,桌面环境也就恢复了。
2.Explorer.exe容易被冒充
首先,病毒还是会利用障眼法来干扰大家,正常的进程名是Explorer.exe,而一些病毒的进程名则为ExpIorer.exe(用数字I代替了字母l),还有的病毒进程名为ExplOrer.exe(用数字0代替o),乍一看,根本就区分不出来 ,实在令人防不胜防。大名鼎鼎的MyDoom病毒就是通过Explorer.exe来进行破坏的。
小知识 MyDoom是一种通过电子邮件附件和P2P网络传播的病毒,当用户打开并运行附件内的病毒程序后,病毒就会以用户信箱内的电子邮件地址为目标,仿造邮件的源地址,向外发送大量带有病毒附件的电子邮件,同时在用户主机上生成Explorer.exe进程。
针对这类情况,除了我们留意进程名字外,还有其他方法进程检测和防范呢?我们可以根据Explorer.exe进程的路径来判断,正常的Explorer.exe进程位于系统根目录下(比如系统盘为C盘,则路径为C:WindowsExplorer.exe),这里我们可以借助一些进程辅助软件来进行查看,比如“360”等能查看进程的软件,观察一下进程路径。
除此之外,在系统的system.ini文件中(C:Windowssystem.ini),在[BOOT]下面有个“shell=文件名”。正确的文件名应该是“Explorer.exe”如果不是“Explorer.exe”而是“shell=Explorer.exe程序名”,那么后面跟着的那个程序就是“木马”程序,这表明你已经中了“木马”了。
此外,在注册表中的情况比较复杂,通过regedit命令打开注册表编辑器,依次打开HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionRun目录下,查看键值中有没有自己不熟悉的自动启动文件,扩展名为EXE,注意有的“木马”程序生成的文件很像系统自身文件,想通为伪装蒙混过关,如“Acid Battery v1.0木马”,它将注册表“HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionRun”下的Explorer键值改为Explorer=“C:Windowsexpiorer.exe”,和ghost xp程序就差一个字母。这需要大家高度警惕。
病毒除了通过文件名相似为伪装Explorer.exe进程外,主要是通过线程插入技术来利用这个进程。比如说曾经的广外幽灵、魔波病毒变种也是利用系统下载进程。线程插入技术使得这些病毒木马可以将他们的服务端程序插入到正常的Explorer.exe进程中,从而让用户找不到病毒的蛛丝马迹。对于这类采用线程插入的木马病毒,我们可以借助“木马辅助查找器”来进行查看,在“进程监控”选项中,勾选Explorer.exe进程,在下面的DLL文件窗口中将显示相应的DLL文件的路径和文件名,发现可疑的最新xp系统下载文件,则直接终止相应的进程即可。当然,这需要大家对常见的木马有基本的了解,否则操作起来就显得比较难。
篇6:msiexec.exe是什么进程
msiexec.exe是用于安装Windows Installer安装包(MSI)这个程序对你系统的正常运行是非常重要的。出现msiexec.exe进程原因:此进程一般在运行Microsoft Update安装更新或安装部分软件的时候出现,占用内存比较大!
当遇到msiexec.exe被误删的时候不要急,你只需要用安装光盘选择修复功能,就可以了。msiexec.exe文件是Windows Installer 的一个组件。 当 Msiexec.exe 被安装程序调用时,它将用 Msi.dll 读取软件包文件 (.msi)、应用转换文件 (.mst) 并合并由安装程序提供的命令行选项。 Windows Installer 执行所有与安装有关的任务:包括将文件复制到硬盘、修改注册表、创建桌面快捷方式、必要时显示提示对话框以便用户输入安装首选项。
当 Windows Installer 被安装在计算机上时,它将更改 .msi 文件的已注册文件类型,以便您双击 .msi 文件即可使该文件与 Msiexec.exe 一起运行
篇7:msiexec.exe是什么进程
msiexec.exe进程程序文件是由微软为其发布的Windows操作系统(Windows 时提出)定义的一个系统进程,官方描述为:Windows installer或Windows安装程序,其主要功能是用于安装新程序。当Msiexec.exe被安装程序调用时,它将用Msi.dll读取软件包文件(.msi)、应用转换文件(.mst)并合并由安装程序提供的命令行选项。 Windows Installer执行所有与安装有关的任务:包括将文件复制到硬盘、修改注册表、创建桌面快捷方式、必要时显示提示对话框以便用户输入安装首选项。通常Msiexec.exe会在微软自动更新、系统升级、或安装部分软件时启动,这时用户能够通过任务管理器看到该进程在后台运行,同时可能伴有大量的内存和CPU占用情况。
Msiexec.exe命令行的一般形式是这样的:
MSIEXEC.EXE package_parameters]
作为普通用户,当看见本进程在运行时如非出现下文中的情况不建议你结束其运行,另外我们可以在系统中的以下位置发现本进程文件:
所在位置:C:WindowsSystem32(C代表系统盘所在盘符,这是本程序的唯一位置)
Msiexec.exe病毒
由于是一个Windows系统自身的进程,故而很多木马病毒及恶意程序会尝试将其感染或使用同名次及类似名称来迷惑用户,相关木马、蠕虫病毒感染实例已被安全厂商拦截。
如果你的中出现这些情况应该保持警惕:在Windows任务管理器中发现两个同名程序在运行、或者本程序不在系统盘中的System32目录中、如果没有进行软件的安装本进程也会时不时的运行或者开机就自动运行、或者系统提示本程序出现错误等情况都很有可能被感染了木马病毒或恶意软件,建议更新杀毒软件最新病毒库后进行全盘查杀通常可解决,如果故障依旧建议还原或重装操作系统。
[msiexec.exe是什么进程]
篇8:后台进程
实例后台进程在启动实例时启动,在终止实例时终止运行,
1.SMON
起初的任务是安装和打开数据库。SMON通过查找和验证数据库控制文件来安装数据库。此后,通过查找和验证所有的 数据文件和联机日志文件打开数据库。一旦打开数据库并使数据库处于使用状态后,SMON就负责执行各种内部管理任务,如合并数据文件中的可用空间。
2.PMON
PMON监视所有服务器进程,并检测会话中的任何资源。如果会话异常终止,PMON将销毁服务器进程,将其PGA内存返回给操作系统的空闲内存池,并回滚任何尚在进行的未完成事务,
3.DBWn
会话将数据写入数据库缓冲区缓存中的缓冲区,DBWn将数据库缓冲区缓存中的数据写入磁盘。
注:在提交事务的时候,DBWn有什么举动? 什么都不做!
4.LGWR&ARCn
LGWR将日志缓冲区中的内容写到磁盘上的联机日志文件中,ARCn将联机日志文件中的内容写到归档日志文件中。
5.CKPT
负责发出普通检查点的信号,激发DBWn。从8i开始,DBWn用增量检查点替代了完全检查点。
注:何时发生完全检查点? 只会应要求这么做,或在有序关闭数据库的时候出现。
【跨进程API Hook.net】相关文章:
1.进程的近义词
2.跨过去现代诗歌
3.跨年夜祝福语
4.跨服口号
7.向前跨一步作文
8.跨年夜的说说
9.跨过去高中作文
10.跨年夜简短祝福语






文档为doc格式