-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
13 changed files
with
2,310 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/*++ | ||
Copyright (c) Alex Ionescu. All rights reserved. | ||
Module Name: | ||
nt.h | ||
Abstract: | ||
This header defines internal NT data structures and routines used by r0ak | ||
Author: | ||
Alex Ionescu (@aionescu) 21-Jul-2018 - First public version | ||
Environment: | ||
User mode only. | ||
--*/ | ||
|
||
#include <winternl.h> | ||
|
||
NTSYSAPI | ||
NTSTATUS | ||
NTAPI | ||
RtlAdjustPrivilege ( | ||
_In_ ULONG Privilege, | ||
_In_ BOOLEAN NewValue, | ||
_In_ BOOLEAN ForThread, | ||
_Out_ PBOOLEAN OldValue | ||
); | ||
|
||
NTSYSAPI | ||
NTSTATUS | ||
NTAPI | ||
ZwOpenSection ( | ||
_Out_ PHANDLE SectionHandle, | ||
_In_ ACCESS_MASK DesiredAccess, | ||
_In_ POBJECT_ATTRIBUTES ObjectAttributes | ||
); | ||
|
||
typedef struct _WORK_QUEUE_ITEM | ||
{ | ||
LIST_ENTRY List; | ||
PVOID WorkerRoutine; | ||
PVOID Parameter; | ||
} WORK_QUEUE_ITEM, *PWORK_QUEUE_ITEM; | ||
|
||
typedef struct _RTL_BALANCED_LINKS | ||
{ | ||
struct _RTL_BALANCED_LINKS *Parent; | ||
struct _RTL_BALANCED_LINKS *LeftChild; | ||
struct _RTL_BALANCED_LINKS *RightChild; | ||
CHAR Balance; | ||
UCHAR Reserved[3]; | ||
} RTL_BALANCED_LINKS; | ||
typedef RTL_BALANCED_LINKS *PRTL_BALANCED_LINKS; | ||
|
||
typedef struct _RTL_AVL_TABLE | ||
{ | ||
RTL_BALANCED_LINKS BalancedRoot; | ||
PVOID OrderedPointer; | ||
ULONG WhichOrderedElement; | ||
ULONG NumberGenericTableElements; | ||
ULONG DepthOfTree; | ||
PRTL_BALANCED_LINKS RestartKey; | ||
ULONG DeleteCount; | ||
PVOID CompareRoutine; | ||
PVOID AllocateRoutine; | ||
PVOID FreeRoutine; | ||
PVOID TableContext; | ||
} RTL_AVL_TABLE; | ||
typedef RTL_AVL_TABLE *PRTL_AVL_TABLE; | ||
|
||
typedef struct tagXSGLOBALS | ||
{ | ||
PVOID NetworkFontsTableLock; | ||
PRTL_AVL_TABLE NetworkFontsTable; | ||
PVOID TrustedFontsTableLock; | ||
PRTL_AVL_TABLE TrustedFontsTable; | ||
} XSGLOBALS, *PXSGLOBALS; | ||
|
||
#pragma warning(push) | ||
#pragma warning(disable:4214) | ||
#pragma warning(disable:4201) | ||
typedef struct _SYSTEM_BIGPOOL_ENTRY | ||
{ | ||
union | ||
{ | ||
PVOID VirtualAddress; | ||
ULONG_PTR NonPaged : 1; | ||
}; | ||
ULONGLONG SizeInBytes; | ||
union | ||
{ | ||
UCHAR Tag[4]; | ||
ULONG TagUlong; | ||
}; | ||
} SYSTEM_BIGPOOL_ENTRY, *PSYSTEM_BIGPOOL_ENTRY; | ||
#pragma warning(pop) | ||
|
||
typedef struct _SYSTEM_BIGPOOL_INFORMATION | ||
{ | ||
ULONG Count; | ||
SYSTEM_BIGPOOL_ENTRY AllocatedInfo[ANYSIZE_ARRAY]; | ||
} SYSTEM_BIGPOOL_INFORMATION, *PSYSTEM_BIGPOOL_INFORMATION; | ||
|
||
#define SE_DEBUG_PRIVILEGE 20 | ||
#define SystemBigPoolInformation (SYSTEM_INFORMATION_CLASS)66 | ||
#define SystemHardwareSecurityTestInterfaceResultsInformation (SYSTEM_INFORMATION_CLASS)166 | ||
#define PERF_WORKER_THREAD 0x48000000 | ||
#define EVENT_TRACE_GROUP_THREAD 0x0500 | ||
#define PERFINFO_LOG_TYPE_WORKER_THREAD_ITEM_END (EVENT_TRACE_GROUP_THREAD | 0x41) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
/*++ | ||
Copyright (c) Alex Ionescu. All rights reserved. | ||
Module Name: | ||
r0ak.c | ||
Abstract: | ||
This module implements the main command line interface for r0ak | ||
Author: | ||
Alex Ionescu (@aionescu) 21-Jul-2018 - First public version | ||
Environment: | ||
User mode only. | ||
--*/ | ||
|
||
#include "r0ak.h" | ||
|
||
_Success_(return != 0) | ||
BOOL | ||
CmdParseInputParameters ( | ||
_In_ PCHAR Arguments[], | ||
_Out_ PVOID* Function, | ||
_Out_ PULONG_PTR FunctionArgument | ||
) | ||
{ | ||
PVOID functionPointer; | ||
PCHAR moduleName, functionName, pBang, functionNameAndModule; | ||
|
||
// | ||
// Check if the user passed in a module!function instead | ||
// | ||
functionPointer = (PVOID)strtoull(Arguments[2], NULL, 0); | ||
if (functionPointer == NULL) | ||
{ | ||
// | ||
// Separate out the module name from the symbol name | ||
// | ||
functionNameAndModule = Arguments[2]; | ||
pBang = strchr(functionNameAndModule, '!'); | ||
if (pBang == NULL) | ||
{ | ||
printf("[-] Malformed symbol string: %s\n", | ||
Arguments[2]); | ||
return FALSE; | ||
} | ||
|
||
// | ||
// Now get the remaining function name | ||
// | ||
functionName = pBang + 1; | ||
*pBang = ANSI_NULL; | ||
moduleName = functionNameAndModule; | ||
|
||
// | ||
// Get the symbol requested | ||
// | ||
functionPointer = SymLookup(moduleName, functionName); | ||
if (functionPointer == NULL) | ||
{ | ||
printf("[-] Could not find symbol!\n"); | ||
return FALSE; | ||
} | ||
} | ||
|
||
// | ||
// Return the data back | ||
// | ||
*Function = functionPointer; | ||
*FunctionArgument = strtoull(Arguments[3], NULL, 0); | ||
return TRUE; | ||
} | ||
|
||
INT | ||
main ( | ||
_In_ INT ArgumentCount, | ||
_In_ PCHAR Arguments[] | ||
) | ||
{ | ||
PKERNEL_EXECUTE kernelExecute; | ||
BOOL b; | ||
ULONG_PTR kernelValue; | ||
PVOID kernelPointer; | ||
INT errValue; | ||
|
||
// | ||
// Print header | ||
// | ||
printf("r0ak v1.0.0 -- Ring 0 Army Knife\n"); | ||
printf("http://www.github.com/ionescu007/r0ak\n"); | ||
printf("Copyright (c) 2018 Alex Ionescu [@aionescu]\n"); | ||
printf("http://www.windows-internals.com\n\n"); | ||
kernelExecute = NULL; | ||
errValue = -1; | ||
|
||
// | ||
// We need four arguments | ||
// | ||
if (ArgumentCount != 4) | ||
{ | ||
printf("USAGE: r0ak.exe\n" | ||
" [--execute <Address | module!function> <Argument>]\n" | ||
" [--write <Address | module!function> <Value>]\n" | ||
" [--read <Address | module!function> <Size>]\n"); | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// Initialize symbol engine | ||
// | ||
b = SymSetup(); | ||
if (b == FALSE) | ||
{ | ||
printf("[-] Failed to initialize Symbol Engine\n"); | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// Initialize our execution engine | ||
// | ||
b = KernelExecuteSetup(&kernelExecute, g_TrampolineFunction); | ||
if (b == FALSE) | ||
{ | ||
printf("[-] Failed to setup Ring 0 execution engine\n"); | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// Caller wants to execute their own routine | ||
// | ||
if (strstr(Arguments[1], "--execute")) | ||
{ | ||
// | ||
// Get the initial inputs | ||
// | ||
b = CmdParseInputParameters(Arguments, &kernelPointer, &kernelValue); | ||
if (b == FALSE) | ||
{ | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// Execute it | ||
// | ||
b = CmdExecuteKernel(kernelExecute, kernelPointer, kernelValue); | ||
if (b == FALSE) | ||
{ | ||
printf("[-] Failed to execute function\n"); | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// It's now safe to exit/cleanup state | ||
// | ||
printf("[+] Function executed successfuly!\n"); | ||
errValue = 0; | ||
} | ||
else if (strstr(Arguments[1], "--write")) | ||
{ | ||
// | ||
// Get the initial inputs | ||
// | ||
b = CmdParseInputParameters(Arguments, &kernelPointer, &kernelValue); | ||
if (b == FALSE) | ||
{ | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// Only 32-bit values can be written | ||
// | ||
if (kernelValue > ULONG_MAX) | ||
{ | ||
printf("[-] Invalid 64-bit value, r0ak only supports 32-bit\n"); | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// Write it! | ||
// | ||
b = CmdWriteKernel(kernelExecute, kernelPointer, (ULONG)kernelValue); | ||
if (b == FALSE) | ||
{ | ||
printf("[-] Failed to write variable\n"); | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// It's now safe to exit/cleanup state | ||
// | ||
printf("[+] Write executed successfuly!\n"); | ||
errValue = 0; | ||
} | ||
else if (strstr(Arguments[1], "--read")) | ||
{ | ||
// | ||
// Get the initial inputs | ||
// | ||
b = CmdParseInputParameters(Arguments, &kernelPointer, &kernelValue); | ||
if (b == FALSE) | ||
{ | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// Only 4GB of data can be read | ||
// | ||
if (kernelValue > ULONG_MAX) | ||
{ | ||
printf("[-] Invalid size, r0ak can only read up to 4GB of data\n"); | ||
goto Cleanup; | ||
} | ||
|
||
|
||
// | ||
// Write it! | ||
// | ||
b = CmdReadKernel(kernelExecute, kernelPointer, (ULONG)kernelValue); | ||
if (b == FALSE) | ||
{ | ||
printf("[-] Failed to read variable\n"); | ||
goto Cleanup; | ||
} | ||
|
||
// | ||
// It's now safe to exit/cleanup state | ||
// | ||
printf("[+] Read executed successfuly!\n"); | ||
errValue = 0; | ||
} | ||
|
||
Cleanup: | ||
// | ||
// Teardown the execution engine if we initialized it | ||
// | ||
if (kernelExecute != NULL) | ||
{ | ||
KernelExecuteTeardown(kernelExecute); | ||
} | ||
return errValue; | ||
} |
Oops, something went wrong.