对CreateRemoteThread的使用

来源:互联网 发布:淘宝商城包包大全 编辑:程序博客网 时间:2024/05/16 13:48

本人小白水平,内容中有看不懂的地方请直接在留言中询问,如果代码中有错误或者用法不正确的地方还请立刻指出,本人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_stackBOOL 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;}
原创粉丝点击