QQ电脑管家5.0是腾讯出的一款安全工具,几乎跟360安全卫士一样,因为腾讯最擅长的就是抄袭模仿别人,别人出三国杀,它就出英雄杀;别人出暴风影音,它就出qq影音;360出安全卫士,它就出qq电脑管家等,如下图:![]() 几乎360安全卫士有的功能它也同样具有,看来腾讯是绝不会让360在安全领域做大,最后威胁到它;因此它要跟360抢”地盘”(也就是用户)。但是你不得不承认腾讯虽然抄 袭别人,但是它去更注重在自己产品加入自己细腻、人性化的因素,因此它推出的“抄袭”作品比原有的软件产品的操作更简洁、使用更舒适,这就是为什么它能屡次抄袭模仿 成功。这些是题外话,言归正转,QQ管家5.0里面有个功能叫“财产保护”。Windows 2000以后的操作系统,每个进程都有2g的私有空间,这个进程空间的资源只能被所属进程访问,其他的进程无权访问,而病毒木马想要盗取帐号、密码以及其他一些重要信息就必 须访问其他进程的私有空间资源。因此病毒木马一般通过DLL注入或者全局钩子等来访问 这些进程的私有空间。因此当不明的DLL要注入到qq2011(正在被QQ电脑管家“财产保护”的一款软件)时就会立即被监控拦截。 下面我就给大家具体分析“财产保护”实现的原理,这个跟360保险箱的功能是一 样,并且它还有对网页操作、支付宝使用等的安全过滤,腾讯的产品总是让人看起来很有噱头。下面我就个大家介绍一下它拦截dll注入的实现原理。 通过挂钩KeUserModeCallback这个未公开的函数可以实现对Ke_LoadLibrary、 WH_KEYBOARD_LL等进行拦截,这个函数也可以用来在Ring0下调用Ring3代码,如果需要更进一步了解,可以去黑月教主的百度1^呢上去看看。下面我们来实现拦截dll注入的功能,解决两个问题: 1.如何挂钩keusermodecallback函数,有两种方式iat hook(qq电脑管家)、inline H00K(360 保险箱)。 2.如何拦截DLL注入,这个功能在KeUserModeCallback挂钩函数里实现。 实现的代码主要来源于对QQ电脑管家驱动文件TCSafeBox.sys的逆向分析,所以我尽量试 着去还原TCSafeBox.sys的代码,核心代码如下: ULONG StartHook(lN PVOID fake_funcaddrss, OUT PULONG Original_funcaddrss) { ULONG win32k_base; ULONG result; if (fake_funcaddrss && Original_funcaddrss) { win32k_base = GetModuleBase(''win32k.sys"); if ( win32k_base>0 ) result = IATHook((PVOID)win32k_base, "ntoskrnl. exe", 〃KeUserModeCallback〃,fake_funcaddrss, Original_funcaddrss); } else result = 0; return result; } ULONG GetModuleBase(lN PCHAR ModuleName) ULONG result; ULONG dwNeedSize=0; NTSTATUS status; PMODULES pModules; int i; char imagename[255]={0}; ZwQuerySystemInformation(SystemModuleInformation, NULL, 0,&dwNeedSize); pModules = ExAllocatePoolWithTag(NonPagedPool, dwNeedSize, 0); if (pModules) { memset(pModules, 0,dwNeedSize); status ZwQuerySystemInformation(SystemModu1eInformation, pModules, dwNeedSize, NULL); if (NT_SUCCESS(status)) while ( i<pModules->dwNumberOfModules ) { strcpy(imagename, pModules->smi[i]. ImageName + pModules->smi[i]. ModuleNameOffset); if (!strncmp(imagename, ModuleName, strlen(ModuleName))) { result = (ULONG)pModules->smi[i]. Base; break; ExFreePoolWithTag(pModules, 0); } return result; ULONG IATHook (IN PVOID ModlueBase, IN PCHAR ImportName, IN PCHAR ApiName, IN ULONG fakeFunctionAddr, OUT PULONG originalFuncAddr) { ULONG reslut; ULONG size; PIMAGE_IMPORT_DESCRIPTOR pImportModuleDirectory; DWORD dwRVAModuleName; PCHAR ModuleName; CHAR RvModuleNameIsZory; ULONG *OriginalFirstThunk; ULONG *FirstThunk; int i; PIMAGE_IMPORT_BY_NAME Imageimportbyname; ULONG result; result = 0; if (ModlueBase && ImportName && ApiName && fakeFunctionAddr && originalFuncAddr && !KeGetCurrentIrql()) { —try { size 二 0; pImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(ModlueBase, TRUE, IMAG E_DIRECTORY_ENTRY_IMPORT, &size); if (pImportModuleDirectory) { while (pImportModuleDirectory && pImportModu1eDirectory->Name) { dwRVAModuleName = pImportModuleDirectory->Name; //模块的 dll 名称 RvAModu 1 eNameIsZory = ((CHAR *) ModlueBase + dwRVAModuleName)== ModuleName = (CHAR *)ModlueBase + dwRVAModuleName; //先找到模块,再在模块里查找函数 |