ssdt学习笔记.docx
《ssdt学习笔记.docx》由会员分享,可在线阅读,更多相关《ssdt学习笔记.docx(20页珍藏版)》请在冰豆网上搜索。
![ssdt学习笔记.docx](https://file1.bdocx.com/fileroot1/2023-2/6/6f9d89f6-a479-46d2-8f1c-3830047859a4/6f9d89f6-a479-46d2-8f1c-3830047859a41.gif)
ssdt学习笔记
标题:
【原创】shadowssdt学习笔记
(一)
(二)
作者:
zhuwg
时间:
2007-12-22,22:
01:
29
链接:
1。
取得shadowssdt真实地址
系统只提供了KeServiceDescriptorTable导出
KeServiceDescriptorTableShadow是个未导出结构
定义
Copycode
typedefstruct_SYSTEM_SERVICE_TABLE
{
PNTPROCServiceTable;//arrayofentrypoints
PDWORDCounterTable;//arrayofusagecounters
DWORDServiceLimit;//numberoftableentries
PBYTEArgumentTable;//arrayofbytecounts
}
SYSTEM_SERVICE_TABLE,
*PSYSTEM_SERVICE_TABLE,
**PPSYSTEM_SERVICE_TABLE;
//-----------------------------------------------------------------------------------------------------------
typedefstruct_SERVICE_DESCRIPTOR_TABLE
{
SYSTEM_SERVICE_TABLEntoskrnl;//ntoskrnl.exe(nativeapi)
SYSTEM_SERVICE_TABLEwin32k;//win32k.sys(gdi/usersupport)
SYSTEM_SERVICE_TABLETable3;//notused
SYSTEM_SERVICE_TABLETable4;//notused
}
SYSTEM_DESCRIPTOR_TABLE,
*PSYSTEM_DESCRIPTOR_TABLE,
**PPSYSTEM_DESCRIPTOR_TABLE;
其实KeServiceDescriptorTableShadow包含4个子结构,其中第一个就是ntoskrnl.exe(nativeapi),和KeServiceDescriptorTable指向一样我们真正需要获得的是第二个win32k.sys(gdi/usersupport),第三个和第四个一般不使用
定位方法
1。
硬编码
Copycode
//forxp
if(gKernelVersion==WINXP)
KeServiceDescriptorTableShadow=KeServiceDescriptorTable-0x40;
//for2k
if(gKernelVersion==WIN2K)
KeServiceDescriptorTableShadow=KeServiceDescriptorTable+0xE0;
2。
搜索KeAddSystemServiceTable
反汇编代码可以看出
Copycode
lkd>uKeAddSystemServiceTablel40
nt!
KeAddSystemServiceTable:
805ba5898bffmovedi,edi
805ba58b55pushebp
805ba58c8becmovebp,esp
805ba58e837d1803cmpdwordptr[ebp+18h],3
805ba592774ejant!
KeAddSystemServiceTable+0x6b(805ba5e2)
805ba5948b4518moveax,dwordptr[ebp+18h]
805ba597c1e004shleax,4
805ba59a83b880a6558000cmpdwordptrnt!
KeServiceDescriptorTable(8055a680)[eax],0
805ba5a1753fjnent!
KeAddSystemServiceTable+0x6b(805ba5e2)
805ba5a38d8840a65580leaecx,nt!
KeServiceDescriptorTableShadow(8055a640)[eax]
805ba5a9833900cmpdwordptr[ecx],0
805ba5ac7534jnent!
KeAddSystemServiceTable+0x6b(805ba5e2)
805ba5ae837d1801cmpdwordptr[ebp+18h],1
805ba5b28b5508movedx,dwordptr[ebp+8]
805ba5b556pushesi
805ba5b68b7510movesi,dwordptr[ebp+10h]
805ba5b957pushedi
805ba5ba8b7d14movedi,dwordptr[ebp+14h]
805ba5bd8911movdwordptr[ecx],edx
805ba5bf8b4d0cmovecx,dwordptr[ebp+0Ch]
805ba5c2898844a65580movdwordptrnt!
KeServiceDescriptorTableShadow+0x4(8055a644)[eax],ecx
805ba5c889b048a65580movdwordptrnt!
KeServiceDescriptorTableShadow+0x8(8055a648)[eax],esi
805ba5ce89b84ca65580movdwordptrnt!
KeServiceDescriptorTableShadow+0xc(8055a64c)[eax],edi
805ba5d40f855a3e0300jnent!
KeAddSystemServiceTable+0x4d(805ee434)
805ba5da5fpopedi
805ba5dbb001moval,1
805ba5dd5epopesi
805ba5de5dpopebp
805ba5dfc21400ret14h
805ba5e232c0xoral,al
805ba5e4ebf8jmpnt!
KeAddSystemServiceTable+0x6d(805ba5de)
805ba5e690nop
805ba5e790nop
805ba5e890nop
805ba5e990nop
805ba5ea90nop
搜索办法很简单
就是找到
805ba5a38d8840a65580leaecx,nt!
KeServiceDescriptorTableShadow(8055a640)[eax]
的8d8840a65580leaecx,nt!
KeServiceDescriptorTableShadow
代码如下
Copycode
voidGetKeServiceDescriptorTableShadow()
{
PUCHARcPtr,pOpcode;
ULONGLength;
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
其实个人更加倾向这个办法稳定安全可靠,上面那个代码也许会受到以后系统代码变化影响但是这个肯定不会
Copycode
GetServiceDescriptorTableShadowAddressprocusesesiediebx
localdwThreadId:
DWORD
xorebx,ebx;=NULL.AssumeServiceDescriptorTableShadowwillbenotfound
moveax,KeServiceDescriptorTable
movesi,[eax]
;FindKTHREAD.ServiceTablefield
;Fornon-GUIthreadsthisfield==KeServiceDescriptorTable
;anditpointstoServiceDescriptorTable
;ForGUIthreads
;ServiceDescriptorTableShadow
invokeKeGetCurrentThread
movedi,200h-4
.whileedi
.break.ifdwordptr[eax][edi]==esi
decedi
.endw
.ifedi!
=0
;edi=offsettoServiceTablefieldinKTHREADstructure
movdwThreadId,080h
.whiledwThreadId<400h
pusheax;reserveDWORDonstack
invokePsLookupThreadByThreadId,dwThreadId,esp
popecx;->ETHREAD/KTHREAD
.ifeax==STATUS_SUCCESS
pushdwordptr[ecx][edi]
fastcallObfDereferenceObject,ecx
popeax
.ifeax!
=esi
movedx,MmSystemRangeStart
movedx,[edx]
movedx,[edx]
.ifeax>edx;somestupiderrorchecking
movebx,eax
invokeDbgPrint,$CTA0("FindShadowTable:
FoundinthreadwithID:
%X\n"),dwThreadId
.break
.endif
.endif
.endif
adddwThreadId,4
.endw
.endif
moveax,ebx
ret
GetServiceDescriptorTableShadowAddressendp
4.mj0011所说的搜索有效内存地址的办法
Copycode
/*
definestructureforthesystemservicetable
*/
structSYS_SERVICE_TABLE{
void**ServiceTable;
unsignedlongCounterTable;
unsignedlongServiceLimit;
void**ArgumentsTable;
};
SYSTEM_DESCRIPTOR_TABLEKeServiceDescriptorTableShadow;
/*
DefineKeServiceDescriptorTablebasedontheSSTstructure
*/
externstructSYS_SERVICE_TABLE*KeServiceDescriptorTable;
/*
DeclarefunctionGetServiceDescriptorShadowTableAddress()
*/
//structSYS_SERVICE_TABLE*GetServiceDescriptorShadowTableAddress();
/*
DeclaretheKeAddSystemServiceTable.Thisisjusta
handletothecallfunction,itwillbeusedbythefunction
abovetoobtainthecorrectaddressoftheKeServiceDescriptorShadowTable
*/
__declspec(dllimport)KeAddSystemServiceTable(ULONG,ULONG,ULONG,ULONG,ULONG);
structSYS_SERVICE_TABLE*GetServiceDescriptorShadowTableAddress()
{
//First,obtainapointertoKeAddSystemServiceTable
unsignedchar*check=(unsignedchar*)KeAddSystemServiceTable;
inti;
//InitializeaninstanceofSystemServiceTable,willbeusedto
//obtainanaddressfromKeAddSystemServiceTable
structSYS_SERVICE_TABLE*rc=0;
//Make100attemptstomatchavalidaddresswiththatofKeServiceDescriptorTable
for(i=0;i<=99;i++){
__try{
//trytoobtainanaddressfromKeAddSystemServiceTable
rc=*(structSYS_SERVICE_TABLE**)check;
//ifthisaddressisNOTvalidORititselfistheaddressof
//KeServiceDescriptorTableORitsfirstentryisNOTequal
//tothefirstentryofKeServiceDescriptorTable
if(!
MmIsAddressValid(rc)||(rc==KeServiceDescriptorTable)
||(memcmp(rc,KeServiceDescriptorTable,sizeof(*rc))!
=0)){
//Proceedwiththenextaddress
check++;
//don'tforgettoresettheoldaddress
rc=0;
}
}__except(EXCEPTION_EXECUTE_HANDLER){rc=0;}
//whentheloopiscompleted,checkifitproducedavalidaddress
if(rc)
//becauseifitdidn't,wefailedtofindtheaddressofKeServiceDescriptorTableShadow
break;
}
//otherwise,thereisavalidaddress!
Soreturnit!
returnrc;
}
二。
函数名定位
这个似乎没有多少好办法,解析pdb可以是可以但是很麻烦
不过还好的是同一个版本的系统调用号一样
所以只需要3套2kxp2k3的调用号就可以完成hook
pdb办法
SymInitialize初始化
SymSetSearchPath“srv**symbols*
SymLoadModule
SymGetSymFromName
老v曾经发出1个获取shadow地址和函数名称的工具使用他可以很方便的获取
具体代码可以F5查看
以上读取pdb的方法测试使用的可以的
但是实际使用很麻烦
经过分析我找到了1个比较好的定位办法
我们以SetWindowsHookExA为例子
Copycode
.text:
77D311D1;HHOOK__stdcallSetWindowsHookExA(intidHook,HOOKPROClpfn,HINSTANCEhmod,DWORDdwThreadId)
.text:
77D311D1public_SetWindowsHookExA@16
.text:
77D311D1_SetWindowsHookExA@16procnear
.text:
77D311D1
.text:
77D311D1idHook=dwordptr8
.text:
77D311D1lpfn=dwordptr0Ch
.text:
77D311D1hModule=dwordptr10h
.text:
77D311D1dwThreadId=dwordptr14h
.text:
77D311D1
.text:
77D311D1movedi,edi
.text:
77D311D3pushebp
.text:
77D311D4movebp,esp
.text:
77D311D6push2;int
.text:
77D311D8push[ebp+dwThreadId];int
.text:
77D311DBpush[ebp+hModule];hModule
.text:
77D311DEpush[ebp+lpfn];int
.text:
77D311E1push[ebp+idHook];int
.text:
77D311E4call_SetWindowsHookExAW@20;SetWindowsHookExAW(x,x,x,x,x)
.text:
77D311E9popebp
.text:
77D311EAretn10h
.text:
77D311EA_SetWindowsHookExA@16endp
.text:
77D2DCFD;int__stdcallSetWindowsHookExAW(int,int,HMODULEhModule,int,int)
.text:
77D2DCFD_SetWindowsHookExAW@20procnear;CODEXREF:
SetWindowsHookExW(x,x,x,x)+13p
.text:
77D2DCFD;SetWindowsHookExA(x,x,x,x)+13p
.text:
77D2DCFD
.text:
77D2DCFDFilename=wordptr-20Ch
.text:
77D2DCFDvar_4=dwordptr-4
.text:
77D2DCFDarg_0=dwordptr8
.text:
77D2DCFDarg_4=dwordptr0Ch
.text:
77D2DCFDhModule=dwordptr10h
.text:
77D2DCFDarg_C=dwordptr14h
.text:
77D2DCFDarg_10=dwordptr18h
.text:
77D2DCFD
.text:
77D2DCFDmovedi,edi
.text:
77D2DCFFpushebp
.text:
77D2DD00movebp,esp
.text:
77D2DD02subesp,20Ch
.text:
77D2DD08moveax,___security_cookie
.text:
77D2DD0Dpushesi
.text:
77D2DD0Emovesi,[ebp+hModule]
.text:
77D2DD11testesi,esi
.text:
77D2DD13pushedi
.text:
77D2DD14movedi,[ebp+arg_4]
.text:
77D2DD17mov[ebp+var_4],eax
.text:
77D2DD1Ajzshortloc_77D2DD33
.text:
77D2DD1Cpush104h;nSize
.text:
77D2DD21leaeax,[ebp+Filename]
.text:
77D2DD27pusheax;lpFilename
.text:
77D2DD28pushesi;hModule
.text:
77D2DD29callds:
__imp__GetModuleFileNameW@12;GetModuleFileNameW(x,x,x)
.text:
77D2DD2Ftesteax,eax
.text:
77D2DD31jzshortloc_77D2DD52
.text:
77D2DD33
.text:
77D2DD33loc_77D2DD33:
;CODEXREF:
SetWindowsHookExAW(x,x,x,x,x)+1Dj
.text:
77D2DD33push[ebp+arg_10]
.text:
77D2DD36moveax,esi
.text:
77D2DD38pushedi
.text:
77D2DD39push[ebp+arg_0]
.text:
77D2DD3Cnegeax
.text:
77D2DD3Epush[ebp+arg_C]
.text:
77D2DD41sbbeax,eax
.text:
77D2DD43leaecx,[ebp+Filename]
.text:
77D2DD49andeax,ecx
.text:
77D2DD4Bpusheax
.text:
77D2DD4Cpushesi
.text:
77D2DD4Dcall__SetWindowsHookEx@24;_SetWindowsHookEx(x,x,x