远程注入Dll:
Exe部分:
CString GetCurrWorkingDir()
{//获取当前目录
CString strPath;
GetCurrentDirectory(MAX_PATH,strPath.GetBuffer(MAX_PATH));
strPath.ReleaseBuffer();
return strPath;
}
void C进程注入EXEDlg::OnBnClickedButton1()
{//按下按钮执行注入
// TODO: 在此添加控件通知处理程序代码
CString str;
this->m_ProcessName.GetWindowTextW(str);//读取编辑框中输入的目标窗口标题
HWND hStart = ::FindWindow(NULL,str);
DWORD PID, TID;
TID = ::GetWindowThreadProcessId (hStart, &PID);//根据hwnd获取进程ID
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,PID); // 打开目标进程
CString dllname;
this->m_DllName.GetWindowTextW(dllname);//读取编辑框中输入的要注入的Dll的名字(dll在当前目录下)
CString dllpath=GetCurrWorkingDir()+dllname;
USES_CONVERSION;//使用T
2A
之前需要用这一句,否则报错
LPSTR lpszDll=T
2A
(dllpath);
DWORD dwSize, dwWritten;
dwSize = lstrlenA( lpszDll ) + 1;
LPVOID lpBuf = VirtualAllocEx( hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE );
if ( NULL == lpBuf )
{
CloseHandle( hProcess );
// 失败处理
MessageBox(_T("NULL == lpBuf"));
}
if ( WriteProcessMemory( hProcess, lpBuf, (LPVOID)lpszDll, dwSize, &dwWritten ) )
{
// 要写入字节数与实际写入字节数不相等,仍属失败
if ( dwWritten != dwSize )
{
VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
CloseHandle( hProcess );
// 失败处理
MessageBox(_T("要写入字节数与实际写入字节数不相等"));
}
// 使目标进程调用LoadLibrary,加载DLL
DWORD dwID;
//LPVOID pFunc =GetProcAddress(GetModuleHandle (_T("Kernel32")), "LoadLibraryA"); //搞不懂,非要使用LoadLibraryA,使用LoadLibraryW就不能注入
LPVOID pFunc = LoadLibraryA;
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, lpBuf, 0, &dwID );
// 等待LoadLibrary加载完毕
WaitForSingleObject( hThread, INFINITE );
// 释放目标进程中申请的空间
VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
CloseHandle( hThread );
CloseHandle( hProcess );
}
else
{
CloseHandle( hProcess );
// 失败处理
MessageBox(_T("WriteProcessMemory写入失败"));
}
}
Dll部分:
win32 dll中有DllMain,采取的处理:
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
switch ( fdwReason )
{
case DLL_PROCESS_ATTACH:
{
MessageBox( NULL, _T("DLL已进入目标进程。"), _T("信息"), MB_ICONINFORMATION );
}
break;
case DLL_PROCESS_DETACH:
{
MessageBox( NULL, _T("DLL已从目标进程卸载。"), _T("信息"), MB_ICONINFORMATION );
}
break;
default:
break;
}
return TRUE;
}
MFC DLL中无DllMain的处理:
BOOL C进程注入DLL2App::InitInstance()
{//MFC DLL的初始化,相当于处理win32 dll中的DLL_PROCESS_ATTACH
CWinApp::InitInstance();
::AfxMessageBox(_T("DLL注入成功"));
return TRUE;
}
BOOL C进程注入DLL2App::ExitInstance()
{//相当于处理win32 dll中的DLL_PROCESS_DETACH
::AfxMessageBox(_T("退出DLL注入"));
return CWinApp::ExitInstance();
}
====================================================================================
另外以下的做一个备忘,在MFC DLL中要处理DLL_THREAD_ATTACH and DLL_THREAD_DETACH的问题(自己找到MFC DLL的DllMain函数修改):
如果只是简单的资源分配回收可参考如下方法实现
●Initializing Regular DLLs
Because regular DLLs have a CWinApp object, they should perform their initialization and termination tasks in the same location as an MFC application: in the InitInstance and ExitInstance member functions of the DLL's CWinApp-derived class. Because MFC provides a DllMain function that is called by _DllMainCRTStartup for PROCESS_ATTACH and PROCESS_DETACH, you should not write your own DllMain function. The MFC-provided DllMain function calls InitInstance when your DLL is loaded and it calls ExitInstance before the DLL is unloaded.
如果就是想在常规MFC DLL中使用DllMain函数参考以下HOWTO//From MSDN Knowledge Base
HOWTO: How to Provide Your Own DllMain in an MFC Regular DLL
●SUMMARY
By design, MFC Regular DLLs have a default DllMain function provided automatically by MFC. Regular DLLs should not provide their own DllMain. Any initialization which is necessary when the DLL is loaded should be done in the InitInstance member function of the one CWinApp-derived class in the Regular DLL. Deinitialization and termination code should go in the ExitInstance member function.
However, InitInstance is only called by MFC's DllMain when a process attaches (DLL_PROCESS_ATTACH) to the DLL and ExitInstance is called only when a process detaches (DLL_PROCESS_DETACH) from the DLL. If it is necessary to handle thread attachment to and detachment from (DLL_THREAD_ATTACH and DLL_THREAD_DETACH) in MFC Regular DLL, the Regular DLL will need to provide its own DllMain. This article explains how to do it.
●MORE INFORMATION
When a Regular DLL is created, the MFC source forcibly links in the code for the source file /Msdev/Mfc/Src/Dllmodul.cpp. Dllmodul.cpp contains most of the code added to a Regular DLL to support MFC in that DLL. One of the most important functions in Dllmodul.cpp is the DllMain function.
To add code to MFC's DllMain, copy the /Msdev/Mfc/Src/Dllmodul.cpp source file to your project directory, and include the copy in your project. This copy of Dllmodul.cpp will be compiled and linked into your DLL instead of the Dllmodul.cpp in the Mfc/Src directory, so changes to the DllMain in it will show up in the final DLL.
The primary caveat is that this is not a recommended solution and should only be used when absolutely necessary. Any changes to the code in Dllmodul.cpp will undoubtedly have unpredictable results. Add code only, do not remove or modify the existing code.
For regular DLLs that use MFC in the Shared Lib, the module state should be set at the beginning of any added code and restored before returning from DllMain. Refer to the sample code in this article for an example of a DllMain that handles the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications and properly switches the module state as necessary.
Additional care must be taken when relying on DllMain being called with DLL_THREAD_ATTACH and DLL_THREAD_DETACH because of the following conditions:
When a thread is created in a process, the system calls DllMain with a value of DLL_THREAD_ATTACH for each of the DLLs mapped into into the process. However, if a process has several threads running in it when a new DLL is mapped into it, DllMain isn't called with a DLL_THREAD_ATTACH value for any of the existing threads.
DllMain is not called with a value DLL_THREAD_ATTACH for the process's primary thread.
On thread termination (by a call to ExitThread), DllMain is called with a value of DLL_THREAD_DETACH for each of the DLLs. DllMain is not called with DLL_THREAD_DETACH for any thread unless a thread terminates by calling ExitThread.
If a thread terminates due to a call to TerminateThread, DllMain isn't called with a value DLL_THREAD_DETACH.
It is possible for a thread in a process to call LoadLibrary to load a DLL causing a call to DllMain with DLL_PROCESS_ATTACH, and then on thread termination, cause a call to dllMain with DLL_THREAD_DETACH without ever calling DLL_THREAD_ATTACH. It is therefore best that the thread that calls LoadLibrary also call FreeLibrary.
NOTE: MFC CWnd objects, CDC objects, CMenu objects, GDI objects, and CImageList objects are restricted to a per-thread, per-module basis. In other words, MFC objects created in one module or thread cannot be passed to and/or used in a different module or thread. This has special relevance for any code added to handle DLL_THREAD_ATTACH or DLL_THREAD_DETACH in DllMain because DllMain is called for these reasons with different threads. CWnd objects, for instance, created in DllMain during DLL_PROCESS_ATTACH or in InitInstance will not be valid during DLL_THREAD_ATTACH.
在Dll中显示对话框、在dll中处理消息(疑惑中):
将dll注入后,要显示一个对话框(无模式对话框)
BOOL C进程注入DLL2App::InitInstance()
{
CWinApp::InitInstance();
::AfxMessageBox(_T("DLL注入成功"));
//在dll类的头文件中定义了CDllDialog *pDllDialog;
//新建一个线程用于创建窗口,直接在这里创建的话在对话框处理消息循环时这里将一直处于阻塞而不能继续执行
::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)CreateDialogBox,(LPVOID)pDllDialog,NULL,NULL);
return TRUE;
}
BOOL C进程注入DLL2App::ExitInstance()
{
::AfxMessageBox(_T("退出DLL注入"));
pDllDialog->DestroyWindow();/*运行是提示错误说pDllDialog指向NULL,不能操作,还没对pDllDialog做其它任何处理,这里确指向NULL了,不明!如果将pDllDialog定义为static的话则出现错误:“错误 1 error LNK2001: 无法解析的外部符号 "public: static class CDllDialog * C进程注入DLL2App::pDllDialog" (?pDllDialog@C进程注入DLL2App@@2PAVCDllDialog@@A) 进程注入DLL2.obj ”*/
delete pDllDialog;
return CWinApp::ExitInstance();
}
void CreateDialogBox(CDllDialog *pDllDialog)
{
pDllDialog=new CDllDialog;
pDllDialog->Create((UINT)IDD_DLL_DIALOG);//,pwnd);//据说要加上第二个参数设置父窗口,可是试验后没任何不同
pDllDialog->ShowWindow(SW_SHOW);
::AfxMessageBox(_T("窗口出来了"));/*弹出MessageBox时确实看到要创建的对话框已经创建显示出来了,但是一旦按下确定关闭这个MessageBox后刚创建的对话框也跟着消失了,不明!如果没这一句甚至根本看不到对话框的出现,因为刚出现就消失了。为了解决这个问题,在对话框中添加消息循环*/
}
BOOL CDllDialog::OnInitDialog()
{
CDialog::OnInitDialog();
this->ShowWindow(SW_SHOW);
this->UpdateWindow();
MSG msg;
while(::GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg); //消息进行必要的处理转换。
DispatchMessage(&msg); /*调用WinProc,将msg的各项信息传递给WinProc【问题:写好了LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam),但是在WinProc中就是接收不到任何的消息,不明!】*/
}/**/
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
如果是在win32 dll中则创建线程使用
CreateDialogW(hinstDLL,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc);//创建无模式对话框
然后在对话框处理函数DialogProc中进行消息循环。
不论是在MFC DLL还是Win32 DLL中,做了消息循环后如果是使用
TranslateMessage(&msg); //消息进行必要的处理转换。
DispatchMessage(&msg); //调用WinProc,将msg的各项信息传递给WinProc
则接收不到任何消息,如果是在BOOL CDllDialog::OnInitDialog()或DialogProc中做消息判断并处理则对话框中的控件(如“确定”“取消”按钮)将失去响应。