基于ring0层的内存搜索,实现枚举线程.
代码的既乱又烂
,将就下~_~.
原理是枚举_ethread
vs2008 + ddkwizard写的
extern "C"
{
#include <ntddk.h>
}
#define OBJECT_HEADER_SIZE 0x018
#define OBJECT_HEADER_TYPE_OFFSET 0x008
#define ETHREAD_CID_OFFSET 0x1ec
#define ETHREAD_STARTADDRESS_OFFSET 0x224
#define ETHRAED_KTHREAD_OFFSET 0x000
#define KTHREAD_TEB_OFFSET 0x020
#define ETHREAD_EXITTIME_OFFSET 0x1c8
PETHREAD pEThread;
PEPROCESS pSystem;
ULONG ThreadType;
ULONG uThreadCount;
ULONG ThreadMaxAddr;
VOID Unload(IN PDRIVER_OBJECT DriverObject)
{
KdPrint(("Driver Unload!\n"));
}
ULONG GetThreadType()
{
KdPrint(("GetThreadType!\n"));
ULONG ThreadType;
ThreadType = *(PULONG)((ULONG)pEThread - OBJECT_HEADER_SIZE + OBJECT_HEADER_TYPE_OFFSET);
return ThreadType;
}
BOOLEAN IsThreadType(IN ULONG i)
{
if(!MmIsAddressValid((PVOID)i))
{
return FALSE;
}
ULONG objectaddress = i - KTHREAD_TEB_OFFSET - ETHRAED_KTHREAD_OFFSET - OBJECT_HEADER_SIZE +OBJECT_HEADER_TYPE_OFFSET;
if(MmIsAddressValid((PVOID)objectaddress))
{
if(*(PULONG)objectaddress == ThreadType)
{
return TRUE;
}
}
return FALSE;
}
VOID ShowThread(IN ULONG i, IN ULONG pid)
{
/*PLARGE_INTEGER ExitTime;
ExitTime = (PLARGE_INTEGER)(i + ETHREAD_EXITTIME_OFFSET);
if(ExitTime->QuadPart == 0)
{
return;
}*/
CLIENT_ID cid;
ULONG teb;
ULONG address;
address = *(PULONG)(i + ETHREAD_STARTADDRESS_OFFSET);
cid.UniqueProcess = *(PHANDLE)((ULONG)i + ETHREAD_CID_OFFSET);
cid.UniqueThread = *(PHANDLE)((ULONG)i+ ETHREAD_CID_OFFSET + 4);
teb = *(PULONG)(i + ETHRAED_KTHREAD_OFFSET + KTHREAD_TEB_OFFSET);
if((ULONG)cid.UniqueProcess != pid)
{
return ;
}
KdPrint(("address of ethread:0x%x\n", i));
KdPrint(("thread addr:0x%x, tid:%5d, pid:0x%x, teb:0x%x\n", address, (ULONG)cid.UniqueThread, (ULONG)cid.UniqueProcess, teb));
uThreadCount++;
}
// 需要列举线程的进程pid
VOID EnumThread(IN ULONG pid)
{
KdPrint(("Enum thread!\n"));
ULONG teb;
for(ULONG i = 0x80000000; i < (ULONG)ThreadMaxAddr; i += 4)
{
if(MmIsAddressValid((PVOID)i)) // 内存判定这块也不太熟
先填上再说了.
{
if((0x817f0020) == i)
{
KdPrint(("address valid\n\n\n\n"));
}
teb = *(PULONG)i;
if((teb & 0xfff00fff) == 0x7ff00000 || teb == 0) // teb的地址前3个要么7ff,要么全0
{
if(IsThreadType(i))
{
ShowThread(i - KTHREAD_TEB_OFFSET - ETHRAED_KTHREAD_OFFSET, pid);
}
}
}
}
KdPrint(("Enum thread leave!\n"));
}
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
uThreadCount = 0;
pEThread = PsGetCurrentThread();
CLIENT_ID cid;
ULONG address;
/*if(pEThread != NULL)
{
address = *(PULONG)((ULONG)pEThread + ETHREAD_STARTADDRESS_OFFSET);
cid.UniqueProcess = *(PHANDLE)((ULONG)pEThread + ETHREAD_CID_OFFSET);
cid.UniqueThread = *(PHANDLE)((ULONG)pEThread + ETHREAD_CID_OFFSET + 4);
KdPrint(("pEThread : 0x%x, tid: 0x%x, address : 0x%x\n",(ULONG)pEThread, (ULONG)cid.UniqueThread, address));
}*/
pSystem = PsGetCurrentProcess();
ThreadMaxAddr = (ULONG)pSystem; // 不管了,先把system进程地址当成线程地址最大值了
ThreadType = GetThreadType();
KdPrint(("Thread type: 0x%x\n", ThreadType));
EnumThread(1480); // 我这里vmware上的explorer.exe的pid.每次都手动填,将就下吧...
KdPrint(("Total thread: %4d\n", uThreadCount));
DriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
}
在vmware上,通过pspcidtable查system的 _eprocess的地址为817bd830.
列举别的进程中的线程还好,列举system的线程发现会漏掉线程,结果发现线程的最大地址比system进程_eprocess的地址还大(就是线程地址大于817bd830).不知道线程地址最大值应该填什么好?
MmIsAddressValid 判断的太少了
其实MmIsAddressValid的判断只有参考价值
只要不上锁,虚拟地址空间随时可以改变
if(*(PULONG)objectaddress == ThreadType)
{
return TRUE;
}
这个判断太脆弱了。。。
![恐怖!](https://www.cnblogs.com/sky-wind/admin/images/smilies/eek.gif)
原理是枚举_ethread
vs2008 + ddkwizard写的
extern "C"
{
#include <ntddk.h>
}
#define OBJECT_HEADER_SIZE 0x018
#define OBJECT_HEADER_TYPE_OFFSET 0x008
#define ETHREAD_CID_OFFSET 0x1ec
#define ETHREAD_STARTADDRESS_OFFSET 0x224
#define ETHRAED_KTHREAD_OFFSET 0x000
#define KTHREAD_TEB_OFFSET 0x020
#define ETHREAD_EXITTIME_OFFSET 0x1c8
PETHREAD pEThread;
PEPROCESS pSystem;
ULONG ThreadType;
ULONG uThreadCount;
ULONG ThreadMaxAddr;
VOID Unload(IN PDRIVER_OBJECT DriverObject)
{
KdPrint(("Driver Unload!\n"));
}
ULONG GetThreadType()
{
KdPrint(("GetThreadType!\n"));
ULONG ThreadType;
ThreadType = *(PULONG)((ULONG)pEThread - OBJECT_HEADER_SIZE + OBJECT_HEADER_TYPE_OFFSET);
return ThreadType;
}
BOOLEAN IsThreadType(IN ULONG i)
{
if(!MmIsAddressValid((PVOID)i))
{
return FALSE;
}
ULONG objectaddress = i - KTHREAD_TEB_OFFSET - ETHRAED_KTHREAD_OFFSET - OBJECT_HEADER_SIZE +OBJECT_HEADER_TYPE_OFFSET;
if(MmIsAddressValid((PVOID)objectaddress))
{
if(*(PULONG)objectaddress == ThreadType)
{
return TRUE;
}
}
return FALSE;
}
VOID ShowThread(IN ULONG i, IN ULONG pid)
{
/*PLARGE_INTEGER ExitTime;
ExitTime = (PLARGE_INTEGER)(i + ETHREAD_EXITTIME_OFFSET);
if(ExitTime->QuadPart == 0)
{
return;
}*/
CLIENT_ID cid;
ULONG teb;
ULONG address;
address = *(PULONG)(i + ETHREAD_STARTADDRESS_OFFSET);
cid.UniqueProcess = *(PHANDLE)((ULONG)i + ETHREAD_CID_OFFSET);
cid.UniqueThread = *(PHANDLE)((ULONG)i+ ETHREAD_CID_OFFSET + 4);
teb = *(PULONG)(i + ETHRAED_KTHREAD_OFFSET + KTHREAD_TEB_OFFSET);
if((ULONG)cid.UniqueProcess != pid)
{
return ;
}
KdPrint(("address of ethread:0x%x\n", i));
KdPrint(("thread addr:0x%x, tid:%5d, pid:0x%x, teb:0x%x\n", address, (ULONG)cid.UniqueThread, (ULONG)cid.UniqueProcess, teb));
uThreadCount++;
}
// 需要列举线程的进程pid
VOID EnumThread(IN ULONG pid)
{
KdPrint(("Enum thread!\n"));
ULONG teb;
for(ULONG i = 0x80000000; i < (ULONG)ThreadMaxAddr; i += 4)
{
if(MmIsAddressValid((PVOID)i)) // 内存判定这块也不太熟
![恐怖!](https://www.cnblogs.com/sky-wind/admin/images/smilies/eek.gif)
{
if((0x817f0020) == i)
{
KdPrint(("address valid\n\n\n\n"));
}
teb = *(PULONG)i;
if((teb & 0xfff00fff) == 0x7ff00000 || teb == 0) // teb的地址前3个要么7ff,要么全0
{
if(IsThreadType(i))
{
ShowThread(i - KTHREAD_TEB_OFFSET - ETHRAED_KTHREAD_OFFSET, pid);
}
}
}
}
KdPrint(("Enum thread leave!\n"));
}
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
uThreadCount = 0;
pEThread = PsGetCurrentThread();
CLIENT_ID cid;
ULONG address;
/*if(pEThread != NULL)
{
address = *(PULONG)((ULONG)pEThread + ETHREAD_STARTADDRESS_OFFSET);
cid.UniqueProcess = *(PHANDLE)((ULONG)pEThread + ETHREAD_CID_OFFSET);
cid.UniqueThread = *(PHANDLE)((ULONG)pEThread + ETHREAD_CID_OFFSET + 4);
KdPrint(("pEThread : 0x%x, tid: 0x%x, address : 0x%x\n",(ULONG)pEThread, (ULONG)cid.UniqueThread, address));
}*/
pSystem = PsGetCurrentProcess();
ThreadMaxAddr = (ULONG)pSystem; // 不管了,先把system进程地址当成线程地址最大值了
ThreadType = GetThreadType();
KdPrint(("Thread type: 0x%x\n", ThreadType));
EnumThread(1480); // 我这里vmware上的explorer.exe的pid.每次都手动填,将就下吧...
KdPrint(("Total thread: %4d\n", uThreadCount));
DriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
}
在vmware上,通过pspcidtable查system的 _eprocess的地址为817bd830.
列举别的进程中的线程还好,列举system的线程发现会漏掉线程,结果发现线程的最大地址比system进程_eprocess的地址还大(就是线程地址大于817bd830).不知道线程地址最大值应该填什么好?
MmIsAddressValid 判断的太少了
其实MmIsAddressValid的判断只有参考价值
只要不上锁,虚拟地址空间随时可以改变
if(*(PULONG)objectaddress == ThreadType)
{
return TRUE;
}
这个判断太脆弱了。。。