对CreateRemoteThread的使用

本人小白水平,内容中有看不懂的地方请直接在留言中询问,如果代码中有错误或者用法不正确的地方还请立刻指出,本人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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值