一个关于CreateRemoteThread函数调用问题

wjling2009 2009-04-07 10:04:42
下面的程序是将一个dll注入到一个进程当中,实现的内容与《Windows核心编程》里面的例子代码基本相同,但不考虑UNICODE,另外我在程序中加入了很多的MessageBox以便能够容易找到错在哪里。
问题是CreateRemoteThread这个函数一直无法调用成功!我跟踪调试发现获取LoadLibrary地址成功,向远程进程写字符串也成功,这让我很郁闷!另外,我用GetLastError()获取失败信息,它返回0,也就是ERROR_SUCCESS ,让我很疑惑。而FormatMessage返回0,这个函数的调用有错误码?

下面是程序的代码:

BOOL WINAPI CInjectDlg::InjectLib(DWORD dwProcessId, PCSTR pLibFile)
{
//注入dll函数
//假定返回false
//本地库文件字符串缓存
PSTR pLibFileRemote=NULL;
HANDLE hProcess=NULL;
HANDLE hThread=NULL;


//下面获取注入目标进程的句柄,使用OpenProcess
hProcess=OpenProcess(PROCESS_CREATE_PROCESS |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE,NULL,dwProcessId);
if(hProcess==NULL)
{
MessageBox("获取目标进程句柄失败!");
return FALSE;
}
//在远程进程申请路径内存
int len=strlen(pLibFile)+1;
pLibFileRemote=(PSTR)VirtualAllocEx(hProcess,NULL,len,
MEM_COMMIT,PAGE_READWRITE);
if(pLibFileRemote==NULL)
{
MessageBox("在远程进程申请路径字符串内存空间失败!");
return FALSE;
}
//将本地字符串复制到远程进程中
if(!WriteProcessMemory(hProcess,pLibFileRemote,(PVOID)pLibFile,len,NULL))
{
MessageBox("向远程进程写字符串失败!");
return FALSE;
}
//获取Kernel32.dll中LoadLibrary的地址
LPTHREAD_START_ROUTINE pfnThreadRtn;
pfnThreadRtn=(LPTHREAD_START_ROUTINE)GetProcAddress(
GetModuleHandle("Kernel32"),"LoadLibraryA");
if(pfnThreadRtn==NULL)
{
MessageBox("获取LoadLibrary地址失败!");
return FALSE;
}
//创建远程线程,并且执行LoadLibrary(pLibFileRomete)
hThread=CreateRemoteThread(hProcess,NULL,0,pfnThreadRtn,
pLibFileRemote,0,NULL);
if(hThread==NULL)
{
MessageBox("创建远程执行线程失败!");
DWORD dwError=GetLastError();
LPSTR str=NULL;
BOOL rtn=::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER,NULL,dwError,0,
str,0,NULL);
if(rtn)
MessageBox(str);
return FALSE;
}
//等待远程线程执行完毕
WaitForSingleObject(hThread,INFINITE);
//完成清理工作
VirtualFreeEx(hProcess,pLibFileRemote,0,MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;


}

EjectLib(DWORD dwProcessId, PCSTR pLibFile)函数就不列出了
DLL的代码如下:

BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
)
{
if(fdwReason==DLL_PROCESS_ATTACH)
{
//cBuf定义所有要显示的信息
HWND hWnd;
hWnd=GetForegroundWindow();
char cBuf[MAX_PATH*100]={0};
LPBYTE pv=NULL;
MEMORY_BASIC_INFORMATION mbi;
while(sizeof(mbi)==VirtualQuery(pv,&mbi,sizeof(mbi)))
{
//定义模块名等信息
char cModName[MAX_PATH];
int nLen;
//如果在页面没有分配
if(mbi.State==MEM_FREE)
mbi.AllocationBase=mbi.BaseAddress;
//出现下面的情况都将nLen置为0
//1.这个页面是自己dll页面;
//2.这个block不是页面的起始;
//3.这个地址为空
if((mbi.AllocationBase==hinstDLL) ||
(mbi.AllocationBase!=mbi.BaseAddress)||
(mbi.AllocationBase==NULL))
nLen=0;
else
nLen=GetModuleFileName((HMODULE)mbi.AllocationBase,cModName,MAX_PATH);
//取得这个基地址所指模块的名字及长度
if(nLen>0)
//注意strchr的使用
sprintf(strchr(cBuf,0),"\n%p-%s",mbi.AllocationBase,cModName);
pv +=mbi.RegionSize;

}

//HWND hWnd;
//hWnd=GetForegroundWindow();
MessageBox(hWnd,cBuf,NULL,NULL);
}

return TRUE;
}

在确定按钮中的代码:

void CInjectDlg::OnBtnInject()
{
// TODO: Add your control notification handler code here
DWORD dwProcessId=::GetDlgItemInt(m_hWnd,IDC_EDIT_ProId,NULL,FALSE);
if(dwProcessId==0)
{
//如果是为0,则注入到自身的进程空间中
dwProcessId=GetCurrentProcessId();
}
char pLibFile[MAX_PATH];
GetModuleFileName(NULL,pLibFile,sizeof(pLibFile));
//注意这里使用的是strrchr,而不是strchr
strcpy(strrchr(pLibFile,'\\')+1,"MyDll.dll");
if(!InjectLib(dwProcessId,pLibFile))
{
MessageBox("注入dll失败!");
return;
}
if(!EjectLib(dwProcessId,pLibFile))
{
MessageBox("清理资源失败!");
return;
}



}

还望各位帮忙!
...全文
214 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
wjling2009 2009-04-28
  • 打赏
  • 举报
回复
终于找到了错误!调用OpenProcess函数是参数错误:PROCESS_CREATE_PROCESS 应为PROCESS_CREATE_THREAD !
wjling2009 2009-04-08
  • 打赏
  • 举报
回复
谢谢了!
wjling2009 2009-04-07
  • 打赏
  • 举报
回复
真的希望有人能读一下,帮助我找出其中的错误!
NineheadedBird 2009-04-07
  • 打赏
  • 举报
回复
仔细读了下 没有发现..
VB拦截Windows Explorer删除进程,内含API HOOK,源代码:倒霉蛋儿,程序有时候也会窗口勾挂失败!   勾住了SHFileOperation等函数,DLL用Delphi写的C会的太少,查了半天才知道原来explorer是用SHFileOperation删除文件,经过测试很稳定,没有出现崩溃的情况,由于只勾住了SHFileOperation函数,所以别的程序要是调用DeleteFile删除文件,拦截不到,要是想拦截DeleteFile自己接着写吧。      mod_Inject.bas类的注释摘录:   Dim MyAddr As Long ‘执行远程线程代码的起始地址。这里等于LoadLibraryA的地址   ‘dll文件路径   MyDllFileLength = LenB(StrConv(MyDllFileName, vbFromUnicode)) + 1    ‘这里把dll文件名从Unicode转换成Ansi,否则英文字母是2个字节。 _   顺便说一下,学过C的应该知道字符串要以/0标志结尾,所以dll文件名长度要加上1个字节存放Chr(0)   ‘得到进程的句柄   在目标进程中申请分配一块空白内存区域。内存的起始地址保存在MyDllFileBuffer中。 _   这块内存区域我们用来存放dll文件路径,并作为参数传递给LoadLibraryA。   在分配出来的内存区域中写入dll路径径。注意第二个参数传递的是MyDllFileBuffer的内容, _   而不是MyDllFileBuffer的内存地址?   If MyReturn = 0 Then Inject = False   MyAddr = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA")   ‘得到LoadLibraryA函数的起始地址。他的参数就是我们刚才写入的dll路径。但是LoadLibraryA本身是不知道参数在哪里的。 _   接下来我们就用CreateRemoteThread函数告诉他参数放在哪里了? If MyAddr = 0 Then Inject = False   MyResult = CreateRemoteThread(ProcessHandle, 0, 0, MyAddr, MyDllFileBuffer, 0, 0)   好了,现在用CreateRemoteThread在目标进程创建一个线程,线程起始地址指向LoadLibraryA, _   参数就是MyDllFileBuffer中保存的dll路径?    If MyResult = 0 Then    Inject = False    Else    Inject = True    End If    ‘接下来你可以使用WaitForSingleObject等待线程执行完毕。 _    并用GetExitCodeThread得到线程的退出代码,用来判断时候正确执行了dll中的代码。    CloseHandle MyResult    CloseHandle ProcessHandle    ‘扫地工作   End Function

15,471

社区成员

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

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