作者:倪茂志 邮件:backspray008@gmail.com 完成于:2005.12.20
文章分为八个部分:
一、为什么需要伪造内核 二、伪造内核文件 三、隐藏进程 四、隐藏内核模块 五、隐藏服务 六、隐藏注册表 七、隐藏文件 八、关于端口
另:建议先看看最后那些参考文章。
一、为什么需要伪造内核:
IceSword(以下简称IS)为了防止一些关键系统函数(包括所有服务中断表中的函数以及IS驱动部分要使用到的一些关键函数)被patch,它直接读取内核文件(以下简称“ntoskrnl.exe”),然后自己分析ntoskrnl.exe的PE结构来获取关键系统函数的原始代码并且把当前内核中所有的关键系统函数还原为windows默认状态,这样保证了IS使用到的函数不被patch过。也许你会想如果我们把还原后的函数再进行patch不还是能躲的过去吗?笔者也试过,还专门写了ring0的Timer来不停的patch自己想hook的函数。结果IS棋高一筹,在对所有的关键系统函数进行还原以后,IS每次调用这些函数前都会先把这些函数还原一次。这样还是能保证IS自己使用到的关键系统函数不被patch。也许你还会想缩小Timer的时间间隔,以致于IS对这些函数进行还原后,这些函数马上又被我们patch,这样IS再调用这些函数时不还是执行了我们patch过的函数。这种想法粗略看起来可以,但你仔细一想就知道是不行的。
治病还是得治本,也许你想过不如直接修改ntoskrnl.exe文件内容,使得IS一开始读入的就已经是我们patch过得函数内容,这样不就躲过去了。这种想法有两个很大的副作用:
1、在通常的默认情况下,windows的系统文件保护是打开的,要停止这种系统文件保护要付出很大的代价,有可能需要重启。
2、就算你停止了系统文件保护,也成功修改了ntoskrnl.exe,但是你不能保证系统每次都能正常关机 假如系统非法关机重启,由于你还来未对ntoskrnl.exe进行还原,此时会发生什么情况我也就不多说了。
而伪造内核文件就很好的避免了上面谈的两大副作用。主要处理下面三个点:
1、截获并修改IS打开ntoskrnl.exe消息,使它指向我要伪造的内核文件(假设为“otoskrnl.exe”)
2、在内核文件中定位我们要修改的数据。
3、隐藏我们伪造的“otoskrnl.exe”,这点请看本文的第七部分。
二、 伪造内核文件:
先说一下本文hook函数的方式:
1、取该函数起始地址的前六个字节内容保留在unsigned char resume[6]中。
2、把构造的两条指令push xxxxxxxx(我们自己构造的函数地址) ret 保留到unsigned char crackcode[6](这两条指令刚好六个字节)中。
3、把该函数起始址的6个字节替换成crackcode[6]的内容。这样系统调用该函数时就会先跳到xxxxxxxx地址去执行我们构造的函数。
而我们构造的xxxxxxxx函数的主要结构如下:
1、把我们hook的那个函数起始的前6个字节用resume[6]内容进行还原。
2、对传递的程序参数进行处理等。
3、调用被还原后的函数。
4、此时可以处理函数返回后的数据等。
5、把还原后的那个函数的起始地址前6个字节再用crackcode[6]内容进行替换。
6、返回。
IS是通过IoCreateFile函数来打开ntoskrnl.exe,因此我们只要hook这个函数,并检查其打开的文件名,如果是打开ntoskrnl.exe的话,我们把文件名替换成otoskrnl.exe再扔回去就OK了。这样所有针对于ntoskrnl.exe文件的操作都会指向otoskrnl.exe, 当然前提是你在进入驱动前记得先把ntoskrnl.exe在原目录下复制一份并命名为otoskrnl.exe。
关于我们要修改的数据在ntoskrnl.exe中偏移的算法也很简单,这里给出公式如下:
函数在中文件偏移=当前函数在内存中的地址 - 当前函数所在驱动模块的起始地址
举个例子来说,假设IoCreateFile在内核中的内存地址是0x8056d1234,由于它是在内存中ntoskrnl.exe模块中,假设ntoskrnl.exe起始地址是0x8045d000。那么IoCreateFile在磁盘上的ntoskrnl.exe文件中的偏移就是0x8056d123-0x8045d000=0x110123了。
再进行详细点说明:假设你对IoCreateFile函数进行了patch,使得该函数起始地址的6前六节的数据XXXXXX变成了YYYYYY。那么你只要打开otoskrnl.exe,把文件偏移调整到上面所说的0x110123处,在写入6个字节的数据YYYYYY。那么当IS打开otoskrnl.exe的话,读出的数据就是YYYYYY了!
下面的代码实现两个功能,一个功能就是hook了IoCreateFile函数,使的所有指向ntoskrnl.exe的操作都指向otoskrnl.exe。另外一个功能就是进行伪造内核(函数RepairNtosFile( DWORD FunctionOffset, DWORD RepairDataPtr)),其中FunctionOffset参数内容就是我们要hook的函数在内存中的地址。RepairDataPtr是指向字符crackcode[6]第一个字节的指针。主要功能就是先把要hook的函数地址在otoskrnl.exe文件中进行定位,然后再把crackcode[6]内容写进去。
#include "ntddk.h" #include "stdarg.h" #include "stdio.h" #include "ntiologc.h" #include "string.h"
#define DWORD unsigned long #define WORD unsigned short #define BOOL unsigned long
PCWSTR NTOSKRNL=L"ntoskrnl.exe"
unsigned char ResumCodeIoCreateFile[6]; unsigned char CrackCodeIoCreateFile[6];
typedef NTSTATUS ( *IOCREATEFILE )(
OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG Disposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength, IN CREATE_FILE_TYPE CreateFileType, IN PVOID ExtraCreateParameters OPTIONAL, IN ULONG Options );
IOCREATEFILE OldIoCreateFile;
DWORD GetFunctionAddr( IN PCWSTR FunctionName) { UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName ); return (DWORD)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
NTSTATUS RepairNtosFile( DWORD FunctionOffset, DWORD RepairDataPtr) { NTSTATUS Status; HANDLE FileHandle; OBJECT_ATTRIBUTES FObject; IO_STATUS_BLOCK IOSB; UNICODE_STRING FileName; LARGE_INTEGER NtosFileOffset;
RtlInitUnicodeString ( &FileName, L"\\SystemRoot\\system32\\otoskrnl.exe" );
InitializeObjectAttributes ( &FObject, &FileName, OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwCreateFile( &FileHandle, FILE_WRITE_DATA+FILE_WRITE_ATTRIBUTES+FILE_WRITE_EA, &FObject, &IOSB, & [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] ... 下一页 >> |