欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]GetActiveProcessLinksOffset.C

[原创]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

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;
}

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功