首先,通过获得目标进程Id,再根据与进程Id获得目标进程的主线程Id,将主线程Id挂起,获得该线程的背景上下文,将该线程的Eip改为自己的ShellCode,最后恢复线程。
重要的函数顺序为:
OpenThread-->SuspendThread-->GetThreadContext-->获取EIP-->修改EIP-->SetThreadContext-->ResumeThread
#include <windows.h>
#include <iostream>
#include <Winternl.h>
using namespace std;
//提权
typedef LONG KPRIORITY;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
namespace HOOK
{
typedef struct _SYSTEM_THREAD_INFORMATION
{
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
LONG BasePriority;
ULONG ContextSwitches;
ULONG ThreadState;
ULONG WaitReason;
ULONG PadPadAlignment;
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
typedef struct _SYSTEM_PROCESS_INFORMATION
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER WorkingSetPrivateSize;
ULONG HardFaultCount;
ULONG NumberOfThreadsHighWatermark;
ULONGLONG CycleTime;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
HANDLE InheritedFromUniqueProcessId;
ULONG HandleCount;
ULONG SessionId;
ULONG_PTR UniqueProcessKey;
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER ReadOperationCount;
LARGE_INTEGER WriteOperationCount;
LARGE_INTEGER OtherOperationCount;
LARGE_INTEGER ReadTransferCount;
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
SYSTEM_THREAD_INFORMATION Threads[1];
}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
}
typedef decltype(&NtQueryInformationProcess) LPFN_NTQUERYINFORMATIONPROCESS;
typedef HMODULE (WINAPI *LPFN_LOADLIBRARYW) (LPCWSTR lpwLibFileName);
typedef
NTSTATUS(NTAPI *LPFN_NTQUERYSYSTEMINFORMATION)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);
BOOL SeEnableSeDebugPrivilege(IN const WCHAR* PriviledgeName, BOOL IsEnable);
BOOL SeGetPebByProcessID(IN UINT32 ProcessID, OUT PPEB Peb);
BOOL SeGetFunctionAddressInTargetProcessImportTableByFunctionName(IN UINT32 ProcessID,
OUT PVOID* ImportFunctionAddress, IN char* ModuleName,
IN char* FunctionName);
BOOL GetMainThreadIDByProcessID(IN UINT32 ProcessID, OUT PUINT32 MainThreadID);
BOOL SeHookIP(IN UINT32 ProcessID, IN UINT32 MainThreadID);
WCHAR __DllFullPath[MAX_PATH] = { 0 };
LPFN_NTQUERYINFORMATIONPROCESS __NtQueryInformationProcess = NULL;
LPFN_LOADLIBRARYW __LoadLibraryW = NULL;
LPFN_NTQUERYSYSTEMINFORMATION __NtQuerySystemInformation = NULL;
#ifdef _WIN64
UINT8 __ShellCode[0x100] = {
0x48,0x83,0xEC,0x28, // sub rsp ,28h
0x48,0x8D,0x0d, // [+4] lea rcx,
0x00,0x00,0x00,0x00, // [+7] DllFullPathOffset = [+43] - [+4] - 7
// call 跳偏移,到地址,解*号
0xff,0x15, // [+11]
0x00,0x00,0x00,0x00, // [+13] LoadLibraryAddressOffset
0x48,0x83,0xc4,0x28, // [+17] add rsp,28h
// jmp 跳偏移&