经过互联网
搜索和不断探索,结果是QQ软件管家造成的灾难。进入
安全模式后,坚决
卸载QQ软件管家,重新
启动,
系统完全正常。
一个同事WindowsXP系统正常
执行,
关闭之后,第二天不能启动,症状的细节:
(1)可以
输入具有
网络功能的安全模式和安全模式。
(2)正常模式,没有windowxp滚动条开始
重启。
(3)进入安全模式,禁用主动重启,然后正常启动,出现
蓝屏,
报告tsfltmgr.sys
内存错误!
经过互联网搜索和不断探索,原来是一场灾难,QQ软件管家不得不责怪。进入安全模式后,坚决卸载QQ软件管家,
重新启动,系统完全正常。
下面是一篇转载的文章,供QQ
电脑管家分析,请
参考:
在QQ电脑管家tsfltmgr钩框架分析
QQ电脑管家新版本有一个tsfltmgr.sys驱动,这是由sysnap,使
驱动程序的一些简单的分析。我们看到了一个漂亮的钩子框架,并把它寄给大家。
首先,TsFltMgr是联系在一起的kifastcallentry功能,与钩点这里:
代码:
复制代码代码如下所示:
KD >你kifastcallentry + E3
NT!kifastcallentry + 0xe3:
8053dbb3 c1e902 SHR ECX,2
-------------------------------------------------------------------------
90 8053dbb6 NOP
90 8053dbb7 NOP
90 8053dbb8 NOP
8053dbb9 e962170c77 JMP tsfltmgr + 0x2320(f75ff320)
-------------------------------------------------------------------------
Jae 8053dbbe 0f83a8010000 NT!kisystemcallexit2 + 0x9f(8053dd6c)
8053dbc4 f3a5 REP MOVS DWORD PTR:{ } { ESI EDI,DWORD PTR }
8053dbc6 ffd3叫EBX
在SHR ECX原kifastcallentry,2说明应MOV EDI,ESP,CMP ESI,mmuserprobeaddress,共8字节,这是由3 tsfltmgr NOP和tsfltmgr取代了这里。
JMP将跳转到kifastcallentry_detour功能,和kifastcallentry_detour
函数的代码,例如,如下:
代码:
复制代码代码如下所示:
保存场景
pushfd
的pushad / kifastcallentry_filter函数调用,滤波器
EDI / /推进系统调用表的相应系统调用的
地址(或ssdtshadow SSDT地址)
EBX / /推在核函数对应的系统调用系统调用表。
功能 / /压入系统调用表在SysCall相应的核函数
电话kifastcallentry_filter / /电话kifastcallentry_filter滤波器
MOV { ESP + 10h },EAX / /改变相应的调用内核地址!
恢复站点
POPAD
指令代替popfd / / kifastcallentry功能跑,跳回到原来的功能
MOV EDI,ESP
CMP ESI,g_7fff0000
推g_jmpback
RET
要注意MOV ESP + 10h { },eax,叫kifastcallentry_filter.before救场后,指令pushad会导致寄存器EAX,EBX,ECX,EDX,ESP,EBP,ESI、EDI堆叠
顺序,并通过POPAD指令后恢复这些寄存器的值,所以MOV EAX 10h }和{ ESP +这里实际上重写存储与kifastcallentry_filter函数,即返回值栈EBX的值,
修改系统调用相应的内核函数地址。
kifastcallentry_filter是真正的过滤功能。已经解释了函数的
参数和返回值。经过
详细的实现,C
语言描述和叙述,例如,
代码:
复制代码代码如下所示:
页__stdcall kifastcallentry_filter(ULONG ulsyscallid,则ulsyscalladdr,普隆pulsyscalltable)
{
pfake_syscall pfakesyscall = null;如果(ulsyscallid = 0x400)
返回ulsyscalladdr;如果(pulsyscalltable = = g_kiservicetable ulsyscallid <= g_servicenum / / 0x11c)
{
pfakesyscall = g_fakesyscalltable { ulsyscallid }; / / SSDT
}
如果(pulsyscalltable = = g_keservicedescriptortable
g_keservicedescriptortable ulsyscallid <= g_servicenum / * 0x11c)。
{
pfakesyscall = g_fakesyscalltable { ulsyscallid }; / / SSDT
}
如果(pulsyscalltable = = g_w32pservicetableaddr ulsyscallid <= g_shadowservicenum / * * 0x29b)
{
pfakesyscall = g_fakesyscalltable { ulsyscallid + 1024 }; / / shadowssdt
}如果(pfakesyscall pfakesyscall -> ulfakesyscalladdr)
{
pfakesyscall -> ulorigsyscalladdr = ulsyscalladdr;
返回pfakesyscall -> ulfakesyscalladdr;
}
返回ulsyscalladdr;
}
需要交代一下,里面有TsFltMgr表,暂命名为g_fakesyscalltable,持有fake_syscall结构指针。表中的每一fake_syscall结构对应一个系统调用。表的前半部分对应于SSDT的系统调用,而1024个是在ShadowSSDT,对应的系统调用。
该fake_syscall结构大致如下(在非常多的领域中的
作用尚不明确)。
代码:
复制代码代码如下所示:
__fake_syscall__ { typedef struct
ulong XXX1;
页ulsyscallid; / /系统调用函数
ulong XXX3;
ultableindex页;
xxx5页;
ulcountforprework页;
ulcountforpostwork页;
xxx8页;
页ulorigsyscalladdr; / /真正的系统调用。
页ulfakesyscalladdr; / /假地址的系统调用
xxx11页;
xxx12页;
xxx13页;
hellip;hellip;
} fake_syscall,* * * ppfake_syscall pfake_syscall;
的kifastcallentry_filter功能是根据功能完成的,在g_fakesyscalltable电缆系统调用导致相应的pfakesyscall对象,然后推断系统调用需要挂钩,将需要承担实际的系统调用地址存放在pfakesyscall -> ulorigsyscalladdr,和pfakesyscall -> ulfakesyscalladdr作为系统调用返回错误的地址。
这样的方式来获得真正的系统调用地址动态可使钩框架tsfltmgr高度兼容,例如,它会在驱动程序的加载顺序是晚于TsFltMgr SSDT HOOK不失效,如tsksp.sys驱动通过QQ电脑管家本身。
我的测试系统(xp_sp2),对tsfltmgr钩子函数:
代码:
复制代码代码如下所示:
/ / SSDT:
NtCreateFile,NtCreateKey,只要,ntcreatesymboliclinkobject NtCreateThread,NtDeleteFile,NtDeleteKey,NtDeviceIoControlFile,NtDeleteValueKey,NtDuplicateObject,NtEnumerateValueKey,ntloaddriver,有NtOpenProcess,ntopensection、NtProtectVirtualMemory、NtQueryValueKey、NtRequestWaitReplyPort、ntsetcontextthread,ntsetinformationfile,ntsetsysteminformation,NtSetValueKey,ntsuspendthread,ntsystemdebugcontrol、NtTerminateProcess,ntterminatethread,NtWriteFile,ntwritevirtualmemory / / ShadowSSDT:
NtUserBuildHwndList,NtUserFindWindowEx,NtUserGetForegroundWindow,NtUserMoveWindow,NtUserQueryWindow,NtUserSendInput,NtUserSetParent,NtUserSetWindowLong,NtUserSetWindowPos,NtUserShowWindow,ntusersetwindowplacement,NtUserShowWindowAsync,NtUserWindowFromPoint
所有的伪系统函数都有统一的代码框架,伪系统函数的代码框架大致如下:
代码:
复制代码代码如下所示:
NTSTATUS __stdcall fakent_xxx(XXX)
{
pfake_syscall pfakesyscall;
页ulxxx = 0;
ulstatus页;
NTSTATUS状态;
ulonglong ulltickcount;
pfakesyscall = g_pfakesyscall_nt_xxx; / /系统调用相应的pfakesyscall对象
状态= status_access_denied;
这是 / /做
性能测试时,实际的版本号是假的g_bperformancetest
如果(g_bperformancetest){
ulltickcount = kequeryinterrupttime();
}
调用
处理前的系统调用!
interlockedincrement(pfakesyscall -> ulcountforprework);
ulstatus =
工作(ulxxx,pfakesyscall);
interlockeddecrement(pfakesyscall -> ulcountforprework);
—
如果(ulstatus!= 0xeeee0004 ulstatus!= 0xeeee0005)
{
origsyscall = pfakesyscall -> ulorigsyscalladdr * porigsyscall; / /调用原来的系统调用!
如果(porigsyscall nt_success(porigsyscall(XXX)))
{
调用后处理系统调用!
interlockedincrement(pfakesyscall -> ulcountforpostwork),
ulstatus =岗位(ulxxx),
interlockeddecrement(pfakesyscall -> ulcountforpostwork),
—
}
} / / 0xeeee0004应该拒绝电话,0xeeee0005应当约定叫。
如果(ulstatus = 0xeeee0005)
状态= status_success; / / psgetcurrentprocessid返回值这一回电话和不实用的,可能是多余的。
(psgetcurrentprocessid); / /似乎做性能测试时需要
如果(g_pfakesyscall_ntterminateprocess -> xxx5 ulltickcount g_bperformancetest){
性能测试(g_pfakesyscall_ntterminateprocess -> xxx13,ulltickcount);
返回状态;
}
以上是对tsfltmgr钩框架分析,祝你元宵节快乐~