枚举服务的一种方法

枚举服务的一种方法

Windows的服务枚举一般有使用函数EnumServicesStatus枚举和直接遍历注册表的方法.本文介绍另一种方法.
我们知道在服务管理中Services.Exe起了重要的作用.在该进程中存在一个双向的链表的结构,用来记录所有注册的服务的信息.
我们可以直接遍历这个链表以达到枚举服务的目的.

该链表的头部由ServiceDatabase符号来标明,在XPSP2下该符号的地址值为0x0101A098,在根据NT源代码(WIN2K源码没有服务相关的内容)我们知道
ServiceDatabase的类型为SERVICE_RECORD,我们根据NT源码,再结合反汇编XPSP2下的ScCreateServiceRecord函数和ScCreateImageRecord函数,
得出XPSP2下SERVICE_RECORD和IMAGE_RECORD的结构如下:

IMAGE_RECORED结构:(大小0x38:)
typedef struct _IMAGE_RECORD {
    struct _IMAGE_RECORD    *Prev;              //+0 linked list
    struct _IMAGE_RECORD    *Next;              //+4 linked list
    LPWSTR                  ImageName;          //+8 fully qualified .exe name
    DWORD                   Pid;                //+C Process ID ok.
    DWORD                   ServiceCount;       //+10 Num services running in process .
    HANDLE                  PipeHandle;         //+14 Handle to Service  .
    HANDLE                  ProcessHandle;      //+18 Handle for process .
    HANDLE                  ObjectWaitHandle;   //+1C Handle for waiting on the process.
    HANDLE                  TokenHandle;        //+20 Logon token handle.
    LUID                    Unknown1;           //+24
    HANDLE                  ProfileHandle;      //+2c User profile handle
    LPWSTR                  AccountName;        //+30 Account process was started under  !!!!!30
    DWORD                   Unknown2;           //+34
}IMAGE_RECORD, *PIMAGE_RECORD, *LPIMAGE_RECORD;

SERVICE_RECORD结构:(大小0x74)
typedef struct _SERVICE_RECORD {
    struct _SERVICE_RECORD  *Prev;          // +0 linked list
    struct _SERVICE_RECORD  *Next;          // +4 linked list
    LPWSTR                  ServiceName;    // +8 points to service name
    LPWSTR                  DisplayName;    // +C points to display name
    DWORD                   ResumeNum;      // +10 Ordered number for this rec
    DWORD                   ServerAnnounce; // +14 Server announcement bit flags
    DWORD                   Signature;      // +18 Identifies this as a service record.
    DWORD                   UseCount;       // +1C How many open handles to service
    DWORD                   StatusFlag;     // +20 status(delete,update...)
    union {
        LPIMAGE_RECORD      ImageRecord;    // +24 Points to image record
        LPWSTR              ObjectName;     // +24 Points to driver object name
    };
    SERVICE_STATUS          ServiceStatus;  // +28 see winsvc.h
    DWORD                   StartType;      // +44  AUTO, DEMAND, etc.
    DWORD                   ErrorControl;   // +48 NORMAL, SEVERE, etc.
    DWORD                   Tag;            // +4C DWORD Id for the service,0=none.
    LPDEPEND_RECORD         StartDepend;    // +50
    LPDEPEND_RECORD         StopDepend;     // +54
    LPWSTR                  Dependencies;   // +58
    PSECURITY_DESCRIPTOR    ServiceSd;      // +5C
    DWORD                   StartError;     // +60
    DWORD                   StartState;     // +64
    LPLOAD_ORDER_GROUP      MemberOfGroup;  // +68
    LPLOAD_ORDER_GROUP      RegistryGroup;  // +6C
    DWORD                   Unknown1;       // +70
} SERVICE_RECORD, *PSERVICE_RECORD, *LPSERVICE_RECORD;

知道了这两个结构,我们使用ReadProcessMemory函数读取Services.exe的内存就可以枚举所有的服务了.
如果你想隐藏什么服务的话,只要将该服务的SERVICE_RECORD结构脱离掉链表就可以,此时所有的枚举方法都没有效果了.当然该服务也不接受SCP的控制管理了.
注意:上面的ServiceDatabase的位置以及IMAGE_RECORD/SERVICE_RECORD都是在XPSP2下的情况;若在其他系统,需要自己分析.

参考文献:
1.关于隐藏服务的讨论 by shadow3
2.Reverse Engineering the Service Control Manager(SCM)
3.hooking the service manager with hacker defender.

你可能感兴趣的:(image,struct,manager,service,dependencies,Descriptor)