GetCurrentProcess得到无效句柄。

bj_leo_2000 2008-04-18 09:41:49
屏幕取词,我在dll中调用GetCurrentProcess得到的返回值总是-1,而WriteProcessMemory每次都返回内存分配访问无效、错误代码998.
代码如下:
#include "stdafx.h"
#include "MouseGetWord.h"
#include <ImageHlp.h>
#include <TlHelp32.h>
#pragma comment(lib,"ImageHlp")

#pragma data_seg("ShareData")
HWND ghWnd=NULL;
HMODULE g_hExe = 0; // 当前进程模块句柄
int gi_MousePosX = 0;
int gi_MousePosY = 0;
UINT gu_TimerID = 0;
HWND gh_MouseWnd = NULL;
#pragma data_seg()
#pragma comment(linker,"/SECTION:ShareData,RWS")
#define WM_MOUSEINFO WM_USER + 100

HHOOK ghMouseHook=NULL;
HINSTANCE ghInstance=NULL;

VOID CALLBACK TimerFunc(HWND wHwnd,UINT uMsg,UINT dEvent,DWORD dwTime);
BOOL WINAPI Hook_TextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString, int cbString);
VOID ModifyIATs(LPCSTR szDllName,PROC pfnOrg,PROC pfnNew);
//---------------------------------------------------------------------------
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
ghInstance = (HINSTANCE)hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
ModifyIATs("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.DLL"),
"TextOutA"),
(PROC)Hook_TextOutA);
break;
case DLL_PROCESS_DETACH:
ModifyIATs("GDI32.dll",(PROC)Hook_TextOutA,GetProcAddress(GetModuleHandle("GDI32.DLL"),"TextOutA"));
if (ghMouseHook != NULL)
{
UnhookWindowsHookEx(ghMouseHook);
ghMouseHook = NULL;
}
break;
}
return TRUE;
}

LRESULT CALLBACK MyHookProc(int aiCode ,WPARAM wParam,LPARAM lParam)
{
if(aiCode<0)
return CallNextHookEx(ghMouseHook,aiCode,wParam,lParam);
if(wParam==WM_MOUSEMOVE)
{
LPMOUSEHOOKSTRUCT lpMouse=(MOUSEHOOKSTRUCT *)lParam;
if(gu_TimerID != NULL)
{
KillTimer(NULL,gu_TimerID);
gu_TimerID = NULL;
}
gu_TimerID = SetTimer(NULL,0,500,(TIMERPROC)TimerFunc);
gh_MouseWnd = lpMouse->hwnd;
gi_MousePosX = lpMouse->pt.x;
gi_MousePosY = lpMouse->pt.y;
}
return CallNextHookEx(ghMouseHook,aiCode,wParam,lParam);
}

VOID CALLBACK TimerFunc(HWND wHwnd,UINT uMsg,UINT dEvent,DWORD dwTime)
{
KillTimer(NULL,gu_TimerID);
gu_TimerID = NULL;
POINT lp;
lp.x = gi_MousePosX;
lp.y = gi_MousePosY;
ScreenToClient(gh_MouseWnd,&lp);
RECT rect;
rect.left = gi_MousePosY - 1;
rect.right = gi_MousePosY + 1;
rect.top = gi_MousePosX - 1;
rect.bottom = gi_MousePosX +1;
InvalidateRect(gh_MouseWnd,&rect,TRUE);

}

extern "C" void SetWindowHandle(HWND ahWnd)
{
ghWnd = ahWnd;
}

extern "C" int StartGetWord()
{
ghMouseHook = SetWindowsHookEx(WH_MOUSE,(HOOKPROC)MyHookProc,ghInstance,0);
if(ghMouseHook == NULL)
return 1;
gu_TimerID = SetTimer(NULL,0,1000,(TIMERPROC)TimerFunc);
return 0;
}

extern "C" int StopGetWord()
{
if(ghMouseHook != NULL)
{
UnhookWindowsHookEx(ghMouseHook);
ghMouseHook = NULL;
}
if(gu_TimerID != NULL)
{
KillTimer(NULL,gu_TimerID);
gu_TimerID = NULL;
}
return 0;
}

VOID ModifyIAT(HMODULE hmodCaller,LPCSTR szDllName,PROC pfnOrg,PROC pfnNew)
{
PIMAGE_THUNK_DATA pITD;
char * lpTemp;
int liRet;
ULONG ulSize;
//对每一个用到的dll,在输入表中都用一个IMAGE_IMPORT_DESCRIPTOR类型的
//结构体保存该dll的信息
PIMAGE_IMPORT_DESCRIPTOR pIID;
//用ImageDirectoryEntryToData可以取得输入表中的第一项
//参数IMAGE_DIRECTORY_ENTRY_IMPORT指明要取得输入表,而不是其他表
pIID =(PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hmodCaller,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&ulSize);
//如果pIID为NULL,表示该模块没有输入表,返回
if( !pIID )
return;
//IMAGE_IMPORT_DESCRIPTOR有一个Name的成员,该成员是dll名字的RVA
//hmodCaller实质是模块映射到进程空间中的基地址,通过将它转换为PBYTE类型,
//再加上Name这个RVA就可以得到这项IMAGE_IMPORT_DESCRIPTOR记录的dll的名字
//将这个名字与我们要挂接的dll的名字比较
//如果两个名字不同,则pIID++取下一项IMAGE_IMPORT_DESCRIPTOR
for(; pIID->Name; pIID++)
{
lpTemp = MakePtr(PSTR,hmodCaller,pIID->Name);
if( !lstrcmpiA( szDllName,lpTemp))
break;
}
//如果遍历完所有dll都没有找到我们要挂接的dll,则返回
if( !pIID->Name )
return;
//可以从一个dll中输入多个函数.对每一个输入的函数,用一个IMAGE_THUNK_DATA
//结构体保存它的信息.在IMAGE_IMPORT_DESCRIPTOR中,有一个FirstThunk成员记录着
//第一个IMAGE_THUNK_DATA(这个IMAGE_THUNK_DATA保存着第一个输入函数的信息)的RVA
//我们用与取得dll名字一样的方法(基址+RVA)取得这个IMAGE_THUNK_DATA
pITD = MakePtr(PIMAGE_THUNK_DATA,hmodCaller,pIID->FirstThunk);
//IMAGE_THUNK_DATA有一个ul成员,它是一个共同体.通过这个共同体的Function成员,我们
//可以得到输入函数在进程空间中的真实地址
//将这个真实地址和我们要挂接的函数的地址比较,如果相同,则修改
//否则pITD++取下一个输入函数的信息
for(; pITD->u1.Function ; pITD++)
{
PROC* ppfn = (PROC*)&pITD->u1.Function;
if( *ppfn == pfnOrg )
{
WriteProcessMemory(GetCurrentProcess(),ppfn,&pfnNew,sizeof(PROC),NULL);
return;
}
}
}

VOID ModifyIATs(LPCSTR szDllName,PROC pfnOrg,PROC pfnNew){
BOOL fOk = FALSE;
MODULEENTRY32 me32;
HANDLE hSnapshot;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId());
me32.dwSize = sizeof( me32 );
//枚举当前进程的全部模块
for( fOk = Module32First( hSnapshot,&me32 ); fOk ; fOk = Module32Next(hSnapshot,&me32)){
if( me32.hModule != ghInstance ){
ModifyIAT(me32.hModule,szDllName,pfnOrg,pfnNew);
}
}
CloseHandle( hSnapshot );
}


BOOL WINAPI Hook_TextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString, int cbString)
{
COPYDATASTRUCT MyCDS;
MyCDS.dwData = 0X002;
MyCDS.cbData = cbString;
MyCDS.lpData = (PVOID )lpszString;
::SendMessage(ghWnd,WM_COPYDATA,(WPARAM)WindowFromDC(hdc),(LPARAM)(LPVOID)&MyCDS);
return TextOutA(hdc,nXStart,nYStart,lpszString,cbString);
}
...全文
1905 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
meiZiNick 2008-05-01
  • 打赏
  • 举报
回复
有点难度哦
arong1234 2008-04-19
  • 打赏
  • 举报
回复
GetCurrentProcess永远返回-1,这在MSDN上有说吧?只是不一定很清楚,所谓的伪句柄就是这个意思
要想在WaitForSingleObject, WriteRemoteMemory中用它,你必须用DuplicateHandle把它转换成一个真实的句柄
也许你也可以用OpenProcess(GetProcessId())打开一个句柄
bj_leo_2000 2008-04-18
  • 打赏
  • 举报
回复
看了不是GetCurrentProcess和WriteProcessMemory的问题,我同样的代码能截获MessageBox,但截获不了TextOutA
Kudeet 2008-04-18
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 bj_leo_2000 的回复:]
查看GetCurrentProcess返回值是0xffffffff,错误代码6,无效句柄。可很奇怪的是我看WriteProcessMemory返回值是1,msdn上说非0为成功,可我GetLastError返回错误代码是998
[/Quote]
这个998并不是WriteProcessMemory返回的呀,它应该只是表示上一次调用失败时的错误值
zhaoyu_me 2008-04-18
  • 打赏
  • 举报
回复
我记得GetCurrentProcess的返回值都是-1吧
看Vista SP1下用OD得到的GetCurrentProcess的代码:
774EB80D >/$ 83C8 FF or eax, FFFFFFFF
774EB810 \. C3 retn
XP SP2也是这个代码,可见Windows是用-1来代表本进程的
bj_leo_2000 2008-04-18
  • 打赏
  • 举报
回复
查看GetCurrentProcess返回值是0xffffffff,错误代码6,无效句柄。可很奇怪的是我看WriteProcessMemory返回值是1,msdn上说非0为成功,可我GetLastError返回错误代码是998
Yofoo 2008-04-18
  • 打赏
  • 举报
回复
GetCurrentProcess得到的返回值总是-1 你如何知道是-1 ???

WriteProcessMemory(GetCurrentProcess(), ...
可以用memcpy 代替
Kudeet 2008-04-18
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 bj_leo_2000 的回复:]
我在dll里挂了鼠标钩子,系统应该是在别的进程有鼠标消息产生的时候去检查这个拥有鼠标钩子处理过程的dll是否存在,如果不存在系统将自动在产生鼠标消息的进程里加载这个dll啊。GetCurrentProcess()不就得到这个进程的句柄了吗?WriteProcessMemory就改写了这个进程要挂接的API地址。不知道我这样理解对不对?
[/Quote]

基本应该是这样的,但挂接API通常需要修改API函数的入口地址来实现。上面的连接里面有示例,你也可以看《Windows核心编程》
bj_leo_2000 2008-04-18
  • 打赏
  • 举报
回复
我在dll里挂了鼠标钩子,系统应该是在别的进程有鼠标消息产生的时候去检查这个拥有鼠标钩子处理过程的dll是否存在,如果不存在系统将自动在产生鼠标消息的进程里加载这个dll啊。GetCurrentProcess()不就得到这个进程的句柄了吗?WriteProcessMemory就改写了这个进程要挂接的API地址。不知道我这样理解对不对?
Kudeet 2008-04-18
  • 打赏
  • 举报
回复
WriteProcessMemory之前应该在目标进程分配空间:
看看这里的示例:
http://www.xiaozhou.net/ReadNews.asp?NewsID=211
Kudeet 2008-04-18
  • 打赏
  • 举报
回复
WriteProcessMemory(GetCurrentProcess(),
// 这是什么意思,写到自己的进程,这样做有意义吗?
cnzdgs 2008-04-18
  • 打赏
  • 举报
回复
GetCurrentProcess只是返回一个假的句柄,即使不是-1也没什么用,如果真正需要进程句柄要用OpenProcess,不过你现在根本不需要进程句柄,在同一进程内直接访问内存即可。
API之网络函数1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同一个网络资源的连接 WNetCancelConnection 结束一个网络连接 WNetCancelConnection2 结束一个网络连接 WNetCloseEnum 结束一次枚举操作 WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接 WNetDisconnectDialog 启动一个标准对话框,以便断开同网络资源的连接 WNetEnumResource 枚举网络资源 WNetGetConnection 获取本地或已连接的一个资源的网络名称 WNetGetLastError 获取网络错误的扩展错误信息 WNetGetUniversalName 获取网络中一个文件的远程名称以及/或者UNC(统一命名规范)名称 WNetGetUser 获取一个网络资源用以连接的名字 WNetOpenEnum 启动对网络资源进行枚举的过程 2. API之消息函数 BroadcastSystemMessage 将一条系统消息广播给系统中所有的顶级窗口 GetMessagePos 取得消息队列中上一条消息处理完毕时的鼠标指针屏幕位置 GetMessageTime 取得消息队列中上一条消息处理完毕时的时间 PostMessage 将一条消息投递到指定窗口的消息队列 PostThreadMessage 将一条消息投递给应用程序 RegisterWindowMessage 获取分配给一个字串标识符的消息编号 ReplyMessage 答复一个消息 SendMessage 调用一个窗口的窗口函数,将一条消息发给那个窗口 SendMessageCallback 将一条消息发给窗口 SendMessageTimeout 向窗口发送一条消息 SendNotifyMessage 向窗口发送一条消息 3. API之文件处理函数 CloseHandle 关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等 CompareFileTime 对比两个文件的时间 CopyFile 复制文件 CreateDirectory 创建一个新目录 CreateFile 打开和创建文件、管道、邮槽、通信服务、设备以及控制台 CreateFileMapping 创建一个新的文件映射对象 DeleteFile 删除指定文件 DeviceIoControl 对设备执行指定的操作 DosDateTimeToFileTime 将DOS日期和时间值转换成一个 win32 FILETIME 值 FileTimeToDosDateTime 将一个 win32 FILETIME 值转换成DOS日期和时间值 FileTimeToLocalFileTime 将一个FILETIME结构转换成本地时间 FileTimeToSystemTime 根据一个FILETIME结构的内容,装载一个SYSTEMTIME结构 FindClose 关闭由FindFirstFile函数创建的一个搜索句柄 FindFirstFile 根据文件名查找文件 FindNextFile 根据调用FindFirstFile函数时指定的一个文件名查找下一个文件 FlushFileBuffers 针对指定的文件句柄,刷新内部文件缓冲区 FlushViewOfFile 将写入文件映射缓冲区的所有数据都刷新到磁盘 GetBinaryType 判断文件是否可以执行 GetCompressedFileSize 判断一个压缩文件在磁盘上实际占据的字节数 GetCurrentDirectory 在一个缓冲区中装载当前目录 GetDiskFreeSpace 获取与一个磁盘的组织有关的信息,以及了解剩余空间的容量 GetDiskFreeSpaceEx 获取与一个磁盘的组织以及剩余空间容量有关的信息 GetDriveType 判断一个磁盘驱动器的类型 GetExpandedName 取得一个压缩文件的全名 GetFileAttributes 判断指定文件的属性 GetFileInformationByHandle 这个函数提供了获取文件信息的一种机制 GetFileSize 判断文件长度 GetFileTime 取得指定文件的时间信息 GetFileType 在给出文件句柄的前提下,判断文件类型 GetFileVersionInfo 从支持版本标记的一个模块里获取文件版本信息

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧