mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-10-26 21:17:40 +00:00
149 lines
5.7 KiB
C
149 lines
5.7 KiB
C
#define WIN32_LEAN_AND_MEAN
|
|
#define _WIN32_WINNT 0x0601
|
|
#include <windows.h>
|
|
|
|
typedef LONG (WINAPI *query_process)(HANDLE, ULONG, void *, ULONG, ULONG *);
|
|
|
|
struct basic_information {
|
|
LONG exit_status;
|
|
void *peb;
|
|
ULONG_PTR affinity;
|
|
LONG priority;
|
|
ULONG_PTR pid, parent;
|
|
};
|
|
|
|
static volatile DWORD peer_id;
|
|
static volatile DWORD payload = 0x13579bdf;
|
|
|
|
static DWORD integrity(HANDLE token)
|
|
{
|
|
union { ULONGLONG align; BYTE bytes[64]; } buffer;
|
|
DWORD size;
|
|
TOKEN_MANDATORY_LABEL *label = (TOKEN_MANDATORY_LABEL *)buffer.bytes;
|
|
if (!GetTokenInformation(token, TokenIntegrityLevel, &buffer, sizeof(buffer), &size)) return 0xffffffff;
|
|
return *GetSidSubAuthority(label->Label.Sid, 0);
|
|
}
|
|
|
|
static BOOL set_integrity(HANDLE token, DWORD level)
|
|
{
|
|
struct { BYTE revision, count, authority[6]; DWORD level; } sid = {1, 1, {0, 0, 0, 0, 0, 16}, level};
|
|
TOKEN_MANDATORY_LABEL label = {{&sid, SE_GROUP_INTEGRITY}};
|
|
return SetTokenInformation(token, TokenIntegrityLevel, &label, sizeof(label));
|
|
}
|
|
|
|
static DWORD traversal(HANDLE token)
|
|
{
|
|
TOKEN_PRIVILEGES privileges;
|
|
DWORD size;
|
|
if (!GetTokenInformation(token, TokenPrivileges, &privileges, sizeof(privileges), &size) || privileges.PrivilegeCount != 1)
|
|
return 0xffffffff;
|
|
return privileges.Privileges[0].Attributes;
|
|
}
|
|
|
|
static BOOL set_traversal(HANDLE token, DWORD attributes)
|
|
{
|
|
TOKEN_PRIVILEGES privileges = {1, {{{23, 0}, 0}}};
|
|
privileges.Privileges[0].Attributes = attributes;
|
|
return AdjustTokenPrivileges(token, FALSE, &privileges, 0, NULL, NULL);
|
|
}
|
|
|
|
static BOOL start(WCHAR mode, PROCESS_INFORMATION *child)
|
|
{
|
|
STARTUPINFOW startup = {0};
|
|
WCHAR command[512];
|
|
DWORD length;
|
|
startup.cb = sizeof(startup);
|
|
command[0] = '"';
|
|
length = GetModuleFileNameW(NULL, command + 1, 480);
|
|
if (!length || length >= 480) return FALSE;
|
|
command[++length] = '"'; command[++length] = ' '; command[++length] = '-'; command[++length] = '-'; command[++length] = mode; command[++length] = 0;
|
|
return CreateProcessW(NULL, command, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startup, child);
|
|
}
|
|
|
|
static int query_peer(query_process query)
|
|
{
|
|
HANDLE process, token, limited;
|
|
struct basic_information information;
|
|
ULONG length;
|
|
ULONG_PTR image;
|
|
DWORD count, value;
|
|
SIZE_T copied;
|
|
process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, peer_id);
|
|
if (!process || !OpenProcessToken(process, TOKEN_ALL_ACCESS, &token) || integrity(token) != 4096 || traversal(token) != 1)
|
|
return 20;
|
|
if (!set_integrity(token, 2048) || !set_traversal(token, SE_PRIVILEGE_ENABLED) || GetLastError() ||
|
|
!GetProcessHandleCount(process, &count) || !count || query(process, 0, &information, sizeof(information), &length) ||
|
|
information.pid != peer_id || !ReadProcessMemory(process, (BYTE *)information.peb + 2 * sizeof(void *), &image, sizeof(image), &copied))
|
|
return 21;
|
|
const void *remote = (void *)(image + (ULONG_PTR)&payload - (ULONG_PTR)GetModuleHandleW(NULL));
|
|
if (!ReadProcessMemory(process, remote, &value, sizeof(value), &copied) || value != 0x13579bdf)
|
|
return 22;
|
|
value = 0x2468ace0;
|
|
if (!WriteProcessMemory(process, (void *)remote, &value, sizeof(value), &copied) || copied != sizeof(value))
|
|
return 23;
|
|
limited = OpenProcess(PROCESS_VM_READ, FALSE, peer_id);
|
|
HANDLE denied = NULL;
|
|
if (!limited || OpenProcessToken(limited, TOKEN_QUERY, &denied) || GetLastError() != ERROR_ACCESS_DENIED || denied ||
|
|
GetProcessHandleCount(limited, &count) || GetLastError() != ERROR_ACCESS_DENIED)
|
|
return 24;
|
|
CloseHandle(limited);
|
|
CloseHandle(token);
|
|
CloseHandle(process);
|
|
return 0;
|
|
}
|
|
|
|
int raven_entry(void)
|
|
{
|
|
const WCHAR *line = GetCommandLineW();
|
|
query_process query = (query_process)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationProcess");
|
|
HANDLE token = NULL;
|
|
for (unsigned index = 0; line[index]; ++index)
|
|
if (line[index] == '-' && line[index + 1] == '-') {
|
|
if (line[index + 2] == 'a') return query_peer(query);
|
|
if (line[index + 2] == 'b') {
|
|
if (payload != 0x2468ace0 || !OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) || integrity(token) != 2048 || traversal(token) != 3)
|
|
return 25;
|
|
CloseHandle(token);
|
|
return 0;
|
|
}
|
|
}
|
|
PROCESS_INFORMATION owner, reader;
|
|
struct basic_information information;
|
|
ULONG length;
|
|
ULONG_PTR image;
|
|
SIZE_T copied;
|
|
DWORD code = 0;
|
|
int result = 0;
|
|
if (!query || !start('b', &owner)) return 1;
|
|
if (!start('a', &reader)) { TerminateProcess(owner.hProcess, 99); return 2; }
|
|
if (!OpenProcessToken(owner.hProcess, TOKEN_ALL_ACCESS, &token) || !set_integrity(token, 4096) || !set_traversal(token, 0) ||
|
|
query(reader.hProcess, 0, &information, sizeof(information), &length) ||
|
|
!ReadProcessMemory(reader.hProcess, (BYTE *)information.peb + 2 * sizeof(void *), &image, sizeof(image), &copied) ||
|
|
!WriteProcessMemory(reader.hProcess, (void *)(image + (ULONG_PTR)&peer_id - (ULONG_PTR)GetModuleHandleW(NULL)),
|
|
&owner.dwProcessId, sizeof(owner.dwProcessId), &copied)) {
|
|
result = 3;
|
|
goto done;
|
|
}
|
|
if (ResumeThread(reader.hThread) != 1 || WaitForSingleObject(reader.hProcess, 15000) != WAIT_OBJECT_0 ||
|
|
!GetExitCodeProcess(reader.hProcess, &code) || code || integrity(token) != 2048 || traversal(token) != 3) {
|
|
result = code ? (int)code : 4;
|
|
goto done;
|
|
}
|
|
if (ResumeThread(owner.hThread) != 1 || WaitForSingleObject(owner.hProcess, 10000) != WAIT_OBJECT_0 ||
|
|
!GetExitCodeProcess(owner.hProcess, &code) || code || integrity(token) != 2048 || traversal(token) != 3)
|
|
result = code ? (int)code : 5;
|
|
done:
|
|
if (result) {
|
|
TerminateProcess(reader.hProcess, 99);
|
|
TerminateProcess(owner.hProcess, 99);
|
|
WaitForSingleObject(reader.hProcess, 5000);
|
|
WaitForSingleObject(owner.hProcess, 5000);
|
|
}
|
|
if (token) CloseHandle(token);
|
|
CloseHandle(reader.hThread);
|
|
CloseHandle(reader.hProcess);
|
|
CloseHandle(owner.hThread);
|
|
CloseHandle(owner.hProcess);
|
|
return result;
|
|
}
|