存档

‘内核编程’ 分类的存档
1,749 views

NT4 操作系统的 NTFS 文件系统驱动源代码(以及 FastFat CDFS 源码)

2010年5月23日

很久以前从微软泄漏出来的 NT 4 源代码, 拥有的人多, 研究的人少. 由于今后工作中要经常同 NTFS 文件系统打交道, 就把这份源码的 NTFS 文件系统驱动部分的源代码扒拉下来, 改巴改巴. 就能编译通过了.

经过初步在 windows XP SP2 环境下测试, 本驱动不足的地方是不支持在资源管理器内通过拷贝粘贴的方式来复制或移动文件, 其他问题还不知道有没有.

能通过的编译环境有

  • VC 6 + ntddk2000
  • VS2008 + WDk 7600.16385.0

更改了几个地方
lfsprocs.h:

/*#define LfsReleaseLfcb(LFCB)           \
    if ((LFCB)->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) {\
        ExReleaseResource( &(LFCB)->Sync->Resource );     \
    }//*/
#define LfsReleaseLfcb(LFCB)                        \
    if ((LFCB)->Sync->Resource.OwnerEntry.OwnerThread == ExGetCurrentResourceThread()) {\
        ExReleaseResource( &(LFCB)->Sync->Resource );   \
    }

#define LfsAcquireLch(LCH)                           \
    ExAcquireResourceExclusive( &(LCH)->Sync->Resource, TRUE )

/*#define LfsReleaseLch(LCH)                        \
    if ((LCH)->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) { \
        ExReleaseResource( &(LCH)->Sync->Resource );   \
    }//*/
#define LfsReleaseLch(LCH)                  \
    if ((LCH)->Sync->Resource.OwnerEntry.OwnerThread == ExGetCurrentResourceThread()) { \
        ExReleaseResource( &(LCH)->Sync->Resource );        \
    }

restrsup.c logsup.c

TransactionStateNormal ;//TransactionActive;
TransactionStateIndoubt ;//TransactionPrepared;
TransactionStateCommittedNotify;//TransactionCommitted;

本来以为想移植到 xp 中会有不少困难,但实际过程中,我只是修改了很小一部分。

  • 其中包括 read 操作的一个死锁 bug. 这个 bug 的起因是:
    NtfsCommonRead 中如果是 pageio 的时候, 且是异步 read, MS 忘记把锁放进完成函数的 context 里了. 即无处释放这个锁.
  • NT 4 的代码少了 NtfsFsdPnp 例程, 这个例程在 NtCreatePagingFile -> PpPagePathAssign 中会调用. 本来我想参照 xp 的, 不过似乎没成功, 所以干脆直接返回 STATUS_SUCCESS, 貌似也没啥大问题, 也能成功换页.

—- weolar

下面是源代码和工程文件的下载链接

源代码 ntfs-4.zip

FastFat 文件系统及 CDFS 文件系统源码

延伸阅读:
NT Cache Manager 相关
NTFS 文件系统底层挖掘
在 VS 2008 内开发驱动程序的 “解决方案” 的编译链接选项的设置
NT 4 源码编译环境
ntfs工程精简版 update for VS 2005/2008/2010
【原创】六一献小礼:完整可编译NT4′s NTFS源码(可稳定替换xp原版ntfs.sys)

内核编程

939 views

在内核驱动中得到 KeServiceDescriptorTableShadow

2010年5月21日

头文件:

//
// svcdesctbl.h
//

#pragma once

typedef struct _KSERVICE_TABLE_DESCRIPTOR {
	PULONG_PTR Base;	// Service Table Base
	PULONG Count;		// Service Counter Table Base, Used only in checked build
	ULONG Limit;
	PUCHAR Number;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;

#define NUMBER_SERVICE_TABLES 2
__declspec(dllimport) KSERVICE_TABLE_DESCRIPTOR
		KeServiceDescriptorTable[NUMBER_SERVICE_TABLES];

KSERVICE_TABLE_DESCRIPTOR * Get_KeServiceDescriptorTableShadow ();

阅读全文…

内核编程 , ,

1,132 views

关于 IoGetDeviceObjectPointer

2010年5月19日

先看 IoGetDeviceObjectPointer() 的内部实现:

  1. 用 ZwOpenFile() 打开设备文件的 handle
  2. 用 ObReferenceObjectByHandle() 来得到 file object
  3. 用 IoGetRelatedDeviceObject() 来得到 device object
  4. 用 ZwClose() 来关闭这个 handle

WRK 1.2 源代码如下:
阅读全文…

内核编程, 技术心得 ,

1,193 views

枚举全局钩子

2010年3月17日

标 题: 枚举全局钩子
作 者: 一块三毛钱
邮箱: zhongts@163.com
时 间: 2005-06-19,21:23:16
链 接: http://bbs.pediy.com/showthread.php?t=14600

首先强调一点,本文给出的代码只在 WinXP+SP2 下测试通过,使用其他系统的朋友最好看懂代码,然后调试运行。如果不巧系统蓝屏可不要找我哦。:)

鼠标钩子、键盘钩子等大家一定是耳熟能详,在 Windows 环境下编程的朋友们肯定都和他们打过交道,比如说截获密码什么的都可以用到他们。本文将介绍一种办法可以枚举所有的全局钩子,找到到底是什么动态库创建了钩子(大部分全局钩子都需要通过动态库来实现)。

下图是程序运行后显示的所有的全局钩子,包括钩子函数在那个动态库中,也就是创建钩子的动态库。图中显示的钩子句柄是指得在当前进程中的句柄,不是系统范围的。比如说 MouseHook 添加了一个全局的鼠标钩子,那么在 explorer 中这个钩子的句柄和在 word 中的句柄是不同的(这一点我是通过 Icesword 观察到的),但都是 MouseHook 添加的钩子都在 mousehook.dll 动态库中。如果想获得 Icesword 一样的结果可以针对每一个进程枚举全局钩子(没试过)。l另外,如果鼠标钩子和键盘钩子不能够显示动态库,可以先动一动鼠标,摁几下键盘再刷新应该就可以显示。

之所以会写这篇文章是因为在编程板块中有一个主题说判断全局钩子的调用者,所以才想着能不能枚举出所有的全局钩子。但那个主题好像说的是钩子的调用者,又好像全局钩子指得是 Hook API 类型的钩子,没搞懂。在那个主题下 zworm 大侠好像说可以通过一个钩子链的东东来枚举钩子,不过大侠没有细说,我自己也没有在符号文件中找到有关钩子链的符号(我只会这一种办法找系统内部变量,比如活动进程链就可以通过这种办法找到位置),所以准备从 CallNextHookEx 函数慢慢往下追希望能够找到系统是怎么找到下一个钩子函数的。本文介绍的方法就是这样来的(另外有一个很重要的一点会在文章的最后提到)。
阅读全文…

内核编程 , ,

2,146 views

内核驱动 unresolved external symbol @__security_check_cookie@4

2010年2月27日

最近在用 winddk 7600.16385.0 开发驱动, 小心谨慎的按照这篇文章设置了编译连接参数, 在编译选项关闭了 buffer security check, 但工程里要用到 wdmsec.lib 静态库, 里面链接进了符号 __security_check_cookie@4, 因此我编译始终出错, 用了各种办法问题依旧, 中间甚至试图逆向 wdmsec.lib 静态库, 用 IDA 打开一看, 发现工程浩大, 只能放弃.

G(oogle) 啊 G啊, G 了好久, 在 这里 找到了解决方案:

将 bufferoverflowU.lib 静态库加入链接依赖列表. 问题貌似解决, 但其实是不对的.

后来用 depends 打开 sys 文件一看, 链接进了 kernel32.dll,

对于 ring 3 的应用程序, 这是很好的解决办法; 但对于内核驱动, 这是绝对不可以的.

看来 这里 才是解决问题的真正方法.

在源代码的最后添加如下代码, 然后在工程设置内添加 VS_IDE_BUILD 标记. 在链接设置内将入口点从 DriverEntry 改成 GsDriverEntry. 问题解决.

#ifdef	VS_IDE_BUILD
ULONG ___security_cookie = 0xbb40;
ULONG ___security_cookie_complement = 0xFFFF44BF;

NTSTATUS GsDriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegPath)
{
	LARGE_INTEGER tickCount;
	KeQueryTickCount(&tickCount);
	if(!___security_cookie || ___security_cookie == 0xbb40)
	{
		ULONG temp = (ULONG)&___security_cookie;
		temp = ((temp  >>  8 )  ^  tickCount.u.LowPart) & 0xffff;
		if(temp)
			___security_cookie = temp;
		else
			___security_cookie = tickCount.u.LowPart & 0xffff;
	}

	___security_cookie_complement = ~___security_cookie;
	return DriverEntry(DriverObject,RegPath);
}

void __fastcall __security_check_cookie(ULONG cookie)
{
	if(cookie != ___security_cookie || cookie & 0xffff0000)
		KeBugCheckEx(0x7f,cookie,___security_cookie,___security_cookie_complement,0);
}
#endif	// VS_IDE_BUILD

PS. 也可以这么解决, 如果 BufferSecurityCheck(/GS) 开关是打开的, 把入口点改成 GsDriverEntry@8, 并加上 BufferOverflowK.lib 静态库.

PPS. 原来, BufferOverflowK.lib 的意思是内核态的 BufferOverflow 库, BufferOverflowU.lib 是用户态的 BufferOverflow 库. That’s all.

延伸阅读:
C 语言库函数的连接
编译器的一些参数

内核编程, 技术心得 , ,

2,603 views

创建有导出函数的内核驱动程序

2010年2月27日

testsys.def

;testsys.def : Declares the module parameters for the DLL.

; LIBRARY      "testsys"

EXPORTS
    ; Explicit exports can go here
    SDK_ExportFunction1		@1
    SDK_ExportFunction2		@2

testsys.h

#ifndef _TESTSYS_H
#define _TESTSYS_H 1

extern void NTAPI SDK_ExportFunction1(ULONG nIndex) ;
extern void NTAPI SDK_ExportFunction2();

#endif

testsys.c

#include <ntddk.h>
#include "testsys.h"

void NTAPI SDK_ExportFunction1(ULONG nIndex)
{
    return ;
}

void NTAPI SDK_ExportFunction2()
{
    return ;
}

#pragma code_seg("INIT")
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	return STATUS_SUCCESS ;
}
#pragma code_seg()

阅读全文…

内核编程 , , ,

1,057 views

GetProcAddress and GetModuleHandle for kernel mode

2010年2月27日

link: http://alter.org.ua/en/docs/nt_kernel/procaddr/

Implementation of GetProcAddress and GetModuleHandle
for Windows NT3.51/NT4/2000/XP/2003/Vista kernel mode,
both 32 and 64 bit platforms

 

Methods description

I’m astonished, so many people ask questions like “How to get address of
some exported function from ntdll.dll dynamically, when we know only the name of
this function ?”
. People, please find the answer below. These are sources of
kernel-mode implementation of Win32 GetModuleHandle() and
GetProcAddress(). In general, this code (except
KernelGetModuleBase3()) should work not only for kernel-mode, but
for user-mode too if you use ntdll.dll

Main appliance of these functions is writing drivers with unified binary
(.SYS) those work under different NT OS versions. Together with
PsGetVersion() they give you a power to work wonders. Lets go. 

KernelGetModuleBase()

Standard and the most legal solution is to use
Nt/ZwQuerySystemInformation(SystemModuleInfo, …). We obtain list of
loaded modules, walk through it looking for required name and parse its export
section. Thats all – golden key is in our pocket. The only limitation is
presence of adequate NtQuerySystemInformation() implementation in
ntdll.dll. NT3 has not it at all. ReactOS has dummy do-nothing implementation. Not
too good. 

But it has greate advantage: it works under 64-bit platforms. We should just
update (thanks to Dmitri Arkhangelski, author of ultradefrag) SYSTEM_MODULE_INFORMATION structure
definition. 

KernelGetModuleBase3()

There is another implementation of GetModuleHandle() (thanks to
Egor Yuzik). It doesn’t use NtQuerySystemInformation which
appeared in NT4. The implementation itself – KernelGetModuleBase3(), is universal for
all Windows NT-family OS’es. The main idea is to use undocumented filed PVOID
SectionHandle
from DRIVER_OBJECT structure. This is actually pointer
to LDR_DATA_TABLE_ENTRY describing corresponding driver. All such
structures are linked in bidirectional list (see LoadOrder member in LDR_DATA_TABLE_ENTRY structure) and cover
all modules loaded in memory. The root record of the list (also called
PsLoadedModuleList) is located just before LDR_DATA_TABLE_ENTRY
structure
corresponding to NTOSKRNL.EXE

Note: Some interesting issues were found during further testing of new code. 
阅读全文…

内核编程 ,

1,380 views

文件加密标识 — OSR经典对白

2010年2月26日

第一篇
FS Filter Driver question

________________________________________
Dear NTDev folks,

We are writing a FileSystem Filter Driver, that mangles the contents of a particular file, such that:
1) the content is Mangled on Write, and
2) Unmangled on
Read.

Our Mangling actually increases the size of the file, and we also insert our own header data in the beginning of the file.

However we still want to present the “correct” file-length to the client programs (e.g. know that the data is actually mangled before it’s stored in the file).

We have been able to do this, to some degree, by handling the Read/Write IRPs, and modifying the length fields in the QueryInformation IRPs (for both File Information, and Directory Listings).

However, we are worried that interactions between the underlying
FileSystem Driver, and the Cache Manager may expose the real length of the file in some cases (e.g. through the FileSize field in the FSRTL_FCB_COMMON_HEADER structure stored in the FsContext field of the FileObject), or cause other problems. 

We are not able to find a good discussion on Data Modifying filter drivers in the IFS kit documentation or in the “Windows NT File System Internals” Book by Rajeev Nagar.

FileSystem Filter Drivers that do non-length-preserving
Encryption or Compression must face the same issues that we are coming across. 
We would really appreciate it if you folks could shed some
light on how the cache manager may affect FileSystem Filter Drivers that mangle the content of the file such that the actual file length changes, or if you could suggest some resources where this information is available.
阅读全文…

内核编程

1,088 views

用 WinDbg 连接 VMware 的客户系统

2010年2月24日

倒腾了两天,综合了网上的各个资料,终于能顺利地用 WinDbg 连上 VMware 上的客户系统了。

首先设置好微软符号服务器的以及下载到本地的路径, 像如下所示:

SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols

自然是为虚拟机上的系统设置好串口设备,如下图。

设置客户系统的启动配置文件 boot.ini ,在 [operating systems] 段中加入一行以调试模式启动的配置:
multi(0)disk(0)rdisk(0)partition(1)WINDOWS=”Microsoft Windows XP Professional Debug” /fastdetect /debugport=com1 /baudrate=115200

设置 WinDbg 快捷方式的命令行为:
“C:\Program Files\Debugging Tools for Windows\windbg.exe” -b -k com:pipe,port=\\.\pipe\com_1,resets=0

重新启动虚拟机上的系统,并选择新加入的启动配置进行启动,如下图。

启动 WinDbg ,稍等一下就可以连上了。
整个的探索过程比较郁闷。有些说法指出,在第 4 步的时候应先启动 WinDbg 然后再启动客户系统。但据我尝试,这样往往导致很长时间连不上,而先启动客户系统后立即启动 WinDbg 的连接效果却非常理想,所以在此沿用我的做法。
另外多说一句,应该先关闭客户系统之后再关闭 WinDbg ,否则关闭 WinDbg 后会导致客户系统无响应,并且在重启客户系统后会造成其硬盘的自检与修复。

在 Vista 客户机上的设置
激活 administrator 账户, 方法是, 右击 “计算机” -> “管理” -> “确定”(如图1)

“计算机管理(本地)” -> “本地用户和组” -> “用户” -> “Administrator” -> 右击, 选择 “属性” (如图2)

在 “常规” 选项卡内, 将 “账户已禁用” 上的勾选去掉, 如上图, 点击 “确定” 后退出.
从当前账户上注销, 在登录窗口上登录到 administrator 账户,
在 cmd 命令行上输入以下命令:

  1. bcdedit /copy {current} /d “Win Vista Debug”
    这时会复制出一个新的配置, 记下这个很长的 GUID字符串, 形如 {526D15B4-23B9-4906-B832-08641F7086C4}, 用这个 GUID 进行下一步
  2. bcdedit /debug {GUID} ON
  3. bcdedit /bootdebug {GUID} ON
  4. bcdedit /dbgsettings
    这个命令可以查看当前的调试配置
  5. bcdedit /timeout 7
    这个命令设置选择菜单的超时时间, 这里设为 7 秒

重新启动虚拟机, 选择 “Win Vista Debug” 配置即可进入调试模式.

重要更新
上述方法在 64 位的 win 7 主机系统和 64 位的 win 7 客户系统无效, 必须使用 virtualKD 工具.使用方法如下链接. VirtualKD + VMWare实现单机内核调试

延伸阅读:
借助 VMware 实现单机使用 WinDbg
WinDBG + VMware = 调试内核
VMWare+WinDbg搭建(驱动)调试环境

内核编程 ,

654 views

神秘代码,不解释

2009年12月17日