利用NtCreateThreadEx注入

#include "x64Inject.h"


HANDLE WINAPI ThreadProc(PTHREAD_DATA data)
{
    data->fnRtlInitUnicodeString(&data->UnicodeString,data->DllName);
    data->fnLdrLoadDll(data->DllPath,data->Flags,&data->UnicodeString,&data->ModuleHandle);
    return data->ModuleHandle;
}

DWORD WINAPI ThreadProcEnd()
{
    MyOutputDebugStringA("ThreadProcEnd");
    return 0;
}


Cx64Inject::Cx64Inject(void)
{
}


Cx64Inject::~Cx64Inject(void)
{
}

//操作系统版本判断
BOOL Cx64Inject::IsVistaOrLater()
{
    OSVERSIONINFO osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&osvi);
    if( osvi.dwMajorVersion >= 6 )
        return TRUE;
    return FALSE;
}

BOOL Cx64Inject::EnableDebugPrivilege()
{
    HANDLE hToken;   
    TOKEN_PRIVILEGES tkp;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))   
        return( FALSE );
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
    tkp.PrivilegeCount = 1;   
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
    if (GetLastError() != ERROR_SUCCESS)   
        return FALSE;   

    return TRUE; 
}


//OD跟踪,发现最后调用的是NtCreateThreadEx,所以这里手动调用
HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
{
    HANDLE hThread = NULL;
    FARPROC pFunc = NULL;
    if( IsVistaOrLater())// Vista, 7, Server2008
    {
        pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
        if( pFunc == NULL )
        {
            MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress("NtCreateThreadEx") 调用失败!错误代码: [%d]", GetLastError());
            return NULL;
        }
        ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);
        if( hThread == NULL )
        {
            MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 调用失败!错误代码: [%d]", GetLastError());
            return NULL;
        }
    }
    else// 2000, XP, Server2003
    {
        hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
        if( hThread == NULL )
        {
            MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 调用失败!错误代码: [%d]", GetLastError());
            return NULL;
        }
    }
    if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
    {
        MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 调用失败!错误代码: [%d]", GetLastError());
        return NULL;
    }
    return hThread;
}

//在目标进程中创建线程并注入dll
BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)
{
    dwProcessId = 648;
    lpcwDllPath = L"C:\MessageBox64.dll";
    BOOL bRet = FALSE;
    HANDLE hProcess = NULL, hThread = NULL;
    LPVOID pCode = NULL;
    LPVOID pThreadData = NULL;
    __try
    {
        if(!EnableDebugPrivilege())
        {
            MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 调用失败!错误代码: [%d]", GetLastError());
            return -1;
        }
        //打开目标进程;
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);
        DWORD dwError = GetLastError();
        if (hProcess == NULL)
            __leave;
        //申请空间,把我们的代码和数据写入目标进程空间里;
        //写入数据;
        THREAD_DATA data;
        HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
        data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");
        data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");
        memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));
        data.DllPath = NULL;
        data.Flags = 0;
        data.ModuleHandle = INVALID_HANDLE_VALUE;
        pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        if (pThreadData == NULL)
            __leave;
        BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);
        if (!bWriteOK)
            __leave;
        MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);
        //写入代码;
        DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;
        pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (pCode == NULL)
        {
            MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 调用失败!错误代码: [%d]", GetLastError());
            __leave;
        }        
        bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);
        if (!bWriteOK)
            __leave;
        MyOutputDebugStringA("pCode = 0x%p", pCode);
        //创建远程线程,把ThreadProc作为线程起始函数,pThreadData作为参数;
        hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);
        if (hThread == NULL)
            __leave;
        //等待完成;
        WaitForSingleObject(hThread, INFINITE);
        bRet = TRUE;
    }
    __finally
    {
        if (pThreadData != NULL)
            VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);
        if (pCode != NULL)
            VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
        if (hThread != NULL)
            CloseHandle(hThread);
        if (hProcess != NULL)
            CloseHandle(hProcess);
    }

    return bRet;
}
#pragma once
#include <windows.h>
#include "MyOutputDebugString.h"
//Native DLL L"C:\Windows\System32\sfc.dll";

typedef struct _LSA_UNICODE_STRING{
    USHORT Length;
    USHORT MaximumLength;
    PWSTR Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;

typedef NTSTATUS (NTAPI *pRtlInitUnicodeString)(PUNICODE_STRING,PCWSTR);
typedef NTSTATUS (NTAPI *pLdrLoadDll)(PWCHAR,ULONG,PUNICODE_STRING,PHANDLE);

typedef struct _THREAD_DATA
{
    pRtlInitUnicodeString fnRtlInitUnicodeString;
    pLdrLoadDll fnLdrLoadDll;
    UNICODE_STRING UnicodeString;
    WCHAR DllName[260];
    PWCHAR DllPath;
    ULONG Flags;
    HANDLE ModuleHandle;
}THREAD_DATA,*PTHREAD_DATA;

typedef VOID (WINAPI *fRtlInitUnicodeString)(PUNICODE_STRING DestinationString,PCWSTR ourceString);

typedef NTSTATUS (WINAPI *fLdrLoadDll)(IN PWCHAR PathToFile OPTIONAL, IN ULONG Flags OPTIONAL, IN PUNICODE_STRING  ModuleFileName, OUT PHANDLE ModuleHandle);

typedef DWORD64 (WINAPI *_NtCreateThreadEx64)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD64 dwStackSize, DWORD64 dw1, DWORD64 dw2, LPVOID Unknown);

class Cx64Inject
{
public:
    Cx64Inject(void);
    ~Cx64Inject(void);
    BOOL InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath);
private:
    BOOL EnableDebugPrivilege();
    BOOL IsVistaOrLater();
    HANDLE MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf);
};
//MyOutputDebugString.h 
#pragma once
#define MYPRINT
//MyOutputDebugString(_T("%d,%s"),123,_T("hello"));

#ifdef _UNICODE
#define MyOutputDebugString MyOutputDebugStringW
#else
#define MyOutputDebugString MyOutputDebugStringA
#endif


//MyOutputDebugStringA("%d,%s",123,"hello");
void MyOutputDebugStringA(const char * szOutputString,...);

//MyOutputDebugStringW(L"%d,%s",456,L"world!");
void MyOutputDebugStringW(const wchar_t * szOutputString,...);
//MyOutputDebugString.cpp 
#include "stdafx.h"
#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>

#pragma warning(disable:4996)

#define MYPRINT

//MyOutputDebugStringA("%d,%s",123,"hello");
void MyOutputDebugStringA(const char * szOutputString,...)
{
#ifdef MYPRINT
    char szBuffer[4096]={0};
    va_list vlArgs;
    va_start(vlArgs,szOutputString);
    _vsnprintf(szBuffer,sizeof(szBuffer)-1,szOutputString,vlArgs);
    //vsprintf(szBuffer,szOutputString,vlArgs);
    va_end(vlArgs);
    char szPrint[4096 + 100]={0};
    char *szFilter = "[sunflover] ";
    strcpy(szPrint,szFilter);
    strcat(szPrint,szBuffer);
    OutputDebugStringA(szPrint);
#endif
}

//MyOutputDebugStringW(L"%d,%s",456,L"world!");
void MyOutputDebugStringW(const wchar_t * szOutputString,...)
{
#ifdef MYPRINT
    wchar_t szBuffer[4096]={0};
    va_list vlArgs;
    va_start(vlArgs,szOutputString);
    _vsnwprintf(szBuffer,sizeof(szBuffer)-2,szOutputString,vlArgs);
    //vswprintf(szBuffer,szOutputString,vlArgs);
    va_end(vlArgs);
    wchar_t szPrint[4096 + 100]={0};
    wchar_t *szFilter = L"[sunflover] ";
    wcscpy(szPrint,szFilter);
    wcscat(szPrint,szBuffer);
    OutputDebugStringW(szPrint);
#endif
}
原文地址:https://www.cnblogs.com/yifi/p/6527760.html