mirror of
https://github.com/entropy-z/Kharon
synced 2026-06-06 15:34:34 +00:00
339 lines
11 KiB
C++
339 lines
11 KiB
C++
/*
|
|
Get target process by name/pid and retrieve informations like:
|
|
- tokens
|
|
- modules
|
|
- handles
|
|
- protection
|
|
- command line
|
|
- threads
|
|
- arch
|
|
*/
|
|
|
|
#include <general.h>
|
|
|
|
auto get_modules(
|
|
_In_ HANDLE process_handle
|
|
) -> void {
|
|
HMODULE modules[1024];
|
|
ULONG bytes_needed = 0;
|
|
|
|
if ( ! EnumProcessModulesEx( process_handle, modules, sizeof(modules), &bytes_needed, LIST_MODULES_ALL ) ) {
|
|
BeaconPrintfW( CALLBACK_ERROR, L"EnumProcessModulesEx failed with error: (%d) %s\n", GetLastError(), fmt_error( GetLastError() ) );
|
|
return;
|
|
}
|
|
|
|
INT32 module_count = bytes_needed / sizeof(HMODULE);
|
|
|
|
for ( INT32 i = 0; i < module_count; i++) {
|
|
WCHAR module_name[MAX_PATH * sizeof(WCHAR)] = { 0 };
|
|
MODULEINFO module_info = { 0 };
|
|
|
|
if ( GetModuleFileNameExW( process_handle, modules[i], module_name, MAX_PATH * sizeof(WCHAR) ) ) {
|
|
GetModuleInformation( process_handle, modules[i], &module_info, sizeof(module_info) );
|
|
|
|
BeaconPkgBytes( (PBYTE)module_name, wcslen( module_name ) * sizeof(WCHAR) );
|
|
BeaconPkgInt64( (INT64)module_info.EntryPoint );
|
|
BeaconPkgInt64( (INT64)module_info.lpBaseOfDll );
|
|
BeaconPkgInt32( module_info.SizeOfImage );
|
|
|
|
printf(" [%03lu] 0x%p | Size: 0x%08lX | %s\n",
|
|
i,
|
|
module_info.lpBaseOfDll,
|
|
module_info.SizeOfImage,
|
|
module_name
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// NtQueryInformationProcess( handle, ProcessMitigationPolicy ... ); # PROCESS_MITIGATION_POLICY_INFORMATION
|
|
auto get_policy(
|
|
_In_ HANDLE process_handle
|
|
) -> void {
|
|
PROCESS_MITIGATION_POLICY_INFORMATION policy = {};
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
status = NtQueryInformationProcess( process_handle, ProcessMitigationPolicy, &policy, sizeof( policy ), nullptr );
|
|
if ( ! nt_success( status ) ) {
|
|
return;
|
|
}
|
|
|
|
policy.Policy;
|
|
|
|
return;
|
|
}
|
|
|
|
auto get_threads(
|
|
_In_ DWORD process_id
|
|
) -> void {
|
|
HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
|
|
if ( snapshot == INVALID_HANDLE_VALUE ) {
|
|
BeaconPrintfW( CALLBACK_ERROR, L"CreateToolhelp32Snapshot failed: (%d) %s\n", GetLastError(), fmt_error( GetLastError() ) );
|
|
return;
|
|
}
|
|
|
|
THREADENTRY32 thread_entry = { 0 };
|
|
thread_entry.dwSize = sizeof(THREADENTRY32);
|
|
|
|
printf("[*] Threads:\n");
|
|
|
|
if ( Thread32First(snapshot, &thread_entry) ) {
|
|
do {
|
|
if ( thread_entry.th32OwnerProcessID == process_id ) {
|
|
|
|
DbgPrint(" TID: %6lu | Priority: %2ld\n",
|
|
thread_entry.th32ThreadID,
|
|
thread_entry.tpBasePri
|
|
);
|
|
|
|
BeaconPkgInt32( thread_entry.th32ThreadID );
|
|
BeaconPkgInt32( thread_entry.dwFlags );
|
|
BeaconPkgInt32( thread_entry.dwSize );
|
|
BeaconPkgInt32( thread_entry.tpBasePri );
|
|
BeaconPkgInt32( thread_entry.tpBasePri );
|
|
}
|
|
} while ( Thread32Next( snapshot, &thread_entry ) );
|
|
}
|
|
|
|
CloseHandle( snapshot );
|
|
}
|
|
|
|
|
|
// NtQueryInformationProcess( handle, ProcessInstrumentationCallback, ... ); # PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION
|
|
auto get_instcallbacks(
|
|
_In_ HANDLE process_handle
|
|
) -> void {
|
|
PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION instrumentation_callback = { 0 };
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
status = NtQueryInformationProcess( process_handle, ProcessInstrumentationCallback, &instrumentation_callback, sizeof( instrumentation_callback ), nullptr );
|
|
if ( ! nt_success( status ) ) {
|
|
return;
|
|
}
|
|
|
|
instrumentation_callback.Callback;
|
|
|
|
return;
|
|
}
|
|
|
|
auto get_protection(
|
|
_In_ HANDLE process_handle
|
|
) -> void {
|
|
PS_PROTECTION protection = { 0 };
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
status = NtQueryInformationProcess( process_handle, ProcessProtectionInformation, &protection, sizeof( protection ), nullptr );
|
|
if ( ! nt_success( status ) ) {
|
|
return;
|
|
}
|
|
|
|
protection.Audit;
|
|
protection.Signer;
|
|
protection.Type;
|
|
|
|
return;
|
|
}
|
|
|
|
// NtQueryInformationProcess( handle, ProcessBasicInformation, ... ); # PROCESS_EXTENDED_BASIC_INFORMATION
|
|
// - arch
|
|
// - parent id / pid
|
|
auto get_basicex(
|
|
_In_ HANDLE process_handle,
|
|
_In_ BASICEX_FLAGS basicex_flags
|
|
) -> void {
|
|
PROCESS_EXTENDED_BASIC_INFORMATION basicex_info = { 0 };
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
status = NtQueryInformationProcess( ((HANDLE)-1), ProcessBasicInformation, &basicex_info, sizeof( basicex_info ), nullptr );
|
|
if ( ! nt_success( status ) ) {
|
|
return;
|
|
}
|
|
|
|
basicex_info.PebBaseAddress;
|
|
// basicex_info.IsWow64Process; // arch
|
|
basicex_info.UniqueProcessId; // pid
|
|
basicex_info.BasicInfo.InheritedFromUniqueProcessId; // ppid
|
|
|
|
return;
|
|
}
|
|
|
|
auto get_handles(
|
|
_In_ HANDLE process_handle
|
|
) -> void {
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG buffer_size = 0x10000;
|
|
PVOID buffer = nullptr;
|
|
|
|
do {
|
|
buffer = malloc( buffer_size );
|
|
if ( ! buffer ) return;
|
|
|
|
status = NtQueryInformationProcess(
|
|
process_handle, ProcessHandleInformation, buffer, buffer_size, nullptr
|
|
);
|
|
|
|
if ( status == STATUS_INFO_LENGTH_MISMATCH ) {
|
|
free( buffer );
|
|
buffer_size *= 2;
|
|
}
|
|
} while ( status == STATUS_INFO_LENGTH_MISMATCH );
|
|
|
|
if ( ! nt_success( status ) ) {
|
|
if ( buffer ) free( buffer );
|
|
BeaconPrintfW( CALLBACK_ERROR, L"NtQueryInformationProcess (handles) failed: (status: %X)\n", status );
|
|
return;
|
|
}
|
|
|
|
auto handle_info = (PPROCESS_HANDLE_SNAPSHOT_INFORMATION)buffer;
|
|
printf("[*] Handles (%llu):\n", handle_info->NumberOfHandles);
|
|
|
|
// for ( INT32 i = 0; i < min( handle_info->NumberOfHandles, 50 ); i++ ) {
|
|
// printf(" Handle: 0x%04X | Type: 0x%02lX | Access: 0x%08lX\n",
|
|
// (USHORT)(ULONG_PTR)handle_info->Handles[i].HandleValue,
|
|
// handle_info->Handles[i].ObjectTypeIndex,
|
|
// handle_info->Handles[i].GrantedAccess
|
|
// );
|
|
// }
|
|
|
|
free( buffer );
|
|
}
|
|
|
|
auto get_tokens(
|
|
_In_ HANDLE process_handle
|
|
) -> void {
|
|
HANDLE token_handle = nullptr;
|
|
TOKEN_ELEVATION elevation = { 0 };
|
|
ULONG elevation_size = sizeof( elevation );
|
|
ULONG token_user_size = 0;
|
|
ULONG integrity_size = 0;
|
|
|
|
if ( ! OpenProcessToken( process_handle, TOKEN_QUERY, &token_handle ) ) {
|
|
BeaconPrintfW( CALLBACK_ERROR, L"Failed to open process token with error: (%d) %s\n", GetLastError(), fmt_error( GetLastError() ) );
|
|
return;
|
|
}
|
|
|
|
GetTokenInformation( token_handle, TokenUser, nullptr, 0, &token_user_size );
|
|
|
|
auto token_user = (PTOKEN_USER)malloc( token_user_size );
|
|
if ( token_user && GetTokenInformation( token_handle, TokenUser, token_user, token_user_size, &token_user_size ) ) {
|
|
WCHAR username[MAX_PATH] = { 0 };
|
|
WCHAR domain[MAX_PATH] = { 0 };
|
|
DWORD username_len = sizeof( username );
|
|
DWORD domain_len = sizeof( domain );
|
|
|
|
SID_NAME_USE sid_type;
|
|
|
|
if ( LookupAccountSidW( nullptr, token_user->User.Sid, username, &username_len, domain, &domain_len, &sid_type ) ) {
|
|
DbgPrint("Token User: %s\\%s\n", domain, username);
|
|
|
|
BeaconPkgBytes( (PBYTE)username, wcslen( username ) * sizeof(WCHAR) );
|
|
BeaconPkgBytes( (PBYTE)domain, wcslen( domain ) * sizeof(WCHAR) );
|
|
}
|
|
}
|
|
|
|
if ( GetTokenInformation( token_handle, TokenElevation, &elevation, sizeof(elevation), &elevation_size ) ) {
|
|
DbgPrint( "Elevated: %s\n", elevation.TokenIsElevated ? "Yes" : "No" );
|
|
|
|
BeaconPkgInt32( elevation.TokenIsElevated );
|
|
}
|
|
|
|
GetTokenInformation( token_handle, TokenIntegrityLevel, nullptr, 0, &integrity_size );
|
|
|
|
auto integrity = (PTOKEN_MANDATORY_LABEL)malloc( integrity_size );
|
|
|
|
if ( integrity && GetTokenInformation( token_handle, TokenIntegrityLevel, integrity, integrity_size, &integrity_size ) ) {
|
|
ULONG integrity_level = *GetSidSubAuthority(
|
|
integrity->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(integrity->Label.Sid) - 1)
|
|
);
|
|
|
|
const char* level_str = "Unknown";
|
|
if ( integrity_level >= SECURITY_MANDATORY_SYSTEM_RID ) level_str = "System";
|
|
else if ( integrity_level >= SECURITY_MANDATORY_HIGH_RID ) level_str = "High";
|
|
else if ( integrity_level >= SECURITY_MANDATORY_MEDIUM_RID ) level_str = "Medium";
|
|
else if ( integrity_level >= SECURITY_MANDATORY_LOW_RID ) level_str = "Low";
|
|
else level_str = "Untrusted";
|
|
|
|
BeaconPkgBytes( (PBYTE)level_str, strlen( level_str ) );
|
|
|
|
DbgPrint("[*] Integrity Level: %s (0x%lX)\n", level_str, integrity_level);
|
|
free( integrity );
|
|
}
|
|
|
|
if ( token_user ) free( token_user );
|
|
CloseHandle( token_handle );
|
|
}
|
|
|
|
auto get_cmdline(
|
|
_In_ HANDLE process_handle
|
|
) -> void {
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG return_len = 0;
|
|
|
|
status = NtQueryInformationProcess(
|
|
process_handle, ProcessCommandLineInformation, nullptr, 0, &return_len
|
|
);
|
|
if ( return_len == 0 ) {
|
|
BeaconPrintfW( CALLBACK_ERROR, L"Failed to get command line size: (%d) %s\n", GetLastError(), fmt_error( GetLastError() ) );
|
|
return;
|
|
}
|
|
|
|
auto cmdline = (PUNICODE_STRING)malloc( return_len );
|
|
if ( ! cmdline ) {
|
|
return;
|
|
}
|
|
|
|
status = NtQueryInformationProcess(
|
|
process_handle, ProcessCommandLineInformation, cmdline, return_len, nullptr
|
|
);
|
|
if ( nt_success( status ) && cmdline->Buffer ) {
|
|
BeaconPkgBytes( (PBYTE)cmdline->Buffer, wcslen( cmdline->Buffer ) * sizeof(WCHAR) );
|
|
DbgPrint("[*] Command Line: %s\n", cmdline->Buffer);
|
|
}
|
|
|
|
free( cmdline );
|
|
}
|
|
|
|
extern "C" auto go( char* args, int argc ) -> void {
|
|
datap data_parser = { 0 };
|
|
|
|
BeaconDataParse( &data_parser, args, argc );
|
|
|
|
HANDLE process_handle = nullptr;
|
|
ULONG target_process = BeaconDataInt( &data_parser );
|
|
|
|
BOOL modules = BeaconDataInt( &data_parser );
|
|
BOOL protection = BeaconDataInt( &data_parser );
|
|
BOOL tokens = BeaconDataInt( &data_parser );
|
|
BOOL policy = BeaconDataInt( &data_parser );
|
|
BOOL threads = BeaconDataInt( &data_parser );
|
|
BOOL callbacks = BeaconDataInt( &data_parser );
|
|
BOOL cmdline = BeaconDataInt( &data_parser );
|
|
BOOL handles = BeaconDataInt( &data_parser );
|
|
BOOL arch = BeaconDataInt( &data_parser );
|
|
BOOL parentid = BeaconDataInt( &data_parser );
|
|
BOOL processid = BeaconDataInt( &data_parser );
|
|
|
|
process_handle = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, target_process );
|
|
if ( ! process_handle || process_handle == INVALID_HANDLE_VALUE ) {
|
|
return;
|
|
}
|
|
|
|
BASICEX_FLAGS basicex = { 0 };
|
|
|
|
basicex.Flags = (arch & 0xFF) | ((parentid & 0xFF) << 8) | ((processid & 0xFF) << 16) | ((protection & 0xFF) << 24);
|
|
|
|
if ( processid || parentid || protection ) get_basicex( process_handle, basicex );
|
|
|
|
if ( modules ) get_modules( process_handle );
|
|
if ( tokens ) get_tokens( process_handle );
|
|
if ( handles ) get_handles( process_handle );
|
|
if ( threads ) get_threads( processid );
|
|
if ( cmdline ) get_cmdline( process_handle );
|
|
if ( callbacks ) get_instcallbacks( process_handle );
|
|
|
|
return;
|
|
}
|