[原创]GetActiveProcessLinksOffset.C
发表于:
2013-5-4 21:04
8279
[原创]GetActiveProcessLinksOffset.C
/*
这是去年写的代码,在:
windows server 2003 32位
windows server 2008 32位和64位
windows xp 32位
windows 7 32位和64位
windows 8 64位
windows server 2012 64位
测试通过。
vista等没有测试!
本人c语言不好,如大家发现问题请指正。
这篇文件本想命名为PsActiveProcessHead.C的,改名为:GetActiveProcessLinksOffset.C吧!
PsActiveProcessHead 内核没有导出这个变量,微软更没有公开,只在一个结构及一些函数中用到了。
定义在:_KDDEBUGGER_DATA64,_KDDEBUGGER_DATA32结构。
#define DEBUG_DATA_PsActiveProcessHeadAddr 80
ULONG64
ExtNtOsInformation::GetKernelProcessListHead(void)
{
return GetNtDebuggerData(DEBUG_DATA_PsActiveProcessHeadAddr,"nt!PsActiveProcessHead",0);
}
以上定义在:engextcpp.cpp,wdbgexts.h,dbgeng.h,WDBGEXTS.H中。
以前觉得能操作内核结构,如:e(k)process,就是牛屄的高手。
慢慢发现这是硬编码,不通用。
后来感觉应该听微软的话,不公开就不用,用操作之的函数,或者别的理论。
但是有时后必须用之,这是下下策。
以前也见过获取eprocees中ActiveProcessLinks成员的偏移量的。
受之启发,几个月后有了自己的思路(方法),有了此文。
此文是获取eprocees中ActiveProcessLinks成员的偏移量的两个办法(函数),力求各个Windows的版本通用,包括32位与64位的。
方法一是:检测ActiveProcessLinks处的有效性,变化之后可得到eprocess,然后检查。
方法二是:通过两个特定进程的关系,如:idle和system,但是idle的eprocess的获取需要汇编,所以放弃。
system的eprocess的下一个ActiveProcessLinks一般是smss.exe(第一个进程,应该也只用一个)。
然后比较特定的值,如地址(本办法使用),或者名字等。
本文编译有几个Warnings,正式使用,请去掉。
made by correy
made at 2013.01.20
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
#include <ntifs.h>
#include <wdm.h>
extern PEPROCESS PsInitialSystemProcess;
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
}
int GetPsActiveProcessHead1()
{
unsigned int x = 0;
HANDLE h,h2;
EPROCESS tem_PEPROCESS;
NTSTATUS r;
PEPROCESS CurrentProcess = PsGetCurrentProcess();//用当前的吧!
int b;
int n = 0;
KIRQL OldIrql;
#ifdef _X86_
unsigned int y;
#endif
#if defined(_AMD64_) || defined(_IA64_)
unsigned __int64 y;
#endif
//代码开始
KeRaiseIrql(APC_LEVEL, &OldIrql);
for (x = 8; x<10000; x +=8) //经验所得是8的倍数。eproceess的结构大小不会超过10000。
{
y =
#ifdef _X86_
(unsigned int)
#endif
#if defined(_AMD64_) || defined(_IA64_)
(unsigned __int64)
#endif
CurrentProcess + x;
y =
#ifdef _X86_
*(unsigned int *)
#endif
#if defined(_AMD64_) || defined(_IA64_)
*(unsigned __int64 *)
#endif
y;
y -= x;
__try
{
//#ifdef _X86_
// ProbeForRead(y, sizeof (unsigned int), sizeof (unsigned int)); //IRQL <= APC_LEVEL
//#endif
//#if defined(_AMD64_) || defined(_IA64_)
// ProbeForRead(y, sizeof (unsigned __int64), sizeof (unsigned __int64));
//#endif
//必须用MmIsAddressValid,尽管微软已经不建议使用。因为ProbeForRead只检测用户称的。注意IRQL <= APC_LEVEL
if (!MmIsAddressValid(y))
{
continue;
}
h = PsGetProcessId(y);//这家伙不检查错误,返回正确不?用异常。
}
__except (1)
{
continue;
}
b = (int)h%4;
if (8 >= h || h >10000 || b != 0)
{
continue;
}
r = PsLookupProcessByProcessId(h,&tem_PEPROCESS);
h2 = PsGetProcessId(y);//这个条件还加不加,多余?
if (r != STATUS_INVALID_PARAMETER && h == h2) // && 不再加附加的验证条件了。
{
DbgPrint("0x%x\n", x);
ObDereferenceObject(tem_PEPROCESS);//必须调用,在某些情况下会死锁,建议使用ObReferenceObjectByHandle
#ifdef _X86_
KeLowerIrql(OldIrql);
return x;
#endif
#if defined(_AMD64_) || defined(_IA64_)
n++;
if (n == 2) //第一个是kprocess的ProcessListEntry。
{
KeLowerIrql(OldIrql);
return x;
}
#endif
}
}
KeLowerIrql(OldIrql);
return -1;//失败返回-1.应该不会返回这里。
}
extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); //c++ 才需要"C"
HANDLE GetPidFromProcessName(char * ProcessName)
{
PEPROCESS Process;
int h;
CHAR * pName;
STRING s1,s2;
KIRQL OldIrql;
KeRaiseIrql(APC_LEVEL, &OldIrql);
for (h = 0; h < 100000; h += 4) //由于PEPROCESS结构不公开,不采用遍历的办法,反而更通用。
{
if (PsLookupProcessByProcessId((HANDLE)h, & Process) != STATUS_INVALID_PARAMETER)
{
pName = (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。
//如果pName不可以访问,请退出,不然蓝屏。 解决办法是下面加异常处理
__try
{
if (!MmIsAddressValid(pName))
{
continue;
}
RtlInitString(&s1, pName);
RtlInitString(&s2, ProcessName);
}
__except (1)
{
continue;
}
//ObDereferenceObject(Process);//加这一行蓝屏。
if (RtlEqualString(&s1, &s2, 1))
{
DbgPrint("pid == %08d\n",h);
KeLowerIrql(OldIrql);
return (HANDLE)h;
}
}
}
KeLowerIrql(OldIrql);
return (HANDLE)-1;
}
int GetPsActiveProcessHead2()
{
unsigned int x = 0;
PEPROCESS system_eprocess,smss_eprocess;
int b;
int n = 0;
HANDLE h_system,h_smss;
#ifdef _X86_
unsigned int y;
#endif
#if defined(_AMD64_) || defined(_IA64_)
unsigned __int64 y;
#endif
//代码开始
h_system = GetPidFromProcessName("system");
h_smss = GetPidFromProcessName("smss.exe");
if (h_system == -1 || h_smss == -1)
{
return -1;
}
if (PsLookupProcessByProcessId(h_system, & system_eprocess) == STATUS_INVALID_PARAMETER ||
PsLookupProcessByProcessId(h_smss, & smss_eprocess) == STATUS_INVALID_PARAMETER)
{
return -1;
}
for (x = 8; x<10000; x +=8) //经验所得是8的倍数。eproceess的结构大小不会超过10000。
{
__try
{
y =
#ifdef _X86_
(unsigned int)
#endif
#if defined(_AMD64_) || defined(_IA64_)
(unsigned __int64)
#endif
system_eprocess + x;
y =
#ifdef _X86_
*(unsigned int *)
#endif
#if defined(_AMD64_) || defined(_IA64_)
*(unsigned __int64 *)
#endif
y; //主要是看这里的内容可以访问不?其实这里没有问题。
y -= x;
if (y == smss_eprocess)
{
DbgPrint("0x%x\n", x);
#ifdef _X86_
return x;
#endif
#if defined(_AMD64_) || defined(_IA64_)
n++;
if (n == 2) //第一个是kprocess的ProcessListEntry。
{
return x;
}
#endif
}
}
__except (1)
{
continue;
}
}
ObDereferenceObject(system_eprocess);
ObDereferenceObject(smss_eprocess);
return -1;//失败返回-1.应该不会返回这里。
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
unsigned __int64 PsActiveProcessHead = 0;
unsigned __int64 t;
PEPROCESS Process; //看看和t相等不?
KSPIN_LOCK SpinLock;
KIRQL OldIrql;
KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = Unload;
PsLookupProcessByProcessId(4, & Process);
t = PsInitialSystemProcess;//断定这个是错误的,和Process不一样,进程的名字为空。
//DbgPrint("PsInitialSystemProcess == 0x%16x\n", PsInitialSystemProcess);
//KeInitializeSpinLock(&SpinLock);//里面用KeRaiseIrql,这里就不用了。
//KeAcquireSpinLock(&SpinLock, &OldIrql);//注意锁的使用。
PsActiveProcessHead = GetPsActiveProcessHead1();
//KeReleaseSpinLock(&SpinLock, OldIrql);
DbgPrint("ActiveProcessLinks 在 eprocess中的偏移是:0x%x\n", PsActiveProcessHead);
PsActiveProcessHead = GetPsActiveProcessHead2();
DbgPrint("ActiveProcessLinks 在 eprocess中的偏移是:0x%x\n", PsActiveProcessHead);
return 0;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!