Skip to content

Instantly share code, notes, and snippets.

@dgellow
Last active April 9, 2021 19:42
Show Gist options
  • Save dgellow/e9a3f22786d6a481985651716ccb5f58 to your computer and use it in GitHub Desktop.
Save dgellow/e9a3f22786d6a481985651716ccb5f58 to your computer and use it in GitHub Desktop.
#include "main.h"
#include <windows.h>
#include <stdio.h>
#include "RemoteThread.h"
#include "ProcessInfo.h"
#include "Hidden.h"
/* Hidden contains things like:
// ReadProcessMemory
case STR_READPROCESSMEMORY:
len = 17;
pad1 = "\x25\x8a\xeb\x75\xd8\xaa\x7d\xd8\x17\xc8\x26\x9d\x7e\xfe\x2a\xf1\xea";
pad2 = "\x77\xef\x8a\x11\x88\xd8\x12\xbb\x72\xbb\x55\xd0\x1b\x93\x45\x83\x93";
for (i = 0; i < len; i ++)
buffer[i] = (char)(((unsigned char)pad1[i]) ^ ((unsigned char)pad2[i]));
buffer[len] = 0;
// This is because some _very_ stupid virus scanners see "ReadProcessMemory" and freak out
// yet they don't see into the world's most trivial obfuscation.
// It also has a layer to generate the HIDE* macros used here, and a build step that probably
// goes way too far and hides all the strings this way.
*/
const DWORD MAXINJECTSIZE = 4096;
typedef HMODULE (__stdcall *PLoadLibraryW)(wchar_t*);
typedef HMODULE (__stdcall *PGetModuleHandleW)(wchar_t*);
typedef BOOL (__stdcall *PFreeLibrary)(HMODULE);
typedef FARPROC (__stdcall *PGetProcAddress)(HMODULE, char*);
typedef BOOL (__stdcall *PSetCurrentDirectory)(wchar_t*);
typedef DWORD (__stdcall *PGetCurrentDirectory)(DWORD, wchar_t*);
typedef BOOL (__stdcall *PSetEnvironmentVariable)(wchar_t*,wchar_t*);
struct RemoteThreadBlock
{
PSetCurrentDirectory fnSetCurrentDirectory;
PGetCurrentDirectory fnGetCurrentDirectory;
PGetProcAddress fnGetProcAddress;
PSetEnvironmentVariable fnSetEnvironmentVariable;
wchar_t szDirectoryPath[512];
wchar_t szFullPath[512];
wchar_t szOldPath[512];
wchar_t szDriveName[5];
DWORD dwReturn;
};
#define ERROR_UNABLE_TO_GET_CURRENT_DIR 1
#define ERROR_UNABLE_TO_SET_CURRENT_DIR 2
#define ERROR_NETWORK_PATH_SPECIFIED 3
#define ERROR_UNABLE_TO_SET_ENVIORNMENT 4
void EnableDebugPriv(void);
bool ExecuteRemoteThread(HANDLE, wchar_t*);
DWORD LoadDllForRemoteThread(DWORD, wchar_t*);
BOOL IsWindowsNT();
DWORD __stdcall RemoteThread(RemoteThreadBlock*);
extern bool g_bIsCMD = false;
/* -------------------------------------------------------------------- */
/* ----------- Local APIs --------------------------------------------- */
/* -------------------------------------------------------------------- */
HMODULE Local_Kernel32()
{
static HMODULE ret = NULL;
if (!ret)
{
ret = LoadLibraryW(HIDEW_KERNEL32);
}
return ret;
}
HMODULE Local_Advapi32()
{
static HMODULE ret = NULL;
if (!ret)
{
ret = LoadLibraryW(HIDEW_ADVAPI32);
}
return ret;
}
HANDLE Local_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_OPENPROCESS);
}
if (ret)
{
typedef HANDLE (WINAPI * PFN_Func)(DWORD, BOOL, DWORD);
return ((PFN_Func) ret)(dwDesiredAccess, bInheritHandle, dwProcessId);
}
}
return NULL;
}
HANDLE Local_GetCurrentProcess()
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_GETCURRENTPROCESS);
}
if (ret)
{
typedef HANDLE (WINAPI * PFN_Func)();
return ((PFN_Func) ret)();
}
}
return NULL;
}
BOOL Local_CloseHandle(HANDLE hObject)
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_CLOSEHANDLE);
}
if (ret)
{
typedef BOOL (WINAPI * PFN_Func)(HANDLE);
return ((PFN_Func) ret)(hObject);
}
}
return FALSE;
}
BOOL Local_OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
{
if (Local_Advapi32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Advapi32(), HIDEA_OPENPROCESSTOKEN);
}
if (ret)
{
typedef BOOL (WINAPI * PFN_Func)(HANDLE, DWORD, PHANDLE);
return ((PFN_Func) ret)(ProcessHandle, DesiredAccess, TokenHandle);
}
}
return FALSE;
}
BOOL Local_LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid)
{
if (Local_Advapi32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Advapi32(), HIDEA_LOOKUPPRIVILEGEVALUEW);
}
if (ret)
{
typedef BOOL (WINAPI * PFN_Func)(LPCWSTR, LPCWSTR, PLUID);
return ((PFN_Func) ret)(lpSystemName, lpName, lpLuid);
}
}
return FALSE;
}
BOOL Local_AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength)
{
if (Local_Advapi32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Advapi32(), HIDEA_ADJUSTTOKENPRIVILEGES);
}
if (ret)
{
typedef BOOL (WINAPI * PFN_Func)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
return ((PFN_Func) ret)(TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength);
}
}
return FALSE;
}
LPVOID Local_VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect)
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_VIRTUALALLOCEX);
}
if (ret)
{
typedef LPVOID (WINAPI * PFN_Func)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
return ((PFN_Func) ret)(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
}
}
return NULL;
}
BOOL Local_WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten)
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_WRITEPROCESSMEMORY);
}
if (ret)
{
typedef BOOL (WINAPI * PFN_Func)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*);
return ((PFN_Func) ret)(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten);
}
}
return FALSE;
}
HANDLE Local_CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_CREATEREMOTETHREAD);
}
if (ret)
{
typedef HANDLE (WINAPI * PFN_Func)(HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
return ((PFN_Func) ret)(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
}
}
return NULL;
}
DWORD Local_WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_WAITFORSINGLEOBJECT);
}
if (ret)
{
typedef DWORD (WINAPI * PFN_Func)(HANDLE, DWORD);
return ((PFN_Func) ret)(hHandle, dwMilliseconds);
}
}
return 0;
}
BOOL Local_ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead)
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_READPROCESSMEMORY);
}
if (ret)
{
typedef BOOL (WINAPI * PFN_Func)(HANDLE, LPCVOID, LPVOID, SIZE_T, SIZE_T*);
return ((PFN_Func) ret)(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
}
}
return FALSE;
}
BOOL Local_VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
{
if (Local_Kernel32())
{
static FARPROC ret = NULL;
if (!ret)
{
ret = GetProcAddress(Local_Kernel32(), HIDEA_VIRTUALFREEEX);
}
if (ret)
{
typedef BOOL (WINAPI * PFN_Func)(HANDLE, LPVOID, SIZE_T, DWORD);
return ((PFN_Func) ret)(hProcess, lpAddress, dwSize, dwFreeType);
}
}
return FALSE;
}
/* -------------------------------------------------------------------- */
/* ----------- End of Local APIs -------------------------------------- */
/* -------------------------------------------------------------------- */
void ChangeParentCurrentDirectory(wchar_t* szNewDirectory)
{
#ifndef _DEBUG
if (g_bIsCMD)
{
EnableDebugPriv();
DWORD dwID = GetParentProcessID(GetCurrentProcessId());
LoadDllForRemoteThread(dwID, szNewDirectory);
}
else
{
#endif
#ifdef _DEBUG
OutputDebugString(HIDEW_CHANGETO);
OutputDebugStringW(szNewDirectory);
OutputDebugString(HIDEW_LINEFEED);
// DebugBreak();
#endif
_tprintf(HIDEW_CHANGETOPARAM, szNewDirectory);
#ifndef _DEBUG
}
#endif
}
BOOL IsWindowsNT()
{
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
#pragma warning (push)
#pragma warning (disable : 4996)
bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
#pragma warning (pop)
if(bOsVersionInfoEx == 0)
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
#pragma warning (push)
#pragma warning (disable : 4996)
if (!GetVersionEx((OSVERSIONINFO *)&osvi))
#pragma warning (pop)
{
return FALSE;
}
}
return osvi.dwPlatformId == VER_PLATFORM_WIN32_NT;
}
DWORD LoadDllForRemoteThread(DWORD processID, wchar_t* lpPathName)
{
HANDLE hProcess = Local_OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE, processID);
if (hProcess != NULL)
{
ExecuteRemoteThread(hProcess, lpPathName);
Local_CloseHandle(hProcess);
}
return 0;
}
void EnableDebugPriv(void)
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
Local_OpenProcessToken(Local_GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
Local_LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &sedebugnameValue);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
Local_AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL);
Local_CloseHandle(hToken);
}
bool ExecuteRemoteThread(HANDLE hProcess, wchar_t* lpPathName)
{
HANDLE ht = 0;
void *p = 0;
RemoteThreadBlock *c = 0;
bool result = false;
DWORD rc;
HMODULE hKernel32 = 0;
RemoteThreadBlock localCopy;
ZeroMemory(&localCopy, sizeof(localCopy));
p = Local_VirtualAllocEx(hProcess, 0, MAXINJECTSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (p == 0)
{
goto cleanup;
}
c = (RemoteThreadBlock*) Local_VirtualAllocEx(hProcess, 0, sizeof(RemoteThreadBlock), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (c == 0)
{
goto cleanup;
}
if (!Local_WriteProcessMemory(hProcess, p, &RemoteThread, MAXINJECTSIZE, 0))
{
goto cleanup;
}
hKernel32 = LoadLibrary(HIDEW_KERNEL32);
if (hKernel32 == NULL)
{
goto cleanup;
}
localCopy.fnGetProcAddress = (PGetProcAddress)GetProcAddress(hKernel32, HIDEA_GETPROCADDRESS);
localCopy.fnSetCurrentDirectory = (PSetCurrentDirectory)GetProcAddress(hKernel32, HIDEA_SETCURRENTDIRECTORYW);
localCopy.fnGetCurrentDirectory = (PGetCurrentDirectory)GetProcAddress(hKernel32, HIDEA_GETCURRENTDIRECTORYW);
localCopy.fnSetEnvironmentVariable = (PSetEnvironmentVariable)GetProcAddress(hKernel32, HIDEA_SETENVIRONMENTVARIABLEW);
if (localCopy.fnSetCurrentDirectory == NULL ||
localCopy.fnGetCurrentDirectory == NULL ||
localCopy.fnGetProcAddress == NULL ||
localCopy.fnSetEnvironmentVariable == NULL)
{
goto cleanup;
}
wchar_t szDriveName[512];
wchar_t lpFullName[512];
ZeroMemory(szDriveName, sizeof szDriveName);
ZeroMemory(lpFullName, sizeof lpFullName);
GetFullPathName(lpPathName, _countof(lpFullName), lpFullName, NULL);
szDriveName[1] = lpFullName[0];
szDriveName[0] = L'=';
szDriveName[2] = L':';
szDriveName[3] = 0;
wcscpy_s(localCopy.szDirectoryPath, lpPathName);
wcscpy_s(localCopy.szDriveName, szDriveName);
wcscpy_s(localCopy.szFullPath, lpFullName);
if (!Local_WriteProcessMemory(hProcess, c, &localCopy, sizeof localCopy, 0))
{
goto cleanup;
}
ht = Local_CreateRemoteThread(hProcess, 0, 0, (DWORD (__stdcall *)(void *)) p, c, 0, &rc);
if (ht == NULL)
{
goto cleanup;
}
rc = Local_WaitForSingleObject(ht, INFINITE);
switch (rc)
{
case WAIT_TIMEOUT:
goto cleanup;
case WAIT_FAILED:
goto cleanup;
case WAIT_OBJECT_0:
if (!Local_ReadProcessMemory(hProcess, c, &localCopy, sizeof localCopy, 0))
{
goto cleanup;
}
else
{
switch (localCopy.dwReturn)
{
case ERROR_UNABLE_TO_GET_CURRENT_DIR:
_tprintf(HIDEW_UNABLETOGET);
break;
case ERROR_UNABLE_TO_SET_CURRENT_DIR:
_tprintf(HIDEW_UNABLETOSET);
break;
case ERROR_NETWORK_PATH_SPECIFIED:
_tprintf(HIDEW_NETWORKPATH);
break;
case ERROR_UNABLE_TO_SET_ENVIORNMENT:
_tprintf(HIDEW_UNABLETOSETENV);
break;
}
}
break;
default:
break;
}
cleanup:
Local_CloseHandle(ht);
if (p != 0)
{
Local_VirtualFreeEx(hProcess, p, 0, MEM_RELEASE);
}
if (c != 0)
{
Local_VirtualFreeEx(hProcess, c, 0, MEM_RELEASE);
}
if (hKernel32 != NULL)
{
FreeLibrary(hKernel32);
}
return result;
}
DWORD __stdcall RemoteThread(RemoteThreadBlock* execBlock)
{
typedef DWORD (*PRemoteDllFunction)();
if ((*execBlock->fnGetCurrentDirectory)(_countof(execBlock->szOldPath), execBlock->szOldPath) == 0)
{
execBlock->dwReturn = ERROR_UNABLE_TO_GET_CURRENT_DIR;
return execBlock->dwReturn;
}
if (!(*execBlock->fnSetCurrentDirectory)(execBlock->szDirectoryPath))
{
execBlock->dwReturn = ERROR_UNABLE_TO_SET_CURRENT_DIR;
return execBlock->dwReturn;
}
if ((*execBlock->fnGetCurrentDirectory)(_countof(execBlock->szFullPath), execBlock->szFullPath) == 0)
{
execBlock->dwReturn = ERROR_UNABLE_TO_GET_CURRENT_DIR;
return execBlock->dwReturn;
}
if (execBlock->szFullPath[0] == _T('\\'))
{
if (!(*execBlock->fnSetCurrentDirectory)(execBlock->szOldPath))
{
execBlock->dwReturn = ERROR_UNABLE_TO_SET_CURRENT_DIR;
return execBlock->dwReturn;
}
execBlock->dwReturn = ERROR_NETWORK_PATH_SPECIFIED;
return execBlock->dwReturn;
}
if (!(*execBlock->fnSetEnvironmentVariable)(execBlock->szDriveName, execBlock->szFullPath))
{
execBlock->dwReturn = ERROR_UNABLE_TO_SET_ENVIORNMENT;
return execBlock->dwReturn;
}
execBlock->dwReturn = 0;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment