阿杰 发表于 2010-1-27 20:49:40

最简单的 远程线程实现自定义Dll注入


首先做一个Dll,名字叫DllInsert.dll,我们在DllMain中的DLL_PROCESS_ATTACH分支写一个::MessageBox(NULL, "You are Load dll now!", "Load", NULL); 在DLL_PROCESS_DETACH中写一个::MessageBox(NULL, "You are Free dll now!", "Free", NULL); ok Dll写完了,把这个Dll放到System32目录中
下面来注入他到Explorer.exe进程,注意:Debug版本会崩溃,Release版本没问题的,原因不白
#include "Tlhelp32.h."
#include "Psapi.h."
//提升权限
BOOL ImproveProcPriv()
{
HANDLE token;
//提升权限
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&token))
{
   // MessageBox(NULL,"打开进程令牌失败...","错误",MB_ICONSTOP);
   return FALSE;
}
TOKEN_PRIVILEGES tkp;
tkp.PrivilegeCount = 1;
::LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges.Luid);
tkp.Privileges.Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(token,FALSE,&tkp,sizeof(tkp),NULL,NULL))
{
   // MessageBox(NULL,"调整令牌权限失败...","错误",MB_ICONSTOP);
   return FALSE;
}
CloseHandle(token);
return TRUE;
}
//这个函数名字取反了,- -! 尴尬
DWORD GetProcNameByPID(char *strName)
{
    HANDLE          hprocessSnap = NULL;
    PROCESSENTRY32 pe32;
memset(&pe32, 0, sizeof(PROCESSENTRY32));
    hprocessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//创建进程快照
// 如果创建快照失败就返回1;
    if (hprocessSnap == INVALID_HANDLE_VALUE)
{
   printf("\nCreateToolhelp32Snapshot()failed:%d",GetLastError());
   return 0;
    }
    pe32.dwSize = sizeof(PROCESSENTRY32);   //初始化pe32的dwsize值
//遍历快照
    if (Process32First(hprocessSnap,&pe32))
{   
   do
   {   
    //如果name(要查找的进程的名字)等于pe32.szExeFile(本进程的名字),就返pe32.the32ProcessID          (进程ID)
    if (!stricmp(strName, pe32.szExeFile))
    {
   return (DWORD)pe32.th32ProcessID;
    }
   }while (Process32Next(hprocessSnap,&pe32));
    }
//如果没找到就返回0
    CloseHandle (hprocessSnap);
    return 0;
}
// ========== 定义一个代码结构,本例为一个对话框============
//类似的可以调用Dll里面是函数,只是要把函数名字作为参数传进来
struct MyData
{
char sz; // 对话框显示内容
DWORD dwLoadLibrary; // LoadLibrary的地址
DWORD dwFreeLibrary;
};

// ========== 远程线程的函数 ==============================
DWORD __stdcall RMTFunc(MyData *pData)
{
typedef HMODULE(__stdcall *MLoadLibrary)(LPCTSTR);
typedef void (__stdcall *MFreeLibrary)(HMODULE);
MLoadLibrary Mloaddll = (MLoadLibrary )(pData->dwLoadLibrary);
MFreeLibrary Mfreedll = (MFreeLibrary )(pData->dwFreeLibrary);
   HMODULE hDll = Mloaddll(pData->sz);
Mfreedll(hDll);
return 0;
}
void CInsertExplorerDlg::OnOK()
{
ImproveProcPriv();
DWORD dwIDExplorer = GetProcNameByPID("Explorer.exe");
if (dwIDExplorer == 0)
{
   ::MessageBox(m_hWnd, "Get Pro ID Error!", NULL, NULL);
}
HANDLE hProcess = OpenProcess(
   PROCESS_ALL_ACCESS,
   FALSE,
   dwIDExplorer);
if (hProcess == NULL)
{
   ::MessageBox(m_hWnd, "Open Process Error!", NULL, NULL);
   return ;
}
// ========= 代码结构 ================================================
MyData data;
ZeroMemory(&data, sizeof (MyData));
strcpy(data.sz, "DllInsert.dll");
HINSTANCE hUser = LoadLibrary("kernel32.dll");
if (! hUser)
{
   printf("Can not load library.\n");
   return ;
}
data.dwLoadLibrary = (DWORD)GetProcAddress(hUser, "LoadLibraryA");
data.dwFreeLibrary = (DWORD)GetProcAddress(hUser, "FreeLibrary");
FreeLibrary(hUser);
if (! data.dwLoadLibrary)
   return ;

// ======= 分配空间 ===================================================
void *pRemoteThread
   = VirtualAllocEx(hProcess, 0,
   1024*4, MEM_COMMIT|MEM_RESERVE,
   PAGE_EXECUTE_READWRITE);
if (! pRemoteThread)
   return ;
if (! WriteProcessMemory(hProcess, pRemoteThread, &RMTFunc, 1024*4, 0))
   return ;
MyData *pData
   = (MyData*)VirtualAllocEx(hProcess, 0,
   sizeof (MyData), MEM_COMMIT,
   PAGE_READWRITE);
if (!pData)
   return ;

if (! WriteProcessMemory(hProcess, pData, &data, sizeof (MyData), 0))
   return ;

// =========== 创建远程线程 ===========================================
HANDLE hThread
   = CreateRemoteThread(hProcess, 0,
   0, (LPTHREAD_START_ROUTINE)pRemoteThread,
   pData, 0, 0);
if (! hThread)
{
   printf("远程线程创建失败");
   return ;
}
CloseHandle(hThread);//这个CloseHandle是不会关掉远程线程的,TerminateThread能关掉
VirtualFreeEx(hProcess, pRemoteThread, 1024*4, MEM_RELEASE);
VirtualFreeEx(hProcess, pData, sizeof (MyData), MEM_RELEASE);
CloseHandle(hProcess);
return ;
}

前面说的那个为什么会崩溃,查了一下原因:
原因是Debug模式下编译器会自动在代码中插入esp的check routine.它可以使Remote Thread崩溃.   
在DEBUG模式下常有这一句:
0043E604 call @ILT+4380(__RTC_CheckEsp) (42E121h)

CreateRemoteThread中莫名其妙的崩溃常由它导致.由于没有你所有的代码,所以只是推测,没有办法详细了.
一般来说这是由于在Debug模式下,编译会在每个函数执行后自动加入
恢复stockheap地址等相关指令,也就是说,它会调用自动恢复stockheap地址函数。
而这个函数在远程地址空间中是不存在的,所以执行时会出错,
如在Release模式下,编译器就不会插入这个指令,所以执行没有问题。

其实这个问题跟远程执行插入你自己的代码也是一样的,都需要在release下面才能
执行成功。
页: [1]
查看完整版本: 最简单的 远程线程实现自定义Dll注入