撰写本系列文章目的在於提升资讯安全之实务能力,
并透过实作体悟到资讯安全领域的重要性,
本系列所有文章之内容皆有一定技术水平,
不得从事非法行为、恶意攻击等非法活动,
「一切不合法规之行为皆受法律所约束」,
为了避免造成公司、厂商或玩家之间困扰,
所有实作不会拿已上市产品、Online Game 等等来作范例学习,
且部分具有深度、价值之内容,将会提升一定阅读门槛(不对该技术做分析、解说),
请勿透过本系列文章所学,从事任何非法活动,请不要以身试法!!!
在昨日的文章中:
【Day 10】- 藏起来的 Process 真的看不见摸不着?(讲解找出断链後的 Process 方法)
已经有说到如何找出修改 ActiveProcessLinks 隐藏的 Process,
到文末时,
有稍微提到 PsLookupProcessByProcessId 会透过 PspCidTable 拿对应 PID 的 Object,
透过这样的方式拿到 EProcess Address,
那今天就要来说说 PspCidTable 是什麽东西。
上一篇与上上篇还没看得可以先去看看哦~
首先开始前要先说一下,
小弟我目前还属於菜鸟阶段,正不断努力学习中,
若有发现错误或不妥之处还请不吝赐教。
欢迎大家多多留言,互相交流交流。
那就开始今天的主题吧~~
什麽是 PspCidTable ?
A Process's、A Thread's Kernel Object Handle Table
每个 Process 都有自己的 Handle Table,
Index 就是 Process 的 PID、TID,
要操作 Process 时(应该说要拿 EProcess Address 时),
通过 Index(PID、TID)存取 Handle Table,然後返回 object pointer。
那 PspCidTable 长什麽样子?
在 WinDbg 中输入 dt _HANDLE_TABLE
lkd> dt _HANDLE_TABLE
nt!_HANDLE_TABLE
+0x000 NextHandleNeedingPool : Uint4B
+0x004 ExtraInfoPages : Int4B
+0x008 TableCode : Uint8B
+0x010 QuotaProcess : Ptr64 _EPROCESS
+0x018 HandleTableList : _LIST_ENTRY
+0x028 UniqueProcessId : Uint4B
+0x02c Flags : Uint4B
+0x02c StrictFIFO : Pos 0, 1 Bit
+0x02c EnableHandleExceptions : Pos 1, 1 Bit
+0x02c Rundown : Pos 2, 1 Bit
+0x02c Duplicated : Pos 3, 1 Bit
+0x02c RaiseUMExceptionOnInvalidHandleClose : Pos 4, 1 Bit
+0x030 HandleContentionEvent : _EX_PUSH_LOCK
+0x038 HandleTableLock : _EX_PUSH_LOCK
+0x040 FreeLists : [1] _HANDLE_TABLE_FREE_LIST
+0x040 ActualEntry : [32] UChar
+0x060 DebugInfo : Ptr64 _HANDLE_TRACE_DEBUG_INFO
首先,先来逆向 PsLookupProcessByProcessId:
uf PsLookupProcessByProcessId
lkd> uf PsLookupProcessByProcessId
nt!PsLookupProcessByProcessId:
fffff800`09de0ad0 48895c2408 mov qword ptr [rsp+8],rbx
fffff800`09de0ad5 4889742410 mov qword ptr [rsp+10h],rsi
fffff800`09de0ada 48897c2418 mov qword ptr [rsp+18h],rdi
fffff800`09de0adf 4156 push r14
fffff800`09de0ae1 4883ec20 sub rsp,20h
fffff800`09de0ae5 65488b342588010000 mov rsi,qword ptr gs:[188h]
fffff800`09de0aee 4c8bf2 mov r14,rdx
fffff800`09de0af1 66ff8ee6010000 dec word ptr [rsi+1E6h]
fffff800`09de0af8 b203 mov dl,3
fffff800`09de0afa e8412afcff call nt!PspReferenceCidTableEntry (fffff800`09da3540)
因为时间、文章长度的关系,我就直接讲重点,
这边看到 call 了一个 PspReferenceCidTableEntry,直接跟进去看,
uf fffff800`09da3540
lkd> uf fffff800`09da3540
nt!PspReferenceCidTableEntry:
fffff800`09da3540 48896c2420 mov qword ptr [rsp+20h],rbp
fffff800`09da3545 56 push rsi
fffff800`09da3546 4883ec20 sub rsp,20h
fffff800`09da354a 488b05afbcedff mov rax,qword ptr [nt!PspCidTable (fffff800`09c7f200)]
不远处就可以看到拿了 PspCidTable Address,
所以可以直接透过这个 API 来定位 PspCidTable,
PspCidTable 是没有导出的,无法直接呼叫使用,
需要手动透过特徵定位。
定位方式:
一、取得 PsLookupProcessByProcessId Address
二、找到 call PspReferenceCidTableEntry
(特徵直接抓 0xe8 即可)
三、进入 PspReferenceCidTableEntry 这个 call
四、找到 rax,qword ptr [nt!PspCidTable (xxx)]
(特徵直接抓 0x48、0x8b 0x05 即可)
五、取得 PspCidTable Address
dp PspCidTable
fffff800`09c7f200
lkd> dp PspCidTable
fffff800`09c7f200 ffffcf01`82216cc0 fffff800`09c7f208
fffff800`09c7f210 fffff800`09c7f208 ffffe307`15ec0480
fffff800`09c7f220 00000000`00000000 00000000`00000000
fffff800`09c7f230 00001000`00010000 ffffe307`15ec7800
fffff800`09c7f240 00000000`00000000 00000002`00005e03
fffff800`09c7f250 00000000`00000000 00000000`00000000
fffff800`09c7f260 00000000`00000000 fffff800`0a158000
fffff800`09c7f270 fffff800`09886000 00000000`00000000
dt _HANDLE_TABLE ffffcf01`82216cc0
lkd> dt _HANDLE_TABLE ffffcf01`82216cc0
nt!_HANDLE_TABLE
+0x000 NextHandleNeedingPool : 0x1800
+0x004 ExtraInfoPages : 0n0
+0x008 TableCode : 0xffffcf01`87f59001
+0x010 QuotaProcess : (null)
+0x018 HandleTableList : _LIST_ENTRY [ 0x?? - 0x?? ]
+0x028 UniqueProcessId : 0
+0x02c Flags : 1
+0x02c StrictFIFO : 0y1
+0x02c EnableHandleExceptions : 0y0
+0x02c Rundown : 0y0
+0x02c Duplicated : 0y0
+0x02c RaiseUMExceptionOnInvalidHandleClose : 0y0
+0x030 HandleContentionEvent : _EX_PUSH_LOCK
+0x038 HandleTableLock : _EX_PUSH_LOCK
+0x040 FreeLists : [1] _HANDLE_TABLE_FREE_LIST
+0x040 ActualEntry : [32] ""
+0x060 DebugInfo : (null)
再来就是 Table 是有分 Level 的:
判断 Table 的 Level:
这里的 TableCode:0xffffcf01`87f59001
结尾是 01
代表这张表是 Level2
dp 0xffffcf01`87f59000
lkd> dp 0xffffcf01`87f59000
ffffcf01`87f59000 ffffcf01`8221a000 ffffcf01`87f5a000
ffffcf01`87f59010 ffffcf01`88585000 ffffcf01`88b50000
ffffcf01`87f59020 ffffcf01`88fe9000 ffffcf01`89d39000
ffffcf01`87f59030 00000000`00000000 00000000`00000000
ffffcf01`87f59040 00000000`00000000 00000000`00000000
ffffcf01`87f59050 00000000`00000000 00000000`00000000
ffffcf01`87f59060 00000000`00000000 00000000`00000000
ffffcf01`87f59070 00000000`00000000 00000000`00000000
dp ffffcf01`8221a000
lkd> dp ffffcf01`8221a000
ffffcf01`8221a000 00000000`00000000 00000000`00000000
ffffcf01`8221a010 e30715ed`8040ff57 00000000`00000000
ffffcf01`8221a020 e30718f8`5080fe9b 00000000`00000000
ffffcf01`8221a030 e30715ec`8700fff7 00000000`00000000
ffffcf01`8221a040 e30715ec`e040fff7 00000000`00000000
ffffcf01`8221a050 e30715ed`3700fff7 00000000`00000000
ffffcf01`8221a060 e30715eb`9040fff7 00000000`00000000
ffffcf01`8221a070 e30715e4`e040fff7 00000000`00000000
e30715ed`8040ff57
dt _eprocess 0xFFFFE30715ED8040
lkd> dt _eprocess 0xFFFFE30715ED8040
nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x2d8 ProcessLock : _EX_PUSH_LOCK
--- --- ---
--- --- ---
--- --- ---
+0x450 ImageFileName : [15] "System"
--- --- ---
--- --- ---
--- --- ---
看到了吧,列举到了系统 Process:System
补充:
每张 Table 在 x64 的大小是 0x1000(4096),
Level2 和 Level3 放的是 Pointer,大小是 8,
所以 Level2 和 Level3 都要列举 4096 / 8 = 516 次,
Level1 是 _handle_table_entry 结构,所以大小是 16,
所以 Level1 要列举 4096 / 16 = 256 次。
列举结果:
所以说了这麽多要怎麽隐藏ㄋ?
请看 hidden Project 的 PsMonitor.c
我放一份在这里:
VOID UnlinkProcessFromCidTable(PProcessTableEntry Entry)
{
PVOID PspCidTable = GetPspCidTablePointer();
if (!PspCidTable)
{
LogWarning("Can't unlink process %Iu from PspCidTable(NULL)", Entry->processId);
return;
}
CidTableContext context;
context.ProcessId = Entry->processId;
context.Found = FALSE;
EX_ENUMERATE_HANDLE_ROUTINE routine = (IsWin8OrAbove() ? (EX_ENUMERATE_HANDLE_ROUTINE)&RemoveHandleCallbackWin8 : &RemoveHandleCallback);
if (!ExEnumHandleTable(PspCidTable, routine, &context, NULL))
{
LogWarning("Can't unlink process %Iu from PspCidTable", Entry->processId);
return;
}
if (!context.Found)
{
LogWarning("Can't find process %Iu in PspCidTable", Entry->processId);
return;
}
// Hack for Windows Vista, 7, to avoid lock bit leak
if (!IsWin8OrAbove())
{
context.Entry->u1.Object = NULL;
context.Entry->u2.GrantedAccess = 0;
}
Entry->cidEntryBackup = context.EntryBackup;
Entry->cidEntry = context.Entry;
}
BOOLEAN RemoveHandleCallback(PHANDLE_TABLE_ENTRY HandleTableEntry, HANDLE Handle, PVOID EnumParameter)
{
PCidTableContext context = (PCidTableContext)EnumParameter;
if (context->ProcessId != Handle)
return FALSE;
context->Found = TRUE;
context->Entry = HandleTableEntry;
context->EntryBackup = *HandleTableEntry;
LogInfo(
"PID %Iu has been removed from PspCidTable, entry:%p, object:%p, access:%08x",
Handle,
HandleTableEntry,
context->EntryBackup.u1.Object,
context->EntryBackup.u2.GrantedAccess
);
return TRUE;
}
notepad.exe 隐藏前:
在 R0 下,暴力列举 PID,然後 CALL PsLookupProcessByProcessId:
在 R3 下,暴力列举 PID,然後 CALL OpenProcess:
隐藏 notepad.exe:
隐藏後在 R0 下,暴力列举 PID,然後 CALL PsLookupProcessByProcessId:
隐藏後在 R3 下,暴力列举 PID,然後 CALL OpenProcess:
隐藏後在 R0 下,列举 PspCidTable:
没人找的到我了吧!哈哈哈哈哈~
好啦,明天开大绝,
教你/你把 Windows 里所有藏起来的 Process(Rookit)找出来 :D
好了,今天就讲到这结束了,
大家若有发现哪里写得不好或错误的地方,都留个言讨论一下吧 XD
那我们下期见 o( ̄▽ ̄)ブ
<<: 通过SafariViewController查询网站 Day22
>>: Day26. Blue Prism取号一把罩–BP自动取得订单编号
Elasticsearch/Solr/ELK Stash Caveat of using Elast...
内部稽核与外部稽核功能面分析 事项 内部稽核 外部稽核 稽核员资格 V 规费 V 认证资格 V 公正...
Hi Dai Gei Ho~ 我是Winnie~ 今天文章要来说的是 toRef 与 toRefs ...
分散式 transaction 和共识 (Distributed Transactions and ...
EPC (Event Driven Process-Chain) 事件驱动流程链是一种流程图应用在业...