BOOL GetSystemToken(PHANDLE phSystemToken)
{
BOOL bResult = FALSE;
HANDLE hWinlogonProcess, hWinlogonToken;
// In theory only PROCESS_QUERY_INFORMATION is necessary (but that's in theory)
bResult = GetProcessbyNameOrId(SOME_SYSTEM_PROCESS_IN_CURRENT_SESSION, hWinlogonProcess, PROCESS_ALL_ACCESS);
if (bResult) {
bResult = OpenProcessToken(hWinlogonProcess, TOKEN_DUPLICATE, hWinlogonToken);
if (bResult) {
*phSystemToken = hWinlogonToken;
}
else {
_tprintf(_T("Failed to get winlogon token handle with error %#.8x\n"), GetLastError());
}
CloseHandle(hWinlogonProcess);
}
else {
_tprintf(_T("Failed to get handle to winlogon with error %#.8x\n"), GetLastError());
}
return bResu minimum necessary
bResult = DuplicateTokenEx(hSystemToken, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenPrimary, hSession0Token);
if (bResult) {
// And switch the clone to session 0
bResult = SetTokenInformation(hSession0Token, TokenSessionId, session0, sizeof(session0));
if (bResult) {
*phSession0Token = hSession0Token;
}
else {
CloseHandle(hSession0Token);
_tprintf(_T("Failed to adjust session id in process token with error %#.8x\n"), GetLastError());
}
}
else {
_tprintf(_T("Failed to duplicate token with error %#.8x\n"), GetLastError());
}
return bResuPrivileges[i].Luid.LowPart == luid.LowPart) (ptp->Privileges[i].Luid.HighPart == luid.HighPart);
}
} // if gettokeninformation
else {
_tprintf(_T("Failed to get token privileges with error %#.8x\n"), error);
}
HeapFree(GetProcessHeap(), 0, ptp);
}
else {
_tprintf(_T("Failed to allocate memory for privileges list\n"));
}
}
else {
_tprintf(_T("Failed token privileges list size with error %#.8x\n"), error);
}
return bResu<
}
// Enable or disable privilege if present in target token
BOOL TogglePrivilege(HANDLE hToken, LPTSTR priv, BOOL enable)
{
BOOL bResult = FALSE;
DWORD error;
LUID luid;
TOKEN_PRIVILEGES tp;
bResult = LookupPrivilegeValue(NULL, priv, luid);
if (bResult) {
// Only attempt to enable privilege if present in token
if (IsPrivilegePresent(hToken, luid)) {
// Setup TP struct
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; // zero for disabled, not removed
// Adjust the token
bResult = AdjustTokenPrivileges(hToken, FALSE, tp, 0, (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL);
bResult = (ERROR_SUCCESS == (error = GetLastError()));
if ((!bResult)) {
_tprintf(_T("Adjusting token privileges failed with error %#.8x\n"), error);
}
}
else {
bResult = FALSE;
}
}
else {
_tprintf(_T("Privilege LUID lookup failed with error %#.8x\n"), GetLastError());
}
return bResu<
}
// Enables/Disables the debug privilege in current process' token
BOOL ToggleDebugPrivilege(BOOL enable)
{
BOOL bResult = FALSE;
HANDLE hProcess, hToken;
// Get current process (pseudo-handle, no need to close)
hProcess = GetCurrentProcess();
// Get current process's token
bResult = OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, hToken);
if (bResult) {
bResult = TogglePrivilege(hToken, SE_DEBUG_NAME, enable);
CloseHandle(hToken);
}
else {
_tprintf(_T("Access to current process' token failed with error %#.8x\n"), GetLastError());
}
return bResu<
}
// Either returns true (for a retry) or false (success or failure)
// Failure: pnbProcesses is 0 and there is no buffer to free
// Success: pnbProcesses is greater than 0 and *pprocesses contains a pointer to be freed
BOOL FillProcessesListWithAlloc(PDWORD *pprocesses, DWORD size, PDWORD pnbProcesses)
{
DWORD *processes, bytes = 0, result = 0;
BOOL retry = FALSE, realloc = FALSE;
// Attempt allocation or reallocation
if (!(*pprocesses)) {
processes = (PDWORD)HeapAlloc(GetProcessHeap(), 0, size);
}
else {
processes = (PDWORD)HeapReAlloc(GetProcessHeap(), 0, *pprocesses, size);
realloc = TRUE;
}
// If allocation for requested size succeeded
if (processes) {
if (EnumProcesses(processes, size, bytes)) {
// Success
if (bytes= size) {
// Not large enough, allocating
*pprocesses = NULL;
do {
size *= 2; // doubling size of buffer for processIDs list
retry = FillProcessesListWithAlloc(pprocesses, size, nb_processes);
} while (retry);
}
else {
nb_processes = bytes / sizeof(DWORD);
}
} // if enumProcesses
else {
_tprintf(_T("EnumProcesses failed with error %#.8x\n"), GetLastError());
}
return nb_processes;
}
// Returns success boolean and outputs process handle with requested rights
BOOL GetProcessbyNameOrId(LPTSTR searchstring, PHANDLE phProcess, DWORD rights)
{
BOOL found = FALSE;
HMODULE hMod;
DWORD *processes, lpProcesses[QUITE_LARGE_NB_PROCESSES], bytes, processId;
SIZE_T nbProcesses, i;
HANDLE hProcess;
TCHAR processname[MAX_PATH + 1], *stop;
processId = _tcstoul(searchstring, stop, 0);
if (processId *stop == L'\0') {
hProcess = OpenProcess(rights, FALSE, processId);
if (hProcess) {
*phProcess = hProcess;
found = TRUE;
}
}
else {
processes = lpProcesses;
nbProcesses = FillProcessesList(processes, sizeof(lpProcesses));
if (nbProcesses) {
for (i = 0; i hProcess = OpenProcess(IDENTIFICATION_RIGHTS, FALSE, processes[i]);
if (hProcess) {
if (EnumProcessModules(hProcess, hMod, sizeof(hMod), bytes)) {
if (GetModuleBaseName(hProcess, hMod, processname, sizeof(processname) / sizeof(TCHAR))) {
// Found the process by that name
if (!_tcsicmp(searchstring, processname)) {
// Close the handle and attempt reopenning with requested rights
CloseHandle(hProcess);
hProcess = OpenProcess(rights, FALSE, processes[i]);
if (hProcess) {
*phProcess = hProcess;
found = TRUE;
}
} // if _tcsicmp
} // if GetModuleBaseName
} // if EnumProcessModules
if (!found) {
// Only close this process handle if it is not the one we are looking for
CloseHandle(hProcess);
}
} // if hProcess
} // for all processes
if (processes != lpProcesses) {
HeapFree(GetProcessHeap(), 0, processes);
}
} // if nbProcesses
}
return found;
}
// Just returns process session
DWORD GetProcessSession(HANDLE hProcess)
{
DWORD sessionId = (DWORD)(-1);
if (!ProcessIdToSessionId(GetProcessId(hProcess), sessionId)) {
_tprintf(_T("Getting target process session id failed with error %#.8x\n"), GetLastError());
}
return sessionId;
}
// Actual dll injection logic. Returns error code or ERROR_SUCCESS (0) if successful
DWORD InjectDll(LPTSTR process, LPTSTR dll)
{
BOOL bResu<
DWORD dwResu<
LPVOID pMem = NULL;
HANDLE hProcess = NULL, hThread = NULL;
DWORD threadId, waitResult, threadExitCode;
SIZE_T sizerequired, dllpathlen, byteswritten;
LPTHREAD_START_ROUTINE pLoadLibrary;
// Find the FIRST process by that name
bResult = GetProcessbyNameOrId(process, hProcess, INJECTION_RIGHTS);
if (bResult) {
// Get required size, including terminating character
dllpathlen = _tcsnlen(dll, MAX_PATH);
if (dllpathlen sizerequired = sizeof(TCHAR)*(dllpathlen + 1);
// Allocate a page in the target process
pMem = VirtualAllocEx(hProcess, 0x0, sizerequired, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (pMem) {
// Copy dll path to target process
bResult = WriteProcessMemory(hProcess, pMem, dll, sizerequired, byteswritten);
if (bResult) {
// Get address to LoadLibrary function
pLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), LOADLIBRARY);
if (pLoadLibrary) {
// Create remote thread pointing to LoadLibrary[A|W]
hThread = CreateRemoteThread(hProcess, NULL, 0, pLoadLibrary, pMem, 0, threadId);
if (hThread) {
waitResult = WaitForSingleObject(hThread, TIMEOUT_10SEC);
if (waitResult == WAIT_OBJECT_0) {
bResult = GetExitCodeThread(hThread, threadExitCode);
if (bResult threadExitCode) {
dwResult = ERROR_SUCCESS;
}
else {
if (bResult) {
dwResult = ERROR_UNIDENTIFIED_ERROR;
_tprintf(_T("LoadLibrary failed, check for dll file presence and x86/x64 mismatch\n"));
}
else {
dwResult = GetLastError();
_tprintf(_T("Could not check LoadLibrary return value in remote thread, error %#.8x\n"), dwResult);
}
}
} // if waitResult==WAIT_OBJECT_0
else {
dwResult = waitResu<
_tprintf(_T("Aborting: %s\n"), waitResult == WAIT_TIMEOUT ? _T("remote thread has been hung for 10 secs") : _T("wait failed"));
}
CloseHandle(hThread);
} // if hThread
else {
dwResult = GetLastError();
_tprintf(_T("Creating remote thread in process %u failed with error %#.8x\n"), GetProcessId(hProcess), dwResult);
}
} // if pLoadLibrary
else {
dwResult = GetLastError();
_tprintf(_T("Failed to get LoadLibrary function address with error %#.8x\n"), dwResult);
}
} // if bResult
else {
dwResult = GetLastError();
_tprintf(_T("Writing remote process %u memory failed with error %#.8x\n"), GetProcessId(hProcess), dwResult);
}
if (!VirtualFreeEx(hProcess, pMem, 0, MEM_RELEASE)) {
dwResult = GetLastError();
_tprintf(_T("Failed to free remote process' allocated memory, error %#.8x\n"), dwResult);
}
} // if pMem
else {
dwResult = GetLastError();
_tprintf(_T("Remote process %u allocation failed with error %#.8x\n"), GetProcessId(hProcess), dwResult);
}
} // if pathlen valid
else {
dwResult = ERROR_BUFFER_OVERFLOW;
_tprintf(_T("Dll path too long\n"));
}
CloseHandle(hProcess);
} // if getProcessbyNameOrId
else {
dwResult = ERROR_NOT_FOUND;
}
return dwResu<
}