如何在驱动程序(sys)中得到当前进程的完整路径和进程名?

学习雨盾的源码,看到了在驱动程序中得到当前进程的完整路径和进程名的代码,网上搜了一下,文档不少,学习。。。

《摘自http://www.chinaitpower.com/A/2001-10-09/1177.html 作者:xstudio 时间:2001-10-09 10:09 出处:互联网 责编:chinaitpower

首先利用 PsGetCurrentProcess IoGetCurrentProcess 函数得到当前进程的句柄,这个句柄是指向 _EPROCESS 结构的指针, _EPROCESS 的结构如下:

typedef struct _EPROCESS

    {

    KPROCESS                     Pcb;

    NTSTATUS                     ExitStatus;

    KEVENT                       LockEvent;

    DWORD                        LockCount;

    QWORD                        CreateTime;

    QWORD                        ExitTime;

    PVOID                        LockOwner;

    DWORD                        UniqueProcessId;

    QWORD                        ActiveProcessLinks;

    DWORD                        QuotaPeakPoolUsage [2]; // NP, P

    DWORD                        QuotaPoolUsage     [2]; // NP, P

    DWORD                         PagefileUsage;

    DWORD                        CommitCharge;

    DWORD                        PeakPagefileUsage;

    DWORD                        PeakVirtualSize;

    QWORD                        VirtualSize;

    DWORD                         Vm [12];

    DWORD                        LastProtoPteFault;

    DWORD                        DebugPort;

    DWORD                        ExceptionPort;

    DWORD                        ObjectTable;

    DWORD                        Token;

    DWORD                         WorkingSetLock [8];

    DWORD                        WorkingSetPage;

    BOOLEAN                      ProcessOutswapEnabled;

    BOOLEAN                      ProcessOutswapped;

    BOOLEAN                      AddressSpaceInitialized;

     BOOLEAN                      AddressSpaceDeleted;

    DWORD                        AddressCreationLock [9];

    DWORD                        ForkInProgress;

    DWORD                        VmOperation;

    DWORD                        VmOperationEvent;

    DWORD                        PageDirectoryPte;

    QWORD                        LastFaultCount;

    PVOID                        VadRoot;

    DWORD                        VadHint;

    DWORD                        CloneRoot;

    DWORD                         NumberOfPrivatePages;

    DWORD                        NumberOfLockedPages;

    WORD                         w184;

    BOOLEAN                      ExitProcessCalled;

    BOOLEAN                      CreateProcessReported;

    HANDLE                        SectionHandle;

    struct _PEB                 *Peb;             // offset 0x1B0

    PVOID                        SectionBaseAddress;

    PVOID                        QuotaBlock;

    NTSTATUS                     LastThreadExitStatus;

    PROCESS_WS_WATCH_INFORMATION WorkingSetWatch;

    DWORD                        InheritedFromUniqueProcessId;

    ACCESS_MASK                  GrantedAccess;

    DWORD                        DefaultHardErrorProcessing;

    DWORD                        LdtInformation;

    DWORD                         VadFreeHint;

    DWORD                        VdmObjects;

    KMUTANT                      ProcessMutant;

    BYTE                         ImageFileName [16];              // offset 0x1FC

    DWORD                        VmTrimFaultValue [2];

    PVOID                        Win32Process;

    DWORD                        d1F8;

    DWORD                        d1FC;

    }

        EPROCESS,

     * PEPROCESS,

**PPEPROCESS;

 

从上面这个结构可以看出,进程名称就是 ImageFileName ,只要用 _EPROCESS 的基地址加上偏移地址 0x1FC 就可以得到进程名称的地址,代码如下:

 

char *ProcessName = (char*)PsGetCurrentProcess() + 0x1FC;

KdPrint((“Current Process Name: %s/n”, ProcessName));

 

要得到完整路径还需要利用 _EPROCESS 结构中的 _PEB 结构指针来得到 ProcessParameters 的地址。 ProcessParameters 保存着进程的完整路径。可以通过 DDK 附带的 WinDbg 工具打开一个可执行程序,然后用 !peb 命令来显示 _PEB 的结构信息。如下所示:

 

———————————————————————————————————————

> !peb

Debugger extension library [F:/WINNT/system32/ntsdexts] loaded

PEB at 7FFDF000

    InheritedAddressSpace:    No

    ReadImageFileExecOptions: No

    BeingDebugged:            Yes

    ImageBaseAddress:         00400000

    Ldr.Initialized: Yes

    Ldr.InInitializationOrderModuleList: 131f88 . 132998

    Ldr.InLoadOrderModuleList: 131ee0 . 132988

    Ldr.InMemoryOrderModuleList: 131ee8 . 132990

        00400000 D:/NtSysInfo.exe

        77F80000 F:/WINNT/System32/ntdll.dll

        77E60000 F:/WINNT/system32/KERNEL32.dll

        77DF0000 F:/WINNT/system32/USER32.dll

        77F40000 F:/WINNT/system32/GDI32.DLL

        76AF0000 F:/WINNT/system32/comdlg32.dll

        70BD0000 F:/WINNT/system32/SHLWAPI.DLL

        77D90000 F:/WINNT/system32/ADVAPI32.dll

        77D20000 F:/WINNT/system32/RPCRT4.DLL

        71700000 F:/WINNT/system32/COMCTL32.DLL

        77560000 F:/WINNT/system32/SHELL32.DLL

         78000000 F:/WINNT/system32/MSVCRT.DLL

        777C0000 F:/WINNT/System32/WINSPOOL.DRV

    SubSystemData:     0

    ProcessHeap:       130000

    ProcessParameters: 20000

        WindowTitle:  'D:/NtSysInfo.exe'

        ImageFile:    'D:/NtSysInfo.exe'

        CommandLine:  '"D:/NtSysInfo.exe" '

        DllPath:      'D:/;.;F:/WINNT/System32;F:/WINNT/system;F:/WINNT;F:/WINNT/system32;F:/WINNT;F:/WINNT/System32/Wbem;J:/WINDOWS;J:/WINDOWS/COMMAND;E:/WINDOWS/SYSTEM/WBEM;J:/WINDOWS;J:/WINDOWS/COMMAND;E:/WINDOWS/SYSTEM/WBEM;J:/WINDOWS;J:/WINDOWS/

COMMAND'


        Environment:  0x10000

 

WinDbg 输出的 PEB 结构信息可以看出 ProcessParameters 的地址为 0x20000 ImageFile 字段就是进程的完整路径。那么 PorcessParamters 的地址又保存在 _PEB 结构的什么地方呢? _PEB 结构的基地址为 0x7ffdf000 ,通过 WinDbg 的“ db 0x7ffdf000 命令显示 0x7ffdf000 地址的信息可以发现 ProcessParameters 的地址保存在 _PEB 结构的 0x10 偏移量处,内容为 0x20000

继续用“ db 0x20000 ”命令显示 ProcessParameters 地址的内容,偏移量为 0x3C 处保存完整路径的地址, 0x3C 处的内容如果是: 0x20670 ,利用“ db 0x20670 ”即可显示出完整路径。完整路径用 UNICODE 格式保存。

我们利用程序模拟上面的步骤则可以得到当前进程的完整路径,代码如下:

PCWSTR GetCurrentProcessFileName()

{

       DWORD dwAddress = (DWORD)PsGetCurrentProcess();

       if(dwAddress == 0 || dwAddress == 0xFFFFFFFF)

              return NULL;

       dwAddress += 0x1B0;

       if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;

       dwAddress += 0x10;

       if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;

       dwAddress += 0x3C;

       if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;

       KdPrint((“Current Process Full Path Name: %ws/n”,  (PCWSTR)dwAddress));

       return (PCWSTR)dwAddress;

}  

Windows NT Windows 2000 _EPROCESS 结构略有不同,所以偏移地址也不相同,故此上面的程序不能正常运行于 Windows NT 。要想在 Windows NT 下获得进程名和完整路径可以用类似的方法得出正确的偏移地址,进而编写出正确的程序。

在Linux系统,uevent是用户空间事件的简称,当设备状态发生变化时,例如热插拔事件,内核会向用户空间发送uevent。编写程序来监听和处理uevent通常涉及以下几个步骤: 1. 使用netlink socket:uevent信息通过netlink socket发送到用户空间,因此程序需要创建一个netlink socket,并绑定到适当的内核地址(PF_NETLINK)和多播组(NETLINK_KOBJECT_UEVENT)。 2. 实现uevent处理逻辑:程序需要有一个循环来监听socket上的消息。每当有新的uevent发生时,内核会向该netlink socket发送消息。 3. 解析uevent消息:接收到的uevent消息是一个字符串列表,通常包含设备的环境变量格式的信息,如ACTION(事件类型),DEVPATH(设备路径),SUBSYSTEM(子系统)等。程序需要解析这些信息以获得所需的数据。 4. 执行响应操作:根据解析出的信息,程序可以执行一些预定义的操作,比如加载驱动、记录日志等。 以下是一个简化的C语言伪代码示例,展示了如何设置netlink socket并准备接收uevent: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <linux/netlink.h> #include <libgen.h> // dirname函数的头文件 #define NETLINK_USER 31 #define BUFFER_SIZE 1024 int main() { struct sockaddr_nl src_addr, dest_addr; struct nlmsghdr *nlh = NULL; struct iovec iov; int sock_fd, result, bytes_sent; // 创建netlink socket sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER); if (sock_fd < 0) { perror("socket"); return 1; } memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); // 自己的进程ID // 绑定socket到本进程 if (bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0) { perror("bind"); return 2; } memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0; // 对端的pid(内核) dest_addr.nl_groups = 1; // 多播组 // 构建消息 nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(BUFFER_SIZE)); memset(nlh, 0, NLMSG_SPACE(BUFFER_SIZE)); nlh->nlmsg_len = NLMSG_SPACE(BUFFER_SIZE); nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = 0; // 设置消息头 ((struct nlmsghdr *)nlh)->nlmsg_type = NLMSG_DONE; ((struct nlmsghdr *)nlh)->nlmsg_flags = 0; // 填充iov iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; // 发送消息 result = sendmsg(sock_fd, &iov, 0); if (result < 0) { perror("sendmsg"); return 3; } // 接收响应 bytes_sent = recv(sock_fd, nlh, BUFFER_SIZE, 0); if (bytes_sent < 0) { perror("recv"); return 4; } // 处理接收到的uevent数据... close(sock_fd); free(nlh); return 0; } ``` 注意,这个示例仅仅是一个起点,实际应用需要更多的错误处理和特定的uevent事件处理逻辑。此外,监听uevent通常还需要设置socket的权限,以及正确处理多播组等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值