已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
标 题: 【原创】shadow ssdt学习笔记(一)(二)作 者: zhuwg时 间: 2007-12-22,22:01:29链 接: /showthread.php?t=569551。取得shadow ssdt真实地址系统只提供了KeServiceDescriptorTable导出KeServiceDescriptorTableShadow是个未导出结构定义Copy codetypedef struct _SYSTEM_SERVICE_TABLEPNTPROC ServiceTable; / array of entry pointsPDWORD CounterTable; / array of usage countersDWORD ServiceLimit; / number of table entriesPBYTE ArgumentTable; / array of byte countsSYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE,*PPSYSTEM_SERVICE_TABLE;/-typedef struct _SERVICE_DESCRIPTOR_TABLESYSTEM_SERVICE_TABLE ntoskrnl; / ntoskrnl.exe ( native api )SYSTEM_SERVICE_TABLE win32k; / win32k.sys (gdi/user support)SYSTEM_SERVICE_TABLE Table3; / not usedSYSTEM_SERVICE_TABLE Table4; / not usedSYSTEM_DESCRIPTOR_TABLE,*PSYSTEM_DESCRIPTOR_TABLE,*PPSYSTEM_DESCRIPTOR_TABLE;其实 KeServiceDescriptorTableShadow包含4个子结构,其中第一个就是ntoskrnl.exe ( native api ),和KeServiceDescriptorTable指向一样 我们真正需要获得的是第二个win32k.sys (gdi/user support),第三个和第四个一般不使用定位方法1。硬编码Copy code/for xpif(gKernelVersion=WINXP)KeServiceDescriptorTableShadow=KeServiceDescriptorTable-0x40;/for 2kif(gKernelVersion=WIN2K)KeServiceDescriptorTableShadow=KeServiceDescriptorTable+0xE0;2。搜索KeAddSystemServiceTable反汇编代码可以看出Copy codelkd u KeAddSystemServiceTable l 40nt!KeAddSystemServiceTable:805ba589 8bff mov edi,edi805ba58b 55 push ebp805ba58c 8bec mov ebp,esp805ba58e 837d1803 cmp dword ptr ebp+18h,3805ba592 774e ja nt!KeAddSystemServiceTable+0x6b (805ba5e2)805ba594 8b4518 mov eax,dword ptr ebp+18h805ba597 c1e004 shl eax,4805ba59a 83b880a6558000 cmp dword ptr nt!KeServiceDescriptorTable (8055a680)eax,0805ba5a1 753f jne nt!KeAddSystemServiceTable+0x6b (805ba5e2)805ba5a3 8d8840a65580 lea ecx,nt!KeServiceDescriptorTableShadow (8055a640)eax805ba5a9 833900 cmp dword ptr ecx,0805ba5ac 7534 jne nt!KeAddSystemServiceTable+0x6b (805ba5e2)805ba5ae 837d1801 cmp dword ptr ebp+18h,1805ba5b2 8b5508 mov edx,dword ptr ebp+8805ba5b5 56 push esi805ba5b6 8b7510 mov esi,dword ptr ebp+10h805ba5b9 57 push edi805ba5ba 8b7d14 mov edi,dword ptr ebp+14h805ba5bd 8911 mov dword ptr ecx,edx805ba5bf 8b4d0c mov ecx,dword ptr ebp+0Ch805ba5c2 898844a65580 mov dword ptr nt!KeServiceDescriptorTableShadow+0x4 (8055a644)eax,ecx805ba5c8 89b048a65580 mov dword ptr nt!KeServiceDescriptorTableShadow+0x8 (8055a648)eax,esi805ba5ce 89b84ca65580 mov dword ptr nt!KeServiceDescriptorTableShadow+0xc (8055a64c)eax,edi805ba5d4 0f855a3e0300 jne nt!KeAddSystemServiceTable+0x4d (805ee434)805ba5da 5f pop edi805ba5db b001 mov al,1805ba5dd 5e pop esi805ba5de 5d pop ebp805ba5df c21400 ret 14h805ba5e2 32c0 xor al,al805ba5e4 ebf8 jmp nt!KeAddSystemServiceTable+0x6d (805ba5de)805ba5e6 90 nop805ba5e7 90 nop805ba5e8 90 nop805ba5e9 90 nop805ba5ea 90 nop搜索办法很简单就是找到805ba5a3 8d8840a65580 lea ecx,nt!KeServiceDescriptorTableShadow (8055a640)eax的8d88 40a65580 lea ecx, nt!KeServiceDescriptorTableShadow代码如下Copy codevoid GetKeServiceDescriptorTableShadow()PUCHAR cPtr, pOpcode;ULONG Length;for (cPtr = (PUCHAR)KeAddSystemServiceTable;cPtr (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE;cPtr += Length)if (!MmIsAddressValid(cPtr) break;Length = SizeOfCode(cPtr, &pOpcode);if (!Length | (Length = 1 & *pOpcode = 0xC3) break;if (*(PUSHORT)pOpcode = 0x888D)KeServiceDescriptorTableShadow = *(PVOID *)(pOpcode + 2);break;3。从KTHREAD.ServiceTable里面搜索如果是GUI线程 那么就是指向ServiceDescriptorTableShadow其实个人更加倾向这个办法 稳定安全可靠,上面那个代码也许会受到以后系统代码变化影响 但是这个肯定不会Copy codeGetServiceDescriptorTableShadowAddress proc uses esi edi ebxlocal dwThreadId:DWORDxor ebx, ebx ; = NULL. Assume ServiceDescriptorTableShadow will be not foundmov eax, KeServiceDescriptorTablemov esi, eax; Find KTHREAD.ServiceTable field; For non-GUI threads this field = KeServiceDescriptorTable; and it points to ServiceDescriptorTable; For GUI threads; ServiceDescriptorTableShadowinvoke KeGetCurrentThreadmov edi, 200h-4.while edi.break .if dword ptr eaxedi = esidec edi.endw.if edi != 0; edi = offset to ServiceTable field in KTHREAD structuremov dwThreadId, 080h.while dwThreadId ETHREAD/KTHREAD.if eax = STATUS_SUCCESSpush dword ptr ecxedifastcall ObfDereferenceObject, ecxpop eax.if eax != esimov edx, MmSystemRangeStartmov edx, edxmov edx, edx.if eax edx ; some stupid error checkingmov ebx, eaxinvoke DbgPrint, $CTA0(FindShadowTable: Found in thread with ID: %Xn), dwThreadId.break.endif.endif.endifadd dwThreadId, 4.endw.endifmov eax, ebxretGetServiceDescriptorTableShadowAddress endp4.mj0011所说的搜索有效内存地址的办法Copy code/*define structure for the system service table*/struct SYS_SERVICE_TABLE void *ServiceTable;unsigned long CounterTable;unsigned long ServiceLimit;void *ArgumentsTable;SYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTableShadow;/*Define KeServiceDescriptorTable based on the SST structure*/extern struct SYS_SERVICE_TABLE *KeServiceDescriptorTable;/*Declare function GetServiceDescriptorShadowTableAddress()*/struct SYS_SERVICE_TABLE * GetServiceDescriptorShadowTableAddress ();/*Declare the KeAddSystemServiceTable. This is just ahandle to the call function, it will be used by the functionabove to obtain the correct address of the KeServiceDescriptorShadowTable*/_declspec(dllimport) KeAddSystemServiceTable (ULONG, ULONG, ULONG, ULONG, ULONG);struct SYS_SERVICE_TABLE * GetServiceDescriptorShadowTableAddress ()/ First, obtain a pointer to KeAddSystemServiceTableunsigned char *check = (unsigned char*)KeAddSystemServiceTable;int i;/Initialize an instance of System Service Table, will be used to/obtain an address from KeAddSystemServiceTablestruct SYS_SERVICE_TABLE *rc=0;/ Make 100 attempts to match a valid address with that of KeServiceDescriptorTablefor (i=0; i=99; i+) _try / try to obtain an address from KeAddSystemServiceTablerc = *(struct SYS_SERVICE_TABLE*)check;/ if this address is NOT valid OR it itself is the address of/KeServiceDescriptorTable OR its first entry is NOT equal/to the first entry of KeServiceDescriptorTableif (!MmIsAddressValid (rc) | (rc = KeServiceDescriptorTable)| (memcmp (rc, KeServiceDescriptorTable, sizeof (*rc) != 0) / Proceed with the next addresscheck+;/ dont forget to reset the old addressrc = 0; _except (EXCEPTION_EXECUTE_HANDLER) rc = 0; / when the loop is completed, check if it produced a valid addressif (rc)/ because if it didnt, we failed to find the address of KeServiceDescriptorTableShadowbreak;/ otherwise, there is a valid address! So return it!return rc;二。函数名定位这个似乎没有多少好办法,解析pdb可以是可以 但是很麻烦不过还好的是 同一个版本的系统 调用号一样所以只需要3套 2k xp 2k3的调用号就可以完成hookpdb办法SymInitialize初始化SymSetSearchPath “srv*symbols*/”SymLoadModuleSymGetSymFromName老v曾经发出1个获取shadow地址和函数名称的工具 使用他可以很方便的获取具体代码可以F5查看以上读取pdb的方法测试使用的可以的但是实际使用很麻烦经过分析 我找到了1个比较好的定位办法我们以SetWindowsHookExA为例子Copy code.text:77D311D1 ; HHOOK _stdcall SetWindowsHookExA(int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId).text:77D311D1 public _SetWindowsHookExA16.text:77D311D1 _SetWindowsHookExA16 proc near.text:77D311D1.text:77D311D1 idHook = dword ptr 8.text:77D311D1 lpfn = dword ptr 0Ch.text:77D311D1 hModule = dword ptr 10h.text:77D311D1 dwThreadId = dword ptr 14h.text:77D311D1.text:77D311D1 mov edi, edi.text:77D311D3 push ebp.text:77D311D4 mov ebp, esp.text:77D311D6 push 2 ; int.text:77D311D8 push ebp+dwThreadId ; int.text:77D311DB push ebp+hModule ; hModule.text:77D311DE push ebp+lpfn ; int.text:77D311E1 push ebp+idHook ; int.text:77D311E4 call _SetWindowsHookExAW20 ; SetWindowsHookExAW(x,x,x,x,x).text:77D311E9 pop ebp.text:77D311EA retn 10h.text:77D311EA _SetWindowsHookExA16 endp.text:77D2DCFD ; int _stdcall SetWindowsHookExAW(int, int, HMODULE hModule, int, int).text:77D2DCFD _SetWindowsHookExAW20 proc near ; CODE XREF: SetWindowsHookExW(x,x,x,x)+13p.text:77D2DCFD ; SetWindowsHookExA(x,x,x,x)+13p.text:77D2DCFD.text:77D2DCFD Filename = word ptr -20Ch.text:77D2DCFD var_4 = dword ptr -4.text:77D2DCFD arg_0 = dword ptr 8.text:77D2DCFD arg_4 = dword ptr 0Ch.text:77D2DCFD hModule = dword ptr 10h.text:77D2DCFD arg_C = dword ptr 14h.text:77D2DCFD arg_10 = dword ptr 18h.text:77D2DCFD.text:77D2DCFD mov edi, edi.text:77D2DCFF push ebp.text:77D2DD00 mov ebp, esp.text:77D2DD02 sub esp, 20Ch.text:77D2DD08 mov eax, _security_cookie.text:77D2DD0D push esi.text:77D2DD0E mov esi, ebp+hModule.text:77D2DD11 test esi, esi.text:77D2DD13 push edi.text:77D2DD14 mov edi, ebp+arg_4.text:77D2DD17 mov ebp+var_4, eax.text:77D2DD1A jz short loc_77D2DD33.text:77D2DD1C push 104h ; nSize.text:77D2DD21 lea eax, ebp+Filename.text:77D2DD27 push eax ; lpFilename.text:77D2DD28 push esi ; hModule.text:77D2DD29 call ds:_imp_GetModuleFileNameW12 ; GetModuleFileNameW(x,x,x).text:77D2DD2F test eax, eax.text:77D2DD31 jz short loc_77D2DD52.text:77D2DD33.text:77D2DD33 loc_77D2DD33: ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+1Dj.text:77D2DD33 push ebp+arg_10.text:77D2DD36 mov eax, esi.text:77D2DD38 push edi.text:77D2DD39 push ebp+arg_0.text:77D2DD3C neg eax.text:77D2DD3E push ebp+arg_C.text:77D2DD41 sbb eax, eax.text:77D2DD43 lea ecx, ebp+Filename.text:77D2DD49 and eax, ecx.text:77D2DD4B push eax.text:77D2DD4C push esi.text:77D2DD4D call _SetWindowsHookEx24 ; _SetWindowsHookEx(x,x,x,x,x,x).text:77D2DD52.text:77D2DD52 loc_77D2DD52: ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+34j.text:77D2DD52 mov ecx, ebp+var_4.text:77D2DD55 pop edi.text:77D2DD56 pop esi.text:77D2DD57 call _security_check_cookie4 ; _security_check_cookie(x).text:77D2DD5C leave.text:77D2DD5D retn 14h.text:77D2DD5D _SetWindowsHookExAW20 endp.text:77D2DD5D.text:77D2DD65 ; _stdcall _SetWindowsHookEx(x, x, x, x, x, x).text:77D2DD65 _SetWindowsHookEx24 proc near ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+50p.text:77D2DD65.text:77D2DD65 var_10 = byte ptr -10h.text:77D2DD65 var_8 = dword ptr -8.text:77D2DD65 var_4 = dword ptr -4.text:77D2DD65 arg_0 = dword ptr 8.text:77D2DD65 arg_4 = dword ptr 0Ch.text:77D2DD65 arg_8 = dword ptr 10h.text:77D2DD65 arg_C = dword ptr 14h.text:77D2DD65 arg_10 = dword ptr 18h.text:77D2DD65 arg_14 = dword ptr 1Ch.text:77D2DD65.text:77D2DD65 mov edi, edi.text:77D2DD67 push ebp.text:77D2DD68 mov ebp, esp.text:77D2DD6A sub esp, 10h.text:77D2DD6D push ebp+arg_4.text:77D2DD70 and ebp+var_4, 0.text:77D2DD74 lea eax, ebp+var_10.text:77D2DD77 push eax.text:77D2DD78 mov ebp+var_8, eax.text:77D2DD7B call ds:_imp_RtlInitUnicodeString8 ; RtlInitUnicodeString(x,x).text:77D2DD81 push ebp+arg_14.text:77D2DD84 push ebp+arg_10.text:77D2DD87 push ebp+arg_C.text:77D2DD8A push ebp+arg_8.text:77D2DD8D push ebp+var_8.text:77D2DD90 push ebp+arg_0.text:77D2DD93 call _NtUserSetWindowsHookEx24 ; NtUserSetWindowsHookEx(x,x,x,x,x,x).text:77D2DD98 leave.text:77D2DD99 retn 18h.text:77D2DD99 _SetWindowsHookEx24 endp.text:77D2DD99.text:77D2DDA1 ; _stdcall NtUserSetWindowsHookEx(x, x, x, x, x, x).text:77D2DDA1 _NtUserSetWindowsHookEx24 proc near ; CODE XREF: _SetWindowsHookEx(x,x,x,x,x,x)+2Ep.text:77D2DDA1 mov eax, 1225h.text:77D2DDA6 mov edx, 7FFE0300h.text:77D2DDAB call dword ptr edx.text:77D2DDAD retn 18h.text:77D2DDAD _NtUserSetWindowsHookEx24 endp我们看这里 .text:77D2DDA1 mov eax, 1225h里面有和ssdt一样的调用号 但是有个问题 NtUserSetWindowsHookEx在user32里面没有导出,我们需要多次搜索才行Copy codeHHOOK STDCALL NtUserSetWindowsHookEx (HINSTANCE Mod, PUNICODE_STRING UnsafeModuleName, DWORD ThreadId, int HookId, HOOKPROC HookProc, BOOL Ansi)这个就是原型 不过搜索起来确实是比较麻烦的,不知道还有无其他好办法了 三。如何hook似乎这个问题并不大,shadow ssdt和ssdt本质上都是1个地址表,最为简单的方法是把你的函数替换地址表的对应项,具体hook代码甚至可以完全照抄ssdt的,这里只说1下几个偶遇到的小问题1。win32k.sys不是常在内存的,如果不是GUI线程,shadow ssdt地址无效解决办法:1。在driverdispatch中hokkdriverdispatch是位于执行driveriocontrol的线程上下文的我们使用1个GUI线程去driveriocontrol2。attachtoprocess通常 我们使用cerss.exeCopy codeHANDLE GetCsrPid()HANDLE Process, hObject;HANDLE CsrId = (HANDLE)0;OBJECT_ATTRIBUTES obj;CLIENT_ID cid;UCHAR Buff0x100;POBJECT_NAME_INFORMATION ObjName = (PVOID)&Buff;PSYSTEM_HANDLE_INFORMATION_EX Handles;ULONG r;Handles = GetInfoTable(SystemHandleInformation);if (!Handles) return CsrId;for (r = 0; r NumberOfHandles; r+)if (Handles-Informationr.ObjectTypeNumber = 21) /Port objectInitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);cid.UniqueProcess = (HANDLE)Handles-Informationr.ProcessId;cid.UniqueThread = 0;if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)if (NT_SUCCESS(ZwDuplicateObject(Process,(HANDLE)Handles-Informationr.Handle,NtCurrentProcess(),&hObject,0, 0, DUPLICATE_SAME_ACCESS)if (NT_SUCCESS(ZwQueryObject(hObject,ObjectNameInformation,ObjName,0x100, NULL)if (ObjName-Name.Buffer &!wcsncmp(LWindowsApiPort, ObjName-Name.Buffer, 20)CsrId = (HANDLE)Handles-Informationr.ProcessId;ZwClose(hObject);ZwClose(Process);ExFreePool(Handles);return CsrId;然后我们KeAttachProcessCopy codentStatus = PsLookupProcessByProcessId(GetCsrPid(), &EProcess);if (!NT_SUCCESS( ntStatus )DbgPrint(PsLookupProcessByProcessId()n);return ntStatus;KeAttachProcess(EProcess);3.使用MDL映射一块不分页内存,设置成可以写入不分页内存 ExAllocatePool(NonPagedPool即为不会被切换到pagefile的内存,是常驻在物理内存的,比较希缺,使用完毕以
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 输电线路迁改项目设备安装调试方案
- 2025四川九州电子科技股份有限公司招聘软件开发岗(平台)2人笔试历年备考题库附带答案详解试卷3套
- 2025北京东城文旅发展集团有限公司应届高校毕业生招聘7人笔试历年常考点试题专练附带答案详解试卷3套
- 2025中国化学工程集团有限公司校园招聘500人笔试历年常考点试题专练附带答案详解试卷3套
- 封丘公务员考试试题及答案
- 楚雄州卫健委公务员考试试题及答案
- 健康养老信息化建设方案
- 产城融合示范区安置区项目建设工程方案
- 北京区卫健委公务员考试试题及答案
- 安置房项目规划设计方案
- DB52-T1626-2021水利工程调整概算报告编制导则
- 第九章 幼儿园组织文化建设课件
- 抢救记录书写要求及模版
- 架线安全技术交底记录
- 人教版数学二年级上册期中考试试卷可打印
- 特种设备日管控、周排查、月调度管理制度
- MOOC 写作与表达-常熟理工学院 中国大学慕课答案
- 钢结构厂房加固施工方案
- 如何预防错混料
- 电气设备老化机理与寿命评估
- 中国梦英语讲解完美版ok
评论
0/150
提交评论