本人小白水平,内容中有看不懂的地方请直接在留言中询问,如果代码中有错误或者用法不正确的地方还请立刻指出,本人QQ号 : 3216393922
对于 CreateRemoteThread,比较简单的用法是用LoadLibrary在目标进程中注入dll,也可以在远程线程中注入代码,并将它运行,不过,有一下几个注意点:
1、如何在远程线程中调用字符串?
所有的字符串必须在目标进程的地址空间中,所以我在目标进程内开辟了两个空间,一个用来存放代码,一个用来存放数据。将数据打包成结构体REMOTE_DATA,一次性运到目标进程中去,再将该结构体数据在目标进程中的地址作为线程函数的参数,这样就可以在线程函数中调用结构体中的字符串数据。
2、如何在远程线程中任意调用系统函数?
为了在远程线程中可以调用任何想调用的函数,必须拥有LoadLibraryW和GetProcAddress这两个函数,调用某一个函数时,先用LoadLibraryW得到函数所在的dll模块句柄,再用GetProcAddress得到函数地址。
例如:想要在远程线程函数内调用MessageBoxW函数,它在User32.dll中
先在数据结构体中定义函数名和dll名
CHAR szMessageBoxW[20] = “MessageBoxW”;
WCHAR szUser32[20] = TEXT(“user32.dll”);
再在远程线程函数中得到dll模块句柄
HMODULE hUser32 = LOADLIBRARYW(myData->szUser32);
然后申明MessageBoxW函数
typedef int(WINAPI* Func1)(HWND hwnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);
Func1 MESSAGEBOXW = (Func1)GETPROCADDRESS(hUser32, myData->szMessageBoxW);
最后调用MessageBoxW函数
MESSAGEBOXW(NULL, myData->szText, myData->szCaption, MB_OK);
3、如何得到函数代码在内存中的大小?
#pragma check_stack(off)
void test()
{
//你的代码
}
void AfterFunc()
{
return;
}
#pragma check_stack
调用SIZE_T cbSize = ((BYTE )(DWORD)AfterFunc - (BYTE )(DWORD)RemoteThreadFunc) + 10就可以得到函数test()的大小,该方法在Debug下无法使用,在Release中才可以使用。
目标是在进程PEView.exe中创建一个线程,线程中创建一个MessageBoxW
下面是代码:
#include <Windows.h>
#include <TlHelp32.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <stdio.h>
#include <tchar.h>
#include <Psapi.h>
using namespace std;
//1.定义进程名称
const wstring& wsProcessName = TEXT("PEView.exe");
//2.定义远程线程中使用的数据
typedef struct
{
WCHAR szCaption[50] = TEXT("123");
WCHAR szText[50] = TEXT("456");
//2.1需要使用的dll
WCHAR szKernel32[20] = TEXT("kernel32.dll");
WCHAR szUser32[20] = TEXT("user32.dll");
WCHAR szGdi32[20] = TEXT("gdi32.dll");
//2.2需要使用的函数
CHAR szMessageBoxW[20] = "MessageBoxW";
CHAR szLoadCursorW[20] = "LoadCursorW";
CHAR szSetCursor[20] = "SetCursor";
CHAR szSleep[20] = "Sleep";
//2.3两个函数LoadLibraryW和GetProcAddressW的地址
DWORD dwLoadLibraryW = 0;
DWORD dwGetProcAddress = 0;
}REMOTE_DATA, *PREMOTE_DATA;
REMOTE_DATA remoteData;
//3.定义远程线程的函数
#pragma check_stack(off)
DWORD __stdcall RemoteThreadFunc(PREMOTE_DATA myData)
{
//LoadLibraryW-->LOADLIBRARYW
typedef HMODULE(WINAPI* LoadLibraryWFunc)(
LPCWSTR lpFileName
);
LoadLibraryWFunc LOADLIBRARYW = (LoadLibraryWFunc)myData->dwLoadLibraryW;
//GetProcAddress-->GETPROCADDRESS
typedef FARPROC(WINAPI* GetProcAddressFunc)(
HMODULE hModule,
LPCSTR lpProcName
);
GetProcAddressFunc GETPROCADDRESS = (GetProcAddressFunc)myData->dwGetProcAddress;
//加载hUser32.dll并得到其句柄
HMODULE hKernel32 = LOADLIBRARYW(myData->szKernel32);
HMODULE hUser32 = LOADLIBRARYW(myData->szUser32);
HMODULE hGdi32 = LOADLIBRARYW(myData->szGdi32);
//调用MessageBoxW
typedef int(WINAPI* Func1)(
HWND hwnd,
LPCWSTR lpText,
LPCWSTR lpCaption,
UINT uType
);
Func1 MESSAGEBOXW = (Func1)GETPROCADDRESS(hUser32, myData->szMessageBoxW);
MESSAGEBOXW(NULL, myData->szText, myData->szCaption, MB_OK);
return 0;
}
void AfterFunc()
{
return;
}
#pragma check_stack
BOOL AdjustProcessTokenPrivilege()
{
LUID luidTmp;
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
return FALSE;
}
if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidTmp))
{
::CloseHandle(hToken);
return FALSE;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luidTmp;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!::AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))
{
::CloseHandle(hToken);
return FALSE;
}
return TRUE;
}
BOOL Camp2str(wstring wsStrA, wstring wsStrB)
{
int nSize = wsStrA.length();
for (int i = 0; i < nSize; ++i)
{
if (wsStrA[i] >= 'A'&&wsStrA[i] <= 'Z')
wsStrA[i] += 'a' - 'A';
}
nSize = wsStrB.length();
for (int i = 0; i < nSize; ++i)
{
if (wsStrB[i] >= 'A'&&wsStrB[i] <= 'Z')
wsStrB[i] += 'a' - 'A';
}
return wsStrA == wsStrB;
}
DWORD GetProcessIdByName(const wstring& wsProcessName)
{
HANDLE hProcess = 0;
DWORD dwProcess[2048], dwNeeded;
TCHAR tcProcName[MAX_PATH] = { 0 };
wstring wsNowProcessName = L"";
int nTempSize = 0;
int nPos = 0;
//将所有进程的ID保存在数组dwProcess中,共dwNeeded个进程
EnumProcesses(dwProcess, sizeof(dwProcess), &dwNeeded);
//用ID打开每一个进程
for (int i = 0; i < (dwNeeded / sizeof(DWORD)); ++i)
{
if (dwProcess[i] != 0)
{
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcess[i]);
GetModuleFileNameEx(hProcess, NULL, tcProcName, MAX_PATH);
nPos = wstring(tcProcName).find_last_of(L'\\');
if (nPos != wstring::npos)
{
wsNowProcessName = wstring(wstring(tcProcName).substr(nPos + 1));
if (Camp2str(wsProcessName, wsNowProcessName))
{
DWORD aa = dwProcess[i];
return aa;
}
}
}
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
//1.提权
if (!AdjustProcessTokenPrivilege())
{
MessageBox(NULL, TEXT("无法提升权限"), TEXT("Fail"), MB_ICONERROR);
return -1;
}
DWORD dwProID = 0;
HANDLE hProcess = NULL;
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
HANDLE hThread = NULL;
void* pRemoteData = NULL;
void* pRemoteThread = NULL;
__try
{
//2.获取进程ID dwProPID
if ((dwProID = GetProcessIdByName(wsProcessName)) == 0)
{
MessageBox(NULL, TEXT("无法由进程名找到进程"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//3.打开进程句柄hProcess
if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProID)) == NULL)
{
MessageBox(NULL, TEXT("无法打开进程"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//4.在宿主进程中找到LoadLibraryW函数和GetProcAddressW函数的地址
//并分别赋给remoteData.dwLoadLibraryW和remoteData.dwGetProcAddress
MODULEENTRY32W me32 = { sizeof(MODULEENTRY32W) };
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProID);
if (hModuleSnap == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, TEXT("无法获取模块快照"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
if (!Module32FirstW(hModuleSnap, &me32))
{
MessageBox(NULL, TEXT("无法获取模块快照"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
do
{
//找到目标进程中的Kernel32.dll
if (lstrcmpiW(me32.szModule, TEXT("Kernel32.dll"))==0)
{
//获得本地hKernel32.dll或LoadLibraryW或GetProcAddress的地址
HANDLE hKernel32 = GetModuleHandleW(TEXT("Kernel32.dll"));
DWORD loadlibraryw = (DWORD)GetProcAddress((HMODULE)hKernel32, (LPCSTR)"LoadLibraryW");
DWORD getprocaddress = (DWORD)GetProcAddress((HMODULE)hKernel32, (LPCSTR)"GetProcAddress");
if (hKernel32 == NULL || loadlibraryw == 0 || getprocaddress == 0)
{
MessageBox(NULL, TEXT("无法获得本地hKernel32.dll或LoadLibraryW或GetProcAddress的地址"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//获得目标进程hKernel32.dll或LoadLibraryW或GetProcAddress的地址
remoteData.dwLoadLibraryW = loadlibraryw - (DWORD)hKernel32 + (DWORD)me32.hModule;
remoteData.dwGetProcAddress = getprocaddress - (DWORD)hKernel32 + (DWORD)me32.hModule;
break;
}
} while (Module32NextW(hModuleSnap, &me32));
CloseHandle(hModuleSnap);
hModuleSnap = INVALID_HANDLE_VALUE;
if (remoteData.dwLoadLibraryW == 0 || remoteData.dwGetProcAddress == 0)
{
MessageBox(NULL, TEXT("未能在目标进程中找到kernel32.dll"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//5.1在宿主进程里分配内存,用于存参数remoteData
pRemoteData = VirtualAllocEx(hProcess, NULL, sizeof(remoteData), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pRemoteData == NULL)
{
MessageBox(NULL, TEXT("无法在宿主进程中分配内存"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//5.2把remoteData写入到目标进程的内存pRemoteData中去
if (!WriteProcessMemory(hProcess, pRemoteData, &remoteData, sizeof(remoteData), NULL))
{
MessageBox(NULL, TEXT("无法将数据remoteData写入宿主进程中"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//6.1在宿主进程里分配内存,用于写线程函数RemoteThreadFunc
SIZE_T cbSize = ((BYTE *)(DWORD)AfterFunc - (BYTE *)(DWORD)RemoteThreadFunc) + 10;
if (cbSize <= 0)
{
cbSize = 2048;
}
pRemoteThread = VirtualAllocEx(hProcess, NULL, cbSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pRemoteThread == NULL)
{
MessageBox(NULL, TEXT("无法在宿主进程中分配内存"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//6.2.把RemoteThread指向的函数写入到目标进程的内存pRemoteThread中去
if (!WriteProcessMemory(hProcess, pRemoteThread, &RemoteThreadFunc, cbSize, NULL))
{
MessageBox(NULL, TEXT("无法将线程函数RemoteThread写入宿主进程中"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//7.启动注入宿主进程的线程
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, pRemoteData, 0, NULL);
if (!hThread)
{
MessageBox(NULL, TEXT("无法在宿主进程中创建远程线程"), TEXT("Fail"), MB_ICONERROR);
__leave;
}
//8.等待线程结束,然后清理内存
WaitForSingleObject(hThread, INFINITE);
}
__finally
{
if (hProcess != NULL)
{
CloseHandle(hProcess);
}
if (hModuleSnap != INVALID_HANDLE_VALUE)
{
CloseHandle(hModuleSnap);
}
if (hThread != NULL)
{
CloseHandle(hThread);
}
if (pRemoteThread != NULL)
{
VirtualFreeEx(hProcess, pRemoteThread, 0, MEM_RELEASE);
}
if (pRemoteData != NULL)
{
VirtualFreeEx(hProcess, pRemoteData, 0, MEM_RELEASE);
}
}
return 0;
}