登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 356|回复: 0

WindowsX86内核11.操作进程内存

[复制链接]

171

主题

21

回帖

1048

积分

管理员

积分
1048
发表于 2024-12-12 12:06:43 | 显示全部楼层 |阅读模式
我们研究内存管理最终目的是操作进程内存和代码注入
操作进程内存
●在3环里面操作进程的函数是 ReadPricessMemory WriteProcessMemory但是用这些函数很容易被检测出来,但是如果通过操作物理内存的方式,那么就不容易检测
●因此我们要知道如何操作对方的物理内存,如我们能得到对方进程的页目录表就可以了,他的地址是物理地址
●页目录表是由操作系统管理,从数据结构来讲他属于进程中的一个属性,每个进程有一个页目录表,所以我们要知道每个进程的页目录表,我们要知道操作系统如何管理进程的
●如果逆向分析,我们可以通过加载符号来搜索相关 Swap 线程的函数
1663748644791-80158de9-268a-417e-b04a-0c89439a789b.jpg
1663748528208-68a37173-8b71-4170-9e5b-dc9895477877.jpg
●切进程就是该CR3的值,那么CR3怎么来的呢 CR3应该是是放到一个结构体 + 18偏移的位置,可以逆向追踪,可以知道来自PROCESS 结构体
●PROCESS 来自于于全局变量
●微软开源了一份内核源码 WRK,可以编译可以用,可用于2个系统(Windows Research Kernel),可以用于Windows2003 和 xp 64位 2个系统,这份源码可以帮助我们研究内核,但是不是完整的,大部分核心代码都有,没有代码的他提供了obj ,下载链接 https://github.com/9176324/WRK.git ,这份源码只能做参考,因为不同的系统源码是不一样的
● 可以通过 sourceinsight 快速的查看源码
Source Insights使用教程
1新建工程
1663752312170-41411f08-b00f-47f3-a491-9f4a03f37a00.jpg
2选择源文件
1663752430290-d3902d77-5907-454d-a6f8-2848ae91fc57.jpg
3添加文件
1663752507989-1731445e-b1f4-4825-a1a7-d97dc9407b46.jpg
1663752780917-7c5933ef-01b9-4508-994f-38285a8333f2.jpg
  • 弄好了之后保存工程在查看符号,这样就可以搜索查看函数源码了
1663752917205-4c521fe5-590e-497b-bd5f-1313a0dd8492.jpg
●例如查看 函数 MilsAddressValid
1663753202985-fffa78d6-af65-451e-8e5e-df2ee4852c5c.jpg
1663753221029-bdf11c1d-1db6-43b9-8daa-d846f259769e.jpg
1663753232090-5923b8ed-881a-4603-b1f8-873d533a6a34.jpg
重要节结构体
结构体不同的版本是不一样的,因为这个结构体是非公开的,在windbg 中可以通过 dt _eprocess 来查看结构体信息,新版本包含老版本的结构体
进程对象 EPROCESS (执行层)
内核分为核心层和执行层
<span class="hljs-keyword" style="box-sizing: border-box; display: inline; overflow: visible; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; text-size-adjust: none; border-radius: 6px; border: 0px; word-break: normal; line-height: inherit; overflow-wrap: normal;">typedef</span><span style="box-sizing: border-box; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; text-size-adjust: none; border-radius: 6px; border-style: initial; border-color: initial; border-image: initial; line-height: inherit; overflow-wrap: normal;"> </span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> _<span class="hljs-title" style="box-sizing: border-box;">EPROCESS</span>
 {</span>
    KPROCESS Pcb;
    EX_PUSH_LOCK ProcessLock;      <span class="hljs-comment" style="box-sizing: border-box;">//EPROCESS成员保护锁(推锁)</span>
    LARGE_INTEGER CreateTime;      <span class="hljs-comment" style="box-sizing: border-box;">//进程创建时间</span>
    LARGE_INTEGER ExitTime;        <span class="hljs-comment" style="box-sizing: border-box;">//进程退出时间</span>
    EX_RUNDOWN_REF RundownProtect; <span class="hljs-comment" style="box-sizing: border-box;">//进程结束保护锁</span>
    HANDLE UniqueProcessId;        <span class="hljs-comment" style="box-sizing: border-box;">//进程ID</span>
    LIST_ENTRY ActiveProcessLinks; <span class="hljs-comment" style="box-sizing: border-box;">//系统所有进程链表,可遍历所有进程</span>
    SIZE_T QuotaUsage[PsQuotaTypes];  <span class="hljs-comment" style="box-sizing: border-box;">//进程内存使用量(数组:分页内存池,非分页内存池,文件内存)</span>
    SIZE_T QuotaPeak[PsQuotaTypes];   <span class="hljs-comment" style="box-sizing: border-box;">//进程内存巅峰使用量(数组:分页内存池,非分页内存池,文件内存)</span>
    SIZE_T CommitCharge;              <span class="hljs-comment" style="box-sizing: border-box;">//虚拟内存已提交的页面数量</span>
    SIZE_T PeakVirtualSize;           <span class="hljs-comment" style="box-sizing: border-box;">//进程虚拟内存大小巅峰值</span>
    SIZE_T VirtualSize;               <span class="hljs-comment" style="box-sizing: border-box;">//进程虚拟内存大小</span>
    LIST_ENTRY SessionProcessLinks;
    PVOID DebugPort;                 <span class="hljs-comment" style="box-sizing: border-box;">//调试端口</span>
    PVOID ExceptionPort;             <span class="hljs-comment" style="box-sizing: border-box;">//异常端口 </span>
    PHANDLE_TABLE ObjectTable;       <span class="hljs-comment" style="box-sizing: border-box;">//进程所有对象句柄表</span>
    EX_FAST_REF Token;               <span class="hljs-comment" style="box-sizing: border-box;">//令牌(病毒,漏洞)</span>
    PFN_NUMBER WorkingSetPage;       <span class="hljs-comment" style="box-sizing: border-box;">//进程工作集页面</span>
    KGUARDED_MUTEX AddressCreationLock;
    KSPIN_LOCK HyperSpaceLock;
    <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> _<span class="hljs-title" style="box-sizing: border-box;">ETHREAD</span> *<span class="hljs-title" style="box-sizing: border-box;">ForkInProgress</span>;</span>  <span class="hljs-comment" style="box-sizing: border-box;">//正在复制物理地址空间的哪个线程</span>
    ULONG_PTR HardwareTrigger;        <span class="hljs-comment" style="box-sizing: border-box;">//记录硬件错误分析次数</span>
    PMM_AVL_TABLE PhysicalVadRoot;   <span class="hljs-comment" style="box-sizing: border-box;">//进程物理VAD树的根节点 </span>
    PVOID CloneRoot;
    PFN_NUMBER NumberOfPrivatePages;  <span class="hljs-comment" style="box-sizing: border-box;">//进程私有页数量</span>
    PFN_NUMBER NumberOfLockedPages;   <span class="hljs-comment" style="box-sizing: border-box;">//进程被锁住的页面数量</span>
    PVOID Win32Process;               <span class="hljs-comment" style="box-sizing: border-box;">//指示是否GUI进程</span>
    <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> _<span class="hljs-title" style="box-sizing: border-box;">EJOB</span> *<span class="hljs-title" style="box-sizing: border-box;">Job</span>;</span>
    PVOID SectionObject;             <span class="hljs-comment" style="box-sizing: border-box;">//进程内存区对象</span>
    PVOID SectionBaseAddress;        <span class="hljs-comment" style="box-sizing: border-box;">//内存区对象基地址</span>
    PEPROCESS_QUOTA_BLOCK QuotaBlock; 
    PPAGEFAULT_HISTORY WorkingSetWatch;  <span class="hljs-comment" style="box-sizing: border-box;">//监控进程页面错误</span>
    HANDLE Win32WindowStation;
    HANDLE InheritedFromUniqueProcessId;
    PVOID LdtInformation;               <span class="hljs-comment" style="box-sizing: border-box;">//进程局部描述符</span>
    PVOID VadFreeHint;
    PVOID VdmObjects;
    PVOID DeviceMap;
    PVOID Spare0[<span class="hljs-number" style="box-sizing: border-box;">3</span>];                   <span class="hljs-comment" style="box-sizing: border-box;">//WRK未使用</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        HARDWARE_PTE PageDirectoryPte;  <span class="hljs-comment" style="box-sizing: border-box;">//页目录的页表项</span>
        ULONGLONG Filler;
    };
    PVOID Session;
    UCHAR ImageFileName[ <span class="hljs-number" style="box-sizing: border-box;">16</span> ];          <span class="hljs-comment" style="box-sizing: border-box;">//进程名称</span>
    LIST_ENTRY JobLinks;
    PVOID LockedPagesList;
    LIST_ENTRY ThreadListHead;          <span class="hljs-comment" style="box-sizing: border-box;">//进程的所有线程</span>
    PVOID SecurityPort;                 <span class="hljs-comment" style="box-sizing: border-box;">//与lsass进程跨进程通讯端口</span>
    PVOID PaeTop;                       <span class="hljs-comment" style="box-sizing: border-box;">//用于支持PAE内存访问机制</span>
    ULONG ActiveThreads;                <span class="hljs-comment" style="box-sizing: border-box;">//进程有多少个活动线程</span>
    ACCESS_MASK GrantedAccess;          <span class="hljs-comment" style="box-sizing: border-box;">//进程访问权限</span>
    ULONG DefaultHardErrorProcessing;   <span class="hljs-comment" style="box-sizing: border-box;">//默认的硬件错误处理</span>
    NTSTATUS LastThreadExitStatus;      <span class="hljs-comment" style="box-sizing: border-box;">//最后一个线程的退出状态</span>
    PPEB Peb;                           <span class="hljs-comment" style="box-sizing: border-box;">//进程环境块</span>
    EX_FAST_REF PrefetchTrace;
    LARGE_INTEGER ReadOperationCount;
    LARGE_INTEGER WriteOperationCount;
    LARGE_INTEGER OtherOperationCount;
    LARGE_INTEGER ReadTransferCount;
    LARGE_INTEGER WriteTransferCount;
    LARGE_INTEGER OtherTransferCount;
    SIZE_T CommitChargeLimit;
    SIZE_T CommitChargePeak;
    PVOID AweInfo;
    SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo;  <span class="hljs-comment" style="box-sizing: border-box;">//进程映像全路径名</span>
    MMSUPPORT Vm;
    ULONG Spares[<span class="hljs-number" style="box-sizing: border-box;">2</span>];
    ULONG ModifiedPageCount;   <span class="hljs-comment" style="box-sizing: border-box;">//进程已修改页面的数量</span>
    ULONG JobStatus;
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        ULONG Flags;
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            ULONG CreateReported            : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG NoDebugInherit            : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG ProcessExiting            : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG ProcessDelete             : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG Wow64SplitPages           : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG VmDeleted                 : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG OutswapEnabled            : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG Outswapped                : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG ForkFailed                : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG Wow64VaSpace4Gb           : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG AddressSpaceInitialized   : <span class="hljs-number" style="box-sizing: border-box;">2</span>;
            ULONG SetTimerResolution        : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG BreakOnTermination        : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG SessionCreationUnderway   : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG WriteWatch                : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG ProcessInSession          : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG OverrideAddressSpace      : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG HasAddressSpace           : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG LaunchPrefetched          : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG InjectInpageErrors        : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG VmTopDown                 : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG ImageNotifyDone           : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG PdeUpdateNeeded           : <span class="hljs-number" style="box-sizing: border-box;">1</span>;    <span class="hljs-comment" style="box-sizing: border-box;">// NT32 only</span>
            ULONG VdmAllowed                : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG SmapAllowed               : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG CreateFailed              : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG DefaultIoPriority         : <span class="hljs-number" style="box-sizing: border-box;">3</span>;
            ULONG Spare1                    : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG Spare2                    : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
        };
    };
    NTSTATUS ExitStatus;
    USHORT NextPageColor;
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SubSystemMinorVersion;   <span class="hljs-comment" style="box-sizing: border-box;">//系统主版本号</span>
            UCHAR SubSystemMajorVersion;   <span class="hljs-comment" style="box-sizing: border-box;">//系统次版本号</span>
        };
        USHORT SubSystemVersion;
    };
    UCHAR PriorityClass;
    MM_AVL_TABLE VadRoot;    <span class="hljs-comment" style="box-sizing: border-box;">//用于管理该进程的虚拟地址空间(平衡二叉树)</span>
    ULONG Cookie;
} EPROCESS, *PEPROCESS;


  • 我们申请内存(malloc 或者 virtualAlloc),系统怎么知道哪块内存可以分配呢,内存的地址很大(4个G),怎么快速知道哪个页被分配了,哪个页没被分配,于是微软系统就做了一棵平衡二叉树,就是把所有页的分配情况做成一棵平衡二叉树,,这颗平衡二叉树里面记录了所有被分配的页,所以要分配页的时候,只要查这棵二叉树就可以快速知道存不存在,因此,我们主要遍历这个二叉树,就可以知道这个进程所有使用的内存
    • dt _eprocess
  • 1663757764443-2cc57afe-bfcb-4d1c-85e3-8ee56b5ca009-1714486640390-75.png
    • dt _MM_AVL_TABLE
    • 1663758136479-98ff77c3-fbf0-4ce1-9123-2f796d0d2c6d-1714486640390-76.png
    • dt _MMADDRESS_NODE
    • 1663758182259-06a99c84-763d-453d-8703-b164912a4213-1714486640390-77.png
  • 遍历计算器进程的内存使用情况
    • 先遍历所有进程,找到计算机的进程 !process 0 0
    • 1663758534406-215408a0-9ae7-46ec-9ac9-aa1af60cfae6-1714486640390-78.png
    • 获取计算器的进程信息,获取 VadRoot偏移 dt _eprocess 87b9ad40
    • 1663758632299-5b92dd48-3c3b-4d2d-9caf-64c036c8e1ab-1714486640390-79.png
    • 遍历二叉树 !vad 87b9ad40+0x278
    • 1663758791626-cbaa73d7-55c7-4142-a7af-8400a6e9c8b1-1714486640390-80.png
    • 1663758872119-b820e369-2ea7-4ae4-8c90-c93f865c77f9-1714486640390-81.png
    • 遍历这棵树,可以找到所有隐藏的模块 Mapped 表示文件映射 private 都是 virtulAlloc申请的

进程对象 KPROCESS (核心层)
<span class="hljs-keyword" style="box-sizing: border-box; display: inline; overflow: visible; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; text-size-adjust: none; border-radius: 6px; border: 0px; word-break: normal; line-height: inherit; overflow-wrap: normal;">typedef</span><span style="box-sizing: border-box; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; text-size-adjust: none; border-radius: 6px; border-style: initial; border-color: initial; border-image: initial; line-height: inherit; overflow-wrap: normal;"> </span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> _<span class="hljs-title" style="box-sizing: border-box;">KPROCESS</span>
{</span>
    DISPATCHER_HEADER Header;     <span class="hljs-comment" style="box-sizing: border-box;">//表明为分发器对象(同步机制)</span>
    LIST_ENTRY ProfileListHead;       <span class="hljs-comment" style="box-sizing: border-box;">//用于参与性能分析</span>
    ULONG_PTR DirectoryTableBase[<span class="hljs-number" style="box-sizing: border-box;">2</span>];  <span class="hljs-comment" style="box-sizing: border-box;">//数组,[0]为进程页目录表地址,[1]为超空间的页目录表地址</span>
    KGDTENTRY LdtDescriptor;         <span class="hljs-comment" style="box-sizing: border-box;">//局部描述符表 </span>
    KIDTENTRY Int21Descriptor;        <span class="hljs-comment" style="box-sizing: border-box;">//为了兼容dos程序, 通过int21调用dos系统功能</span>
    USHORT IopmOffset;               <span class="hljs-comment" style="box-sizing: border-box;">//制定IOPM位置,控制用户模式的IO权限</span>
    UCHAR Iopl;                       <span class="hljs-comment" style="box-sizing: border-box;">//进程的I/O优先级</span>
    BOOLEAN Unused;                   <span class="hljs-comment" style="box-sizing: border-box;">//未使用</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">volatile</span> KAFFINITY ActiveProcessors;  <span class="hljs-comment" style="box-sizing: border-box;">//当前进程在哪些处理上运行</span>
    ULONG KernelTime;                   <span class="hljs-comment" style="box-sizing: border-box;">//内核模式运行时间(有线程结束更新时间)</span>
    ULONG UserTime;                     <span class="hljs-comment" style="box-sizing: border-box;">//用户模式运行时间(有线程结束更新时间)</span>
    LIST_ENTRY ReadyListHead;          <span class="hljs-comment" style="box-sizing: border-box;">//记录了就绪但未加入全局就绪表的线程(双向链表)</span>
    SINGLE_LIST_ENTRY SwapListEntry;      <span class="hljs-comment" style="box-sizing: border-box;">//进程被换出内存使用</span>
    PVOID VdmTrapcHandler;                <span class="hljs-comment" style="box-sizing: border-box;">//指向ctrl + c中断的函数(用于虚拟dos机)</span>
    LIST_ENTRY ThreadListHead;            <span class="hljs-comment" style="box-sizing: border-box;">//当前进程的所有线程(双向循环链表)</span>
    KSPIN_LOCK ProcessLock;               <span class="hljs-comment" style="box-sizing: border-box;">//自选锁对象,保护数据成员</span>
    KAFFINITY Affinity;                   <span class="hljs-comment" style="box-sizing: border-box;">//指定进程可以在那些处理器上运行</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            LONG AutoAlignment : <span class="hljs-number" style="box-sizing: border-box;">1</span>;      <span class="hljs-comment" style="box-sizing: border-box;">//内存对其检查标志</span>
            LONG DisableBoost : <span class="hljs-number" style="box-sizing: border-box;">1</span>;       <span class="hljs-comment" style="box-sizing: border-box;">//线程优先级的提升和时限有关</span>
            LONG DisableQuantum : <span class="hljs-number" style="box-sizing: border-box;">1</span>;     <span class="hljs-comment" style="box-sizing: border-box;">//线程优先级的提升和时限有关</span>
            LONG ReservedFlags : <span class="hljs-number" style="box-sizing: border-box;">29</span>;     <span class="hljs-comment" style="box-sizing: border-box;">//保留</span>
        };
        
        LONG ProcessFlags;
    };
    SCHAR BasePriority;                 <span class="hljs-comment" style="box-sizing: border-box;">//所有线程的基本优先级</span>
    SCHAR QuantumReset;                 <span class="hljs-comment" style="box-sizing: border-box;">//所有线程的时限 (时间片)</span>
    UCHAR State;                        <span class="hljs-comment" style="box-sizing: border-box;">//进程是否在内存中</span>
    UCHAR ThreadSeed;                   <span class="hljs-comment" style="box-sizing: border-box;">//每个线程以此作为理想处理器</span>
    UCHAR PowerState;                   <span class="hljs-comment" style="box-sizing: border-box;">//电源状态</span>
    UCHAR IdealNode;                    <span class="hljs-comment" style="box-sizing: border-box;">//为一个进程选择优先的处理器节点</span>
    BOOLEAN Visited;                    <span class="hljs-comment" style="box-sizing: border-box;">//WRK未使用</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        KEXECUTE_OPTIONS Flags;
        UCHAR ExecuteOptions;          <span class="hljs-comment" style="box-sizing: border-box;">//设置进程内存的执行选项</span>
    };
    ULONG_PTR StackCount;              <span class="hljs-comment" style="box-sizing: border-box;">//多少个线程的栈在内存中</span>
    LIST_ENTRY ProcessListEntry;       <span class="hljs-comment" style="box-sizing: border-box;">//系统中所有具有活动线程的进程链表</span>
} KPROCESS, *PKPROCESS, *PRKPROCESS;


线程对象 ETHREAD (执行层)
<span class="hljs-keyword" style="box-sizing: border-box;">typedef</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> _<span class="hljs-title" style="box-sizing: border-box;">ETHREAD</span> {</span>
    KTHREAD Tcb;
    LARGE_INTEGER CreateTime;      <span class="hljs-comment" style="box-sizing: border-box;">//线程创建时间</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        LARGE_INTEGER ExitTime;    <span class="hljs-comment" style="box-sizing: border-box;">//线程退出时间</span>
        LIST_ENTRY LpcReplyChain;
        LIST_ENTRY KeyedWaitChain;
    };
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        NTSTATUS ExitStatus;    <span class="hljs-comment" style="box-sizing: border-box;">//线程退出状态</span>
        PVOID OfsChain;         <span class="hljs-comment" style="box-sizing: border-box;">//WRK未使用</span>
    };
    LIST_ENTRY PostBlockList;
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        PTERMINATION_PORT TerminationPort;
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> _<span class="hljs-title" style="box-sizing: border-box;">ETHREAD</span> *<span class="hljs-title" style="box-sizing: border-box;">ReaperLink</span>;</span>
        PVOID KeyedWaitValue;
    };
    KSPIN_LOCK ActiveTimerListLock;
    LIST_ENTRY ActiveTimerListHead;   <span class="hljs-comment" style="box-sizing: border-box;">//当前线程的所有定时器</span>
    CLIENT_ID Cid;                    <span class="hljs-comment" style="box-sizing: border-box;">//线程ID</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        KSEMAPHORE LpcReplySemaphore;
        KSEMAPHORE KeyedWaitSemaphore;
    };
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        PVOID LpcReplyMessage;          <span class="hljs-comment" style="box-sizing: border-box;">// -> Message that contains the reply</span>
        PVOID LpcWaitingOnPort;
    };
    PPS_IMPERSONATION_INFORMATION ImpersonationInfo;
    LIST_ENTRY IrpList;
    ULONG_PTR TopLevelIrp;  <span class="hljs-comment" style="box-sizing: border-box;">// either NULL, an Irp or a flag defined in FsRtl.h</span>
    <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> _<span class="hljs-title" style="box-sizing: border-box;">DEVICE_OBJECT</span> *<span class="hljs-title" style="box-sizing: border-box;">DeviceToVerify</span>;</span>
    PEPROCESS ThreadsProcess;        <span class="hljs-comment" style="box-sizing: border-box;">//当前线程所属进程</span>
    PVOID StartAddress;              <span class="hljs-comment" style="box-sizing: border-box;">//系统dll的启动地址(来自Context的EIP)</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        PVOID Win32StartAddress;     <span class="hljs-comment" style="box-sizing: border-box;">//线程回调函数地址(来自context的EAX)</span>
        ULONG LpcReceivedMessageId;
    };
    LIST_ENTRY ThreadListEntry;
    EX_RUNDOWN_REF RundownProtect;   <span class="hljs-comment" style="box-sizing: border-box;">//线程停止保护锁</span>
    EX_PUSH_LOCK ThreadLock;         <span class="hljs-comment" style="box-sizing: border-box;">//保护线程的数据成员</span>
    ULONG LpcReplyMessageId;         <span class="hljs-comment" style="box-sizing: border-box;">//当前正等待对一个消息的应答</span>
    ULONG ReadClusterSize;           <span class="hljs-comment" style="box-sizing: border-box;">//在一次I/O操作读取了多少个页面</span>
    ACCESS_MASK GrantedAccess;       <span class="hljs-comment" style="box-sizing: border-box;">//线程的访问权限</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {

        ULONG CrossThreadFlags;            <span class="hljs-comment" style="box-sizing: border-box;">//针对跨线程访问的标志</span>
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            ULONG Terminated              : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//线程已执行中止操作</span>
            ULONG DeadThread              : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//创建失败</span>
            ULONG HideFromDebugger        : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//该线程对于调试器不可见</span>
            ULONG ActiveImpersonationInfo : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG SystemThread            : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//是一个系统线程</span>
            ULONG HardErrorsAreDisabled   : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//对于该现场,硬件错误无效</span>
            ULONG BreakOnTermination      : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//调试器在线程中止时停下该线程</span>
            ULONG SkipCreationMsg         : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//不向调试器发送创建线程消息(可以用于反调试)</span>
            ULONG SkipTerminationMsg      : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//不向调试器发送线程中止消息(可以用于反调试)</span>
        };
    };
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        ULONG SameThreadPassiveFlags;
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            ULONG ActiveExWorker : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG ExWorkerCanWaitUser : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG MemoryMaker : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            ULONG KeyedEventInUse : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
        };
    };
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        ULONG SameThreadApcFlags;
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            BOOLEAN LpcReceivedMsgIdValid : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN LpcExitThreadCalled   : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN AddressSpaceOwner     : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN OwnsProcessWorkingSetExclusive  : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN OwnsProcessWorkingSetShared     : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN OwnsSystemWorkingSetExclusive   : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN OwnsSystemWorkingSetShared      : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN OwnsSessionWorkingSetExclusive  : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN OwnsSessionWorkingSetShared     : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
            BOOLEAN ApcNeeded                       : <span class="hljs-number" style="box-sizing: border-box;">1</span>;
        };
    };
    BOOLEAN ForwardClusterOnly;
    BOOLEAN DisablePageFaultClustering;
    UCHAR ActiveFaultCount;
<span class="hljs-meta" style="box-sizing: border-box;">#<span class="hljs-meta-keyword" style="box-sizing: border-box;">if</span> defined (PERF_DATA)</span>
    ULONG PerformanceCountLow;
    LONG PerformanceCountHigh;
<span class="hljs-meta" style="box-sizing: border-box;">#<span class="hljs-meta-keyword" style="box-sizing: border-box;">endif</span></span>
} ETHREAD, *PETHREAD;


线程对象 ETHREAD (核心层)
<span class="hljs-keyword" style="box-sizing: border-box;">typedef</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> _<span class="hljs-title" style="box-sizing: border-box;">KTHREAD</span> 
{</span>
    DISPATCHER_HEADER Header;       <span class="hljs-comment" style="box-sizing: border-box;">//分发器对象</span>
    LIST_ENTRY MutantListHead;      <span class="hljs-comment" style="box-sizing: border-box;">//指向该线程的互斥体对象链表</span>
    PVOID InitialStack;             <span class="hljs-comment" style="box-sizing: border-box;">//内核原始栈的位置</span>
    PVOID StackLimit;               <span class="hljs-comment" style="box-sizing: border-box;">//内核栈界限</span>
    PVOID KernelStack;              <span class="hljs-comment" style="box-sizing: border-box;">//内核栈的开始位置</span>
    KSPIN_LOCK ThreadLock;          <span class="hljs-comment" style="box-sizing: border-box;">//自旋锁,保护线程数据成员</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        KAPC_STATE ApcState;        <span class="hljs-comment" style="box-sizing: border-box;">//指向APC信息(异步过程调用,有一个队列,记录了所有的注册函数)</span>
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR ApcStateFill[KAPC_STATE_ACTUAL_LENGTH];
            BOOLEAN ApcQueueable;             <span class="hljs-comment" style="box-sizing: border-box;">//是否可以插入APC</span>
            <span class="hljs-keyword" style="box-sizing: border-box;">volatile</span> UCHAR NextProcessor;     <span class="hljs-comment" style="box-sizing: border-box;">//关于线程调度器的选择</span>
            <span class="hljs-keyword" style="box-sizing: border-box;">volatile</span> UCHAR DeferredProcessor; <span class="hljs-comment" style="box-sizing: border-box;">//关于线程调度器的选择</span>
            UCHAR AdjustReason;               <span class="hljs-comment" style="box-sizing: border-box;">//优先级调整原因</span>
            SCHAR AdjustIncrement;            <span class="hljs-comment" style="box-sizing: border-box;">//优先级调整量</span>
        };
    };
    KSPIN_LOCK ApcQueueLock;     <span class="hljs-comment" style="box-sizing: border-box;">//自旋锁,保护APC队列</span>
    ULONG ContextSwitches;       <span class="hljs-comment" style="box-sizing: border-box;">//线程进行了多少次环境切换</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">volatile</span> UCHAR State;        <span class="hljs-comment" style="box-sizing: border-box;">//线程状态</span>
    UCHAR NpxState;              <span class="hljs-comment" style="box-sizing: border-box;">//浮点寄存器状态</span>
    BOOLEAN Alertable;           <span class="hljs-comment" style="box-sizing: border-box;">//说明一个线程是否可以被唤醒</span>
    BOOLEAN WaitNext;            <span class="hljs-comment" style="box-sizing: border-box;">//线程马上要调用一个内核等待函数</span>
    UCHAR WaitReason;            <span class="hljs-comment" style="box-sizing: border-box;">//线程等待理由</span>
    SCHAR Priority;              <span class="hljs-comment" style="box-sizing: border-box;">//该线程动态优先级</span>
    UCHAR EnableStackSwap;       <span class="hljs-comment" style="box-sizing: border-box;">//本线程栈是否允许换到外存中</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">volatile</span> UCHAR SwapBusy;     <span class="hljs-comment" style="box-sizing: border-box;">//当前线程是否在切换环境中</span>
    BOOLEAN Alerted[MaximumMode];
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        LIST_ENTRY WaitListEntry;
        SINGLE_LIST_ENTRY SwapListEntry;
    };
    PRKQUEUE Queue;      <span class="hljs-comment" style="box-sizing: border-box;">//队列分发器对象</span>
    PVOID Teb;           <span class="hljs-comment" style="box-sizing: border-box;">//指向TEB,这就是3环的Teb</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        KTIMER Timer;   <span class="hljs-comment" style="box-sizing: border-box;">//线程上的定时器(超时等待)</span>
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR TimerFill[KTIMER_ACTUAL_LENGTH];
            <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
                <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
                    LONG AutoAlignment : <span class="hljs-number" style="box-sizing: border-box;">1</span>;   <span class="hljs-comment" style="box-sizing: border-box;">//参考KPROCESS</span>
                    LONG DisableBoost : <span class="hljs-number" style="box-sizing: border-box;">1</span>;     <span class="hljs-comment" style="box-sizing: border-box;">//参考KPROCESS</span>
                    LONG ReservedFlags : <span class="hljs-number" style="box-sizing: border-box;">30</span>;
                };
                LONG ThreadFlags;
            };
        };
    };
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        KWAIT_BLOCK WaitBlock[THREAD_WAIT_OBJECTS + <span class="hljs-number" style="box-sizing: border-box;">1</span>];  <span class="hljs-comment" style="box-sizing: border-box;">//第4项用于可等待的定时器对象</span>
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR WaitBlockFill0[KWAIT_BLOCK_OFFSET_TO_BYTE0];
            BOOLEAN SystemAffinityActive;
        };
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR WaitBlockFill1[KWAIT_BLOCK_OFFSET_TO_BYTE1];
            CCHAR PreviousMode;
        };
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR WaitBlockFill2[KWAIT_BLOCK_OFFSET_TO_BYTE2];
            UCHAR ResourceIndex;
        };
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR WaitBlockFill3[KWAIT_BLOCK_OFFSET_TO_BYTE3];
            UCHAR LargeStack;
        };
    };
    LIST_ENTRY QueueListEntry;
    PKTRAP_FRAME TrapFrame;     <span class="hljs-comment" style="box-sizing: border-box;">//切换线程,保存寄存器环境用</span>
    PVOID CallbackStack;
    PVOID ServiceTable;         <span class="hljs-comment" style="box-sizing: border-box;">//该线程使用的SSDT表</span>
    UCHAR ApcStateIndex;
    UCHAR IdealProcessor;       <span class="hljs-comment" style="box-sizing: border-box;">//该线程的理想处理器</span>
    BOOLEAN Preempted;          <span class="hljs-comment" style="box-sizing: border-box;">//该线程是否被高优先级的线程抢占了</span>
    BOOLEAN ProcessReadyQueue;
    BOOLEAN KernelStackResident;
    SCHAR BasePriority;
    SCHAR PriorityDecrement;
    CHAR Saturation;
    KAFFINITY UserAffinity;
    PKPROCESS <span class="hljs-built_in" style="box-sizing: border-box;">Process</span>;
    KAFFINITY Affinity;          <span class="hljs-comment" style="box-sizing: border-box;">//掩码,指定线程在哪一核上运行</span>
    PKAPC_STATE ApcStatePointer[<span class="hljs-number" style="box-sizing: border-box;">2</span>];
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        KAPC_STATE SavedApcState;
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SavedApcStateFill[KAPC_STATE_ACTUAL_LENGTH];
            CCHAR FreezeCount;
            CCHAR SuspendCount;
            UCHAR UserIdealProcessor;
            UCHAR CalloutActive;
            UCHAR OtherPlatformFill;
        };
    };
    PVOID Win32Thread;
    PVOID StackBase;
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        KAPC SuspendApc;
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SuspendApcFill0[KAPC_OFFSET_TO_SPARE_BYTE0];
            SCHAR Quantum;
        };
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SuspendApcFill1[KAPC_OFFSET_TO_SPARE_BYTE1];
            UCHAR QuantumReset;
        };
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SuspendApcFill2[KAPC_OFFSET_TO_SPARE_LONG];
            ULONG KernelTime;
        };
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SuspendApcFill3[KAPC_OFFSET_TO_SYSTEMARGUMENT1];
            PVOID TlsArray;
        };
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SuspendApcFill4[KAPC_OFFSET_TO_SYSTEMARGUMENT2];
            PVOID BBTData;
        };
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SuspendApcFill5[KAPC_ACTUAL_LENGTH];
            UCHAR PowerState;
            ULONG UserTime;
        };
    };
    <span class="hljs-keyword" style="box-sizing: border-box;">union</span> {
        KSEMAPHORE SuspendSemaphore;
        <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="box-sizing: border-box;">struct</span> {</span>
            UCHAR SuspendSemaphorefill[KSEMAPHORE_ACTUAL_LENGTH];
            ULONG SListFaultCount;
        };
    };
    LIST_ENTRY ThreadListEntry;
    PVOID SListFaultAddress;
} KTHREAD, *PKTHREAD, *PRKTHREAD;


1663759855440-67c5c82b-50be-4bf3-9e1c-fb4d3d1f5171-1714486689878-96.png
1663759924908-0534b2b4-15fe-46dc-98cd-bd99e9e88c51-1714486689878-97.png
对源码进行编译调试编译
<font color="rgba(0, 0, 0, 0.8)" face="SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace"><span style="box-sizing: border-box; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; text-size-adjust: none; border-radius: 6px; border-style: initial; border-color: initial; border-image: initial; line-height: inherit; overflow-wrap: normal;">path G:\wrk-v1</span></font><span class="hljs-number" style="box-sizing: border-box;">.2</span>\tools\x86;%path% 

cl.exe

cd G:\wrk-v1<span class="hljs-number" style="box-sizing: border-box;">.2</span>\base\ntos

g:

nmake -nologo x86=


1663765371823-2dbfccb4-b023-4a3c-8388-abce2f09968e-1714486703967-102.png
1663765416799-43319702-ddd9-4ea9-a638-86abcbdd2cfa-1714486703967-103.png
1663765454973-a4953545-78d0-4dff-85c9-a85c9c3e0b55-1714486703967-104.png
这个就等于 NTKernel.exe
用法
先把文件拷到虚拟机里面,我们要把当前系统的内核替换掉,但是不能把系统原来的内核删了,因此只能在 boot.ini里面加一个开机选项
​ 1. 把 wrkx86.exe 复制到/WINDOWS/system32/目录下
​ 把 ..\wrk-v1.2\ws03sp1hals\x86\halacpim目录下的 halacpim.dll 复制到/WINDOWS/system32/目录下
​ 2.编辑BOOT.ini
/kernel=wrkx86.exe /hal=halacpim.dll multi(0)disk(0)rdisk(0)partition(1)/WINDOWS="Windows Server 2003, Enterprise" /fastdetect /NoExecute=OptOut    multi(0)disk(0)rdisk(0)partition(1)/WINDOWS="WRK 1.2" /fastdetect /NoExecute=OptOut /kernel=wrkx86.exe /hal=halmacpi.dll  /debugport=com1 /baudrate=115200

​ 3.配置双机调试
​ 4.用windbg去连接 ,连接后记得 lm 看一下符号加载没有
​ 5.要调试什么函数都可以可以 .例如我们要调 NtCreateProcess
1663766460269-9190bb95-69d1-42ba-a53b-16b340e7aceb-1714486730155-111.png
1663766525690-7f90297e-6900-4d95-9959-534895cb6e0e-1714486730155-112.png
然后在文件里面搜索你要调试的函数,下断点 F9就可以了 ,或者通过命令 BP NtCreateProcess 也可以
  • WRK源码还是有缺陷的,比如一些计算器,画图等3环软件就没有源码,而且它的源码不是很全,微软是不会提供的
    • 可以自己逆向获取,但是工作量太大了;可以下载ReatOS,用它和WRK结合起来分析

参考书籍
Windows内核原理和实现 潘爱民
Windows内核情景分析 毛德操
获取所有进程的页目录表地址
  • 我们主需要获取一个进程的进程对象,就可以遍历所有进程
  • 可以通过API PsGetCurrentProcess 获取当前的进程对象
  • 我们可以通过 wrk 查看 该函数的实现
#define _PsGetCurrentProcess() (CONTAINING_RECORD(((KeGetCurrentThread())->ApcState.Process),EPROCESS,Pcb))拿到当前的一个线程,通过线程的 ApcState 拿到进程
<span style="box-sizing: border-box; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; text-size-adjust: none; border-radius: 6px; border-style: initial; border-color: initial; border-image: initial; line-height: inherit; overflow-wrap: normal;">
</span><span class="hljs-function" style="box-sizing: border-box;">NTAPI <span class="hljs-title" style="box-sizing: border-box;">KeGetCurrentThread</span> <span class="hljs-params" style="box-sizing: border-box;">(VOID)</span>
</span>{
<span class="hljs-meta" style="box-sizing: border-box;">#<span class="hljs-meta-keyword" style="box-sizing: border-box;">if</span> (_MSC_FULL_VER >= 13012035)</span>
    <span class="hljs-keyword" style="box-sizing: border-box;">return</span> (struct _KTHREAD *) (ULONG_PTR) __readfsdword (FIELD_OFFSET (KPCR, PrcbData.CurrentThread));
<span class="hljs-meta" style="box-sizing: border-box;">#<span class="hljs-meta-keyword" style="box-sizing: border-box;">else</span></span>
    __asm {  mov eax, fs:[<span class="hljs-number" style="box-sizing: border-box;">0</span>] KPCR.PrcbData.CurrentThread }
<span class="hljs-meta" style="box-sizing: border-box;">#<span class="hljs-meta-keyword" style="box-sizing: border-box;">endif</span></span>
}
可以看到这里涉及到一个KPCR结构体也就是CPU控制块CPU控制块: 操作系统需要实时交给CPU很多表信息,因此需要快速的去查一下表,因此微软做了一个KPCR结构体,里面放了CPU用到的所有表,这个表地址 放到了 fs:[0]  或者直接在WinDbg里u一下这个函数的实现
kd> u PsGetCurrentProcess
nt!PsGetCurrentProcess:
        mov     eax,dword ptr fs:[<span class="hljs-number" style="box-sizing: border-box;">00000124</span>h];等价于_KPRCB结构体再+<span class="hljs-number" style="box-sizing: border-box;">4</span>的位置也就是当前线程
        mov     eax,dword ptr [eax+<span class="hljs-number" style="box-sizing: border-box;">50</span>h];拿到当前线程对象后再加<span class="hljs-number" style="box-sizing: border-box;">50</span>h就得到了进程对象结构体
        ret
也就是fs:[124]在_KPCR结构体最后一项还要加4的位置,0x120 PrcbData : _KPRCB(还要+4)也就是_KPRCB结构体里的+0x004 CurrentThread    : Ptr32 _KTHREAD 成员然后再+50h就是_KTHREAD里的+0x040 ApcState : _KAPC_STATE;这个结构体里再+10的位置最终在_KAPC_STATE结构体里+10的位置得到了+0x010 Process : Ptr32 _KPROCESS这里测试系统用的是Win732位.XP的话是eax+44h

  • KPCR结构体的部分成员 可以通过指令 dt KPCR 查看
  • KPCR这个结构体基本上想拿什么东西都可以从这里拿
kd> dt _KPCR
    
ntdll!_KPCR
+0x000 NtTib            : _NT_TIB ;记录了内核的栈信息
;........成员省略..........................
+0x020 Prcb             : Ptr32 _KPRCB;   最重要的成员 KPCRB结构体
;........成员省略..........................
+0x03c GDT              : Ptr32 _KGDTENTRY ;CPU要给GDTR的地址就从这里拿出来给过去
;........成员省略..........................
+0x120 PrcbData         : _KPRCB   


    • KPCRB结构体 可以通过指令 dt KPCR 查看
  • 这个结构体很大,结构体套结构体,所以只展示部分重要字段
    <font color="rgba(0, 0, 0, 0.8)" face="SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace"><span style="box-sizing: border-box; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; text-size-adjust: none; border-radius: 6px; border-style: initial; border-color: initial; border-image: initial; line-height: inherit; overflow-wrap: normal;">kd> dt _KPRCB
        
    ntdll!_KPRCB
    +</span></font><span class="hljs-number" style="box-sizing: border-box;">0x000</span> MinorVersion     : Uint2B
    +<span class="hljs-number" style="box-sizing: border-box;">0x002</span> MajorVersion     : Uint2B
    +<span class="hljs-number" style="box-sizing: border-box;">0x004</span> CurrentThread    : Ptr32 _KTHREAD    保存了当前线程,指向一个_KTHREAD结构体也就等价 
                                                于指向_ETHREAD结构体
    +<span class="hljs-number" style="box-sizing: border-box;">0x008</span> NextThread       : Ptr32 _KTHREAD;   指向下一个会被切换的线程
    +<span class="hljs-number" style="box-sizing: border-box;">0x00c</span> IdleThread       : Ptr32 _KTHREAD;   指向空闲的线程(如果没有下一个就走这个空闲的)


  • 以XP为例,遍历所有进程
  • 1663770532796-a3845596-0000-4f7f-a48f-fe28b47d8303-1714486811366-117.png
  • 可以看到 fs的地址不是0 ,所以 _KPCR 结构体的首地址在 ffdff000
  • kd> dt _KPCR
    nt!_KPCR
       +0x000 NtTib            : _NT_TIB
       +0x01c SelfPcr          : Ptr32 _KPCR
       +0x020 Prcb             : Ptr32 _KPRCB
       +0x024 Irql             : UChar
       +0x028 IRR              : Uint4B
       +0x02c IrrActive        : Uint4B
       +0x030 IDR              : Uint4B
       +0x034 KdVersionBlock   : Ptr32 Void
       +0x038 IDT              : Ptr32 _KIDTENTRY
       +0x03c GDT              : Ptr32 _KGDTENTRY
       +0x040 TSS              : Ptr32 _KTSS
       +0x044 MajorVersion     : Uint2B
       +0x046 MinorVersion     : Uint2B
       +0x048 SetMember        : Uint4B
       +0x04c StallScaleFactor : Uint4B
       +0x050 DebugActive      : UChar
       +0x051 Number           : UChar
       +0x052 Spare0           : UChar
       +0x053 SecondLevelCacheAssociativity : UChar
       +0x054 VdmAlert         : Uint4B
       +0x058 KernelReserved   : [14] Uint4B
       +0x090 SecondLevelCacheSize : Uint4B
       +0x094 HalReserved      : [16] Uint4B
       +0x0d4 InterruptMode    : Uint4B
       +0x0d8 Spare1           : UChar
       +0x0dc KernelReserved2  : [17] Uint4B
       +0x120 PrcbData         : _KPRCB
    
    
    kd> dt _eprocess
    ntdll!_EPROCESS
       +0x000 Pcb              : _KPROCESS
       +0x06c ProcessLock      : _EX_PUSH_LOCK
       +0x070 CreateTime       : _LARGE_INTEGER
       +0x078 ExitTime         : _LARGE_INTEGER
       +0x080 RundownProtect   : _EX_RUNDOWN_REF
       +0x084 UniqueProcessId  : Ptr32 Void
       +0x088 ActiveProcessLinks : _LIST_ENTRY
       +0x090 QuotaUsage       : [3] Uint4B
       +0x09c QuotaPeak        : [3] Uint4B
       +0x0a8 CommitCharge     : Uint4B
       +0x0ac PeakVirtualSize  : Uint4B
       +0x0b0 VirtualSize      : Uint4B
       +0x0b4 SessionProcessLinks : _LIST_ENTRY
       +0x0bc DebugPort        : Ptr32 Void
       +0x0c0 ExceptionPort    : Ptr32 Void
       +0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE
       +0x0c8 Token            : _EX_FAST_REF
       +0x0cc WorkingSetLock   : _FAST_MUTEX
       +0x0ec WorkingSetPage   : Uint4B
       +0x0f0 AddressCreationLock : _FAST_MUTEX
       +0x110 HyperSpaceLock   : Uint4B
       +0x114 ForkInProgress   : Ptr32 _ETHREAD
       +0x118 HardwareTrigger  : Uint4B
       +0x11c VadRoot          : Ptr32 Void
       +0x120 VadHint          : Ptr32 Void
       +0x124 CloneRoot        : Ptr32 Void
       +0x128 NumberOfPrivatePages : Uint4B
       +0x12c NumberOfLockedPages : Uint4B
       +0x130 Win32Process     : Ptr32 Void
       +0x134 Job              : Ptr32 _EJOB
       +0x138 SectionObject    : Ptr32 Void
       +0x13c SectionBaseAddress : Ptr32 Void
       +0x140 QuotaBlock       : Ptr32 _EPROCESS_QUOTA_BLOCK
       +0x144 WorkingSetWatch  : Ptr32 _PAGEFAULT_HISTORY
       +0x148 Win32WindowStation : Ptr32 Void
       +0x14c InheritedFromUniqueProcessId : Ptr32 Void
       +0x150 LdtInformation   : Ptr32 Void
       +0x154 VadFreeHint      : Ptr32 Void
       +0x158 VdmObjects       : Ptr32 Void
       +0x15c DeviceMap        : Ptr32 Void
       +0x160 PhysicalVadList  : _LIST_ENTRY
       +0x168 PageDirectoryPte : _HARDWARE_PTE_X86
       +0x168 Filler           : Uint8B
       +0x170 Session          : Ptr32 Void
       +0x174 ImageFileName    : [16] UChar
       +0x184 JobLinks         : _LIST_ENTRY
       +0x18c LockedPagesList  : Ptr32 Void
       +0x190 ThreadListHead   : _LIST_ENTRY
       +0x198 SecurityPort     : Ptr32 Void
       +0x19c PaeTop           : Ptr32 Void
       +0x1a0 ActiveThreads    : Uint4B
       +0x1a4 GrantedAccess    : Uint4B
       +0x1a8 DefaultHardErrorProcessing : Uint4B
       +0x1ac LastThreadExitStatus : Int4B
       +0x1b0 Peb              : Ptr32 _PEB
       +0x1b4 PrefetchTrace    : _EX_FAST_REF
       +0x1b8 ReadOperationCount : _LARGE_INTEGER
       +0x1c0 WriteOperationCount : _LARGE_INTEGER
       +0x1c8 OtherOperationCount : _LARGE_INTEGER
       +0x1d0 ReadTransferCount : _LARGE_INTEGER
       +0x1d8 WriteTransferCount : _LARGE_INTEGER
       +0x1e0 OtherTransferCount : _LARGE_INTEGER
       +0x1e8 CommitChargeLimit : Uint4B
       +0x1ec CommitChargePeak : Uint4B
       +0x1f0 AweInfo          : Ptr32 Void
       +0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
       +0x1f8 Vm               : _MMSUPPORT
       +0x238 LastFaultCount   : Uint4B
       +0x23c ModifiedPageCount : Uint4B
       +0x240 NumberOfVads     : Uint4B
       +0x244 JobStatus        : Uint4B
       +0x248 Flags            : Uint4B
       +0x248 CreateReported   : Pos 0, 1 Bit
       +0x248 NoDebugInherit   : Pos 1, 1 Bit
       +0x248 ProcessExiting   : Pos 2, 1 Bit
       +0x248 ProcessDelete    : Pos 3, 1 Bit
       +0x248 Wow64SplitPages  : Pos 4, 1 Bit
       +0x248 VmDeleted        : Pos 5, 1 Bit
       +0x248 OutswapEnabled   : Pos 6, 1 Bit
       +0x248 Outswapped       : Pos 7, 1 Bit
       +0x248 ForkFailed       : Pos 8, 1 Bit
       +0x248 HasPhysicalVad   : Pos 9, 1 Bit
       +0x248 AddressSpaceInitialized : Pos 10, 2 Bits
       +0x248 SetTimerResolution : Pos 12, 1 Bit
       +0x248 BreakOnTermination : Pos 13, 1 Bit
       +0x248 SessionCreationUnderway : Pos 14, 1 Bit
       +0x248 WriteWatch       : Pos 15, 1 Bit
       +0x248 ProcessInSession : Pos 16, 1 Bit
       +0x248 OverrideAddressSpace : Pos 17, 1 Bit
       +0x248 HasAddressSpace  : Pos 18, 1 Bit
       +0x248 LaunchPrefetched : Pos 19, 1 Bit
       +0x248 InjectInpageErrors : Pos 20, 1 Bit
       +0x248 VmTopDown        : Pos 21, 1 Bit
       +0x248 Unused3          : Pos 22, 1 Bit
       +0x248 Unused4          : Pos 23, 1 Bit
       +0x248 VdmAllowed       : Pos 24, 1 Bit
       +0x248 Unused           : Pos 25, 5 Bits
       +0x248 Unused1          : Pos 30, 1 Bit
       +0x248 Unused2          : Pos 31, 1 Bit
       +0x24c ExitStatus       : Int4B
       +0x250 NextPageColor    : Uint2B
       +0x252 SubSystemMinorVersion : UChar
       +0x253 SubSystemMajorVersion : UChar
       +0x252 SubSystemVersion : Uint2B
       +0x254 PriorityClass    : UChar
       +0x255 WorkingSetAcquiredUnsafe : UChar
       +0x258 Cookie           : Uint4B


  • //枚举进程页目录表
    void EnumProcessDir() {
        PEPROCESS Porcess = NULL;
        //获取进程对象
        __asm {
            mov eax, fs:[124h]    //ETHREAD; 先获取当前线程对象
            mov eax, [eax + 44h]  //EPROCESS;进程对象 在XP里是+44h (34+10)
            mov Porcess, eax;     //进程对象保存一下.
        }
    
        //链表在EPROCESS结构体偏移88的位置
        _LIST_ENTRY* head = (_LIST_ENTRY*)((char*)Porcess + 0x88);//链表头;
            //这样就得到了第一个进程的结构体指针.
        _LIST_ENTRY* tail = head;//由于是双向循环链表所以再保存一下,相当于保存一下遍历的终点
    
        //如果头不等于尾就一直循环.
        do {
            Porcess = (PEPROCESS)((char*)head - 0x88); //获取到进程对象
            //进程ID在偏移0x84的位置
            ULONG UniqueProcessId = *(ULONG*)((char*)Porcess + 0x84); 
            //进程名在偏移0x174的位置
            CHAR* ImageFileName = (char*)Porcess + 0x174; 
            //获取页目录表的地址
            PVOID DirectoryTableBase = *(PVOID*)((char*)Porcess + 0x18);
            KdPrint(("UniqueProcessId:%d  ImageFileName:%s DirectoryTableBase:%p 
                             \r\n", UniqueProcessId, ImageFileName, DirectoryTableBase));
    
            //下一个链表
            head = head->Blink; //当前节点等于它的后继节点
        } while (head != tail);
    
        /* 
            得到一个进程的页目录表地址, 要操作它的进程就简单了...
            知道某个进程的页目录表地址,就可以查它的表了,就能知道对方的线性地址映射到那个物理地址
            这样就能在自己线程里操作这个物理地址,等价于操作对方的进程
            流程就是:
            读写进程内存 => 虚拟地址  =>  页目录表地址 =>  物理地址  =>  当前进程操作物理地址
    
            操作物理地址的话可以把物理地址映射到自己的进程里,等价于强制和别的进程内存共享...
        */
    }


  • 遍历的时候我们可以发现有一个无效的进程ID,因为他有头结点,头结点就是一个空的节点,一般都是全局变量
  • 1663773022003-d4b2909f-a014-4193-9d08-fd310b88e30d.jpg
  • 1663773418135-24793d7d-a043-4ed4-bd25-81224216ff3d.jpg

获取所有进程的页目录表地址
  • 只需要获取到一个进程的进程对象,就可以遍历所有进程了
  • 通过API可以获取到当前的进程对象PsGetCurrentProcess

可以用WRK或者ReatOS看一下这个函数是如何实现的,就能知道进程结构体中的链表放在那里了WRK版本        #define PsGetCurrentProcess() _PsGetCurrentProcess()        #define _PsGetCurrentProcess() (CONTAINING_RECORD(((KeGetCurrentThread())        ->ApcState.Process),EPROCESS,Pcb))可以看到这里是先拿到当前线程,然后通过线程的APC状态拿到进程这个线程来自于fs:[0]
NTAPI KeGetCurrentThread (VOID)
{
#if (_MSC_FULL_VER >= 13012035)
    return (struct _KTHREAD *) (ULONG_PTR) __readfsdword (FIELD_OFFSET (KPCR, PrcbData.CurrentThread));
#else
    __asm {  mov eax, fs:[0] KPCR.PrcbData.CurrentThread }
#endif
}
可以看到这里涉及到一个KPCR结构体也就是CPU控制块或者直接在WinDbg里u一下这个函数的实现
kd> u PsGetCurrentProcess
nt!PsGetCurrentProcess:
        mov     eax,dword ptr fs:[00000124h];等价于_KPRCB结构体再+4的位置也就是当前线程
        mov     eax,dword ptr [eax+50h];拿到当前线程对象后再加50h就得到了进程对象结构体
        ret
也就是fs:[124]在_KPCR结构体最后一项还要加4的位置,0x120 PrcbData : _KPRCB(还要+4)也就是_KPRCB结构体里的+0x004 CurrentThread    : Ptr32 _KTHREAD 成员然后再+50h就是_KTHREAD里的+0x040 ApcState : _KAPC_STATE;这个结构体里再+10的位置最终在_KAPC_STATE结构体里+10的位置得到了+0x010 Process : Ptr32 _KPROCESS这里测试系统用的是Win732位.XP的话是eax+44h

KPCR-->CPU控制块
操作系统作者要时时刻刻交给CPU很多表的信息. 动不动就切换进程切换线程就要快速的去查一些表,所以微软就做了一个KPCR结构体,里面放了CPU要用到的所有表 而这个表地址被放到fs里了 所以要想访问这个表就直接fs:[0]就可以访问了
    • KPCR结构体的部分成员
  • kd> dt _KPCR ntdll!_KPCR +0x000 NtTib : _NT_TIB ;记录了内核的栈信息 ;........成员省略.......................... +0x020 Prcb : Ptr32 _KPRCB;KPCRB结构体 ;........成员省略.......................... +0x03c GDT : Ptr32 _KGDTENTRY ;CPU要给GDTR的地址就从这里拿出来给过去 ;........成员省略.......................... +0x120 PrcbData : _KPRCB
      • KPCRB结构体
    • 这个结构体很大,结构体套结构体,所以只展示部分重要字段 kd> dt _KPRCB ntdll!_KPRCB +0x000 MinorVersion : Uint2B +0x002 MajorVersion : Uint2B ;保存了当前线程,指向一个_KTHREAD结构体也就等价于指向_ETHREAD结构体 +0x004 CurrentThread : Ptr32 _KTHREAD +0x008 NextThread : Ptr32 _KTHREAD;指向下一个会被切换的线程 +0x00c IdleThread : Ptr32 _KTHREAD;指向空闲的线程(如果没有下一个就走这个空闲的)
      • KPCR这个结构体基本上想拿什么东西都可以从这里拿
      • 代码示例
    • //枚举进程页目录表
      void EnumProcessDir() {
          PEPROCESS Porcess = NULL;
          //获取进程对象
          __asm {
              mov eax, fs:[124h] //先获取当前线程对象
              mov eax, [eax + 44h] //EPROCESS;进程对象 在XP里是+44h
              mov Porcess, eax; //进程对象保存一下.
          }
      
          //链表在EPROCESS结构体偏移88的位置
          _LIST_ENTRY* head = (_LIST_ENTRY*)((char*)Porcess + 0x88);//链表头;
              //这样就得到了第一个进程的结构体指针.
          _LIST_ENTRY* tail = head;//由于是双向循环链表所以再保存一下,相当于保存一下尾部吧
      
          //如果头不等于尾就一直循环.
          do {
              Porcess = (PEPROCESS)((char*)head - 0x88); //获取到进程对象
              //进程ID再0x84的位置
              ULONG UniqueProcessId = *(ULONG*)((char*)Porcess + 0x84); 
              //进程名在174的位置
              CHAR* ImageFileName = (char*)Porcess + 0x174; 
              //获取页目录表的地址
              PVOID DirectoryTableBase = *(PVOID*)((char*)Porcess + 0x18);
              KdPrint(("UniqueProcessId:%d  ImageFileName:%s DirectoryTableBase:%p 
                               \r\n", UniqueProcessId, ImageFileName, DirectoryTableBase));
      
              //下一个链表
              head = head->Blink; //当前节点等于它的后继节点
          } while (head != tail);
      
          /* 
              得到一个进程的页目录表地址, 要操作它的进程就简单了...
              知道某个进程的页目录表地址,就可以查它的表了,就能知道对方的线性地址映射到那个物理地址
              这样就能在自己线程里操作这个物理地址,等价于操作对方的进程
              流程就是:
              读写进程内存 => 虚拟地址  =>  页目录表地址 =>  物理地址  =>  当前进程操作物理地址
      
              操作物理地址的话可以把物理地址映射到自己的进程里,等价于强制和别的进程内存共享...
          */
      }





您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-4-5 05:48 , Processed in 0.117905 second(s), 28 queries , Yac On.

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表