2009年2月16日星期一

vista里的事

设置系统调试引导:
{GUID}要替换为bcdedit /copy {current} /d DebugEntry产生的值。
bcdedit /copy {current} /d DebugEntry
bcdedit /dbgsetting serial baudrate:115200 debugport:1
bcdedit /displayorder {current} {GUID}
bcdedit /debug {GUID} on

其实,简单的说bcdedit /debug on就可以打开调试引导,然而如果机器上还有以前的操作系统需要引导还要加入:
bcdedit /create {legacy} /d "XP"
bcdedit /set {legacy} device boot
bcdedit /set {legacy} path ntldr
bcdedit /displayorder {legacy} /addlast

一般的,使用bcdedit /displayorder {legacy} /addlast就可以了。

打开调试信息:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter
下建立项Debug Print Filter并建立DWORD值Defaut为0xfffffff。
Vista 主要设计目标客户机,所以打印调试信息需要用掩码打开,mask在Vista DDK
中有详细讲解。如果不想重启操作系统可以在windbg中直接设置mask。

VC6:
VC6带的编译器无法编译Vista DDK中的代码。错误信息是在DDK的一个头文件中
打印出来的,意思是这个版本的编译器无法被DDK支持。
SDK也有类似的情况,Windows 2003 sp1 SDK和之后版本也不再支持VC6
编译器。

libpcap:
在调试libpcap代码时,由于本机已经安装了libpcap,所以调试的时候系统使用了
早已安装好的release dll而不是要调试的刚刚编译好的debug dll。这样奇怪的事情
发生了。

DbgView:
OutPutDebugString是把User Mode调试信息发送给调试器的API。
如果使用OutPutDebugStrng的进程被Ring3调试器调试那么,调试信息会被发送
给Ring3调试器。如果有系统调试器工作,那么系统调试器也会收到。
而使用DbgView观察的User Mode调试信息是使用HooK。所以如果发现DbgView
不能工作应该先看看其capture菜单的设置情况。OSR上有关于Vista 64和DbgView
的相关讨论,但还没有来得急看。我们发现DbgView不能得到服务的调试信息,之
后发现,DbgView不能得到其它session的调试信息。原因是要访问别的Session
对象必须要加Global前缀并设置好权限。在新版的DbgView中要使用capture中的
Capture Global Win32。

nsi:
测试中发现,Vista在设置IP地址的时候使用了\device\nsi这个设备。我们上网搜索
到一篇相关文章,作者是CardMagic。那篇文章介绍了一种使用nsi来隐藏本机端口的
方法,因为以前的方法在Vista通通都废了。在HooK NtDeviceIoControlFile之
后我们得到了120013这个东西。事情还不算完,测试时发现Ping也会使用这个ControlCode,在对比了三个机器上数据结构格式之后,又加了一些判断。
在Ring3中,开UAC的时候dllhost用netsh.dll发送此controlcode,而没有UAC的
时候explorer会直接使用netsh.dll。

UAC:
万恶的UAC是最令我们痛苦的。在administrators组除了administrator之外,所有
的用户都使用标准用户权限,只有在询问用户之后才会被赋予真正的管理员权限。
在msconfig中可以配置UAC。需要提升权限的应用程序必须使用manifest文件编译
之后图标中就会出现一个小盾牌,但不幸的是这样也有例外,如果名字中patch等
字样的程序也会有小盾牌,并询问用户提升权限。Vista中新加入了一个
会话0隔离的概念,以前的操作系统会把高权限服务和普通应用程序放在同一个
会话之中,而Vista是把高权限的服务放在session 0之中,而session 0没有
打开桌面对象\windows\windowstations\winsta0,所以没有和用户交互的能力。
微软这么做是把高权限和与用户交互两种能力分开。我们以前的产品却有这样的
特性,比如客户端的某个服务,以高权限运行却又可以弹出提示窗口。现在在
微软的地盘上这是不被允许的。当然我们也不是没有办法。刚跳槽到微软内核组的
Mark Russinovich在谈到安全边界时提到CreateRemoteThread是个不安全的API,
Vista还有个完整性检查的概念(MIC)就是用来控制这个的,大概意思是低的打不开
高的,即使有权限。但我们不在这个概念的绞杀范围内,我们有正规的高权限
和高MIC的服务。这样用CreateRemoteThread注如到在session 1的winlogon.exe
让它来帮我们启动ClientUI。还可以用服务打开winlogon的token,在赋予我们的
ClientUI。但最后落到项目上还是顺着微软的意思把高权限和与用户交互功能分开。
我怀疑Mark Russinovich就是UAC的设计者,毕竟他是因为sony rootkit事件而名声大噪。有个设置UAC的工具叫TweakUAC.exe。

rename:
HooK NtSetInfomationFile把改名字的动作加以判断,阻止掉非法的改文件名操作。
但是用户可以在本路径下用剪切并复制创建一个名为"复件 filename.exe”的文件。
这样我们又HooK NtCreateFile判断创建的文件名是不是"复件 filename.exe"。
即使是这样还有漏洞,因为跨分区的文件操作还是不能阻止,但大家认为
这样熟悉文件系统并熟练使用cmd.exe的一般用户是不存在的。appmgr的一个不是
漏洞的漏洞是并没有判断NTFS文件系统特性:使用OBJECT ID访问文件。

peb中的事

CreateProcess->NtCreateProcess->NtCreateThread->NotifyRoutine
父进程把子进程参数设置好,子进程随后会再次自己处理数据。ImageFile的
buffer是ProcessParameters的偏移。

kd> ba r4 nt!PspCreateProcessNotifyRoutineCount

kd> .process /i 81477020
You need to continue execution (press 'g' ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.

kd> !peb
PEB at 7ffdf000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: No
ImageBaseAddress: 00400000
Ldr 00000000
*** unable to read Ldr table at 00000000
SubSystemData: 00000000
ProcessHeap: 00000000
ProcessParameters: 00020000
WindowTitle: 'C:\Program Files\Internet Explorer\iexplore.exe'
ImageFile: 'C:\Program Files\Internet Explorer\iexplore.exe'
CommandLine: '"C:\Program Files\Internet Explorer\iexplore.exe"'
DllPath: 'C:\Program Files\Internet Explorer;C:\WINDOWS\System32;C:\WINDOWS\system;C:\WINDOWS;.;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Internet Explorer;'
Environment: 00010000
=::=::\
ALLUSERSPROFILE=C:\Documents and Settings\All Users
APPDATA=C:\Documents and Settings\Administrator\Application Data
CLIENTNAME=Console
CommonProgramFiles=C:\Program Files\Common Files
COMPUTERNAME=DEBUG
ComSpec=C:\WINDOWS\system32\cmd.exe
HOMEDRIVE=C:
HOMEPATH=\Documents and Settings\Administrator
LOGONSERVER=\\DEBUG
NUMBER_OF_PROCESSORS=1
OS=Windows_NT
Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Internet Explorer;
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 8, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=0f08
ProgramFiles=C:\Program Files
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\WINDOWS
TEMP=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
TMP=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
USERDOMAIN=DEBUG
USERNAME=Administrator
USERPROFILE=C:\Documents and Settings\Administrator
windir=C:\WINDOWS
kd> dt -r -v nt!_PEB 7ffdf000
struct _PEB, 66 elements, 0x210 bytes
+0x000 InheritedAddressSpace : 0 ''
+0x001 ReadImageFileExecOptions : 0 ''
+0x002 BeingDebugged : 0 ''
+0x003 SpareBool : 0 ''
+0x004 Mutant : 0xffffffff
+0x008 ImageBaseAddress : 0x00400000
+0x00c Ldr : (null)
+0x010 ProcessParameters : 0x00020000 struct _RTL_USER_PROCESS_PARAMETERS, 28 elements, 0x290 bytes
+0x000 MaximumLength : 0x1000
+0x004 Length : 0x744
+0x008 Flags : 0
+0x00c DebugFlags : 0
+0x010 ConsoleHandle : 0xfffffffe
+0x014 ConsoleFlags : 0
+0x018 StandardInput : (null)
+0x01c StandardOutput : 0x00010001
+0x020 StandardError : (null)
+0x024 CurrentDirectory : struct _CURDIR, 2 elements, 0xc bytes
+0x000 DosPath : struct _UNICODE_STRING, 3 elements, 0x8 bytes
"--- memory read error at address 0x00000290 ---"
+0x008 Handle : (null)
+0x030 DllPath : struct _UNICODE_STRING, 3 elements, 0x8 bytes
"--- memory read error at address 0x00000498 ---"
+0x000 Length : 0x162
+0x002 MaximumLength : 0x164
+0x004 Buffer : 0x00000498 "--- memory read error at address 0x00000498 ---"
+0x038 ImagePathName : struct _UNICODE_STRING, 3 elements, 0x8 bytes
"--- memory read error at address 0x000005fc ---"
+0x000 Length : 0x5e
+0x002 MaximumLength : 0x60
+0x004 Buffer : 0x000005fc "--- memory read error at address 0x000005fc ---"
+0x040 CommandLine : struct _UNICODE_STRING, 3 elements, 0x8 bytes
"--- memory read error at address 0x0000065c ---"
+0x000 Length : 0x62
+0x002 MaximumLength : 0x64
+0x004 Buffer : 0x0000065c "--- memory read error at address 0x0000065c ---"
+0x048 Environment : 0x00010000
+0x04c StartingX : 0
+0x050 StartingY : 0
+0x054 CountX : 0
+0x058 CountY : 0
+0x05c CountCharsX : 0
+0x060 CountCharsY : 0
+0x064 FillAttribute : 0
+0x068 WindowFlags : 0x401
+0x06c ShowWindowFlags : 1
+0x070 WindowTitle : struct _UNICODE_STRING, 3 elements, 0x8 bytes
"--- memory read error at address 0x000006c0 ---"
+0x000 Length : 0x5e
+0x002 MaximumLength : 0x60
+0x004 Buffer : 0x000006c0 "--- memory read error at address 0x000006c0 ---"
+0x078 DesktopInfo : struct _UNICODE_STRING, 3 elements, 0x8 bytes
"--- memory read error at address 0x00000720 ---"
+0x000 Length : 0x1e
+0x002 MaximumLength : 0x20
+0x004 Buffer : 0x00000720 "--- memory read error at address 0x00000720 ---"
+0x080 ShellInfo : struct _UNICODE_STRING, 3 elements, 0x8 bytes
"--- memory read error at address 0x00000740 ---" +0x000 Length : 0
+0x002 MaximumLength : 2
+0x004 Buffer : 0x00000740 "--- memory read error at address 0x00000740 ---"
+0x088 RuntimeData : struct _UNICODE_STRING, 3 elements, 0x8 bytes
"" +0x000 Length : 0
+0x002 MaximumLength : 0
+0x004 Buffer : (null)
+0x090 CurrentDirectores : [32] struct _RTL_DRIVE_LETTER_CURDIR, 4 elements, 0x10 bytes
+0x000 Flags : 0
+0x002 Length : 0
+0x004 TimeStamp : 0
+0x008 DosPath : struct _STRING, 3 elements, 0x8 bytes
"" +0x014 SubSystemData : (null)
+0x018 ProcessHeap : (null)
+0x01c FastPebLock : (null)
+0x020 FastPebLockRoutine : (null)
+0x024 FastPebUnlockRoutine : (null)
+0x028 EnvironmentUpdateCount : 0
+0x02c KernelCallbackTable : (null)

How to find real cdrom device

文档名称:How to find real cdrom device
文档维护:welfear
创建时间:2008年6月17日


目录


0 背景

1 数据

2 问题


0 背景

本文档描述一种简单、可靠的找到CdRom的软方法。虚拟光驱的方法很多,要识别虚拟光驱不如可靠的枚举
系统中真实存在光驱。

1 数据

要枚举Windows NT中的内核设备栈,尤其是总线栈结构,必须借助devnode结构。但这个结构并没有公开,也
没有任何已知的文档参考。下面从驱动、设备、节点和它们的关系入手找到解决问题的方法。

假定使用PCI总线。Driver->DeviceObject和Device->AttachedDevice可以枚举下面的Device Object list。

kd> !drvobj 8174e870
Driver object (8174e870) is for:
\Driver\PCI
Driver Extension List: (id , addr)

Device Object list:
81743cd0 81743030 81741a30 81741c30
8175b630 81741e20


先看第一个,也就是Driver->DeviceObject指向的设备。

kd> !devobj 81743cd0
Device object (81743cd0) is for:
NTPNP_PCI0004 \Driver\PCI DriverObject 8174e870
Current Irp 00000000 RefCount 0 Type 00000022 Flags 00001040
DevExt 81743d88 DevObjExt 81743e68 DevNode 817436a8
ExtensionFlags (0000000000)
AttachedDevice (Upper) 817456d0 \Driver\DC21x4
Device queue is not busy.


在81743e68处,偏移0x20就是DevNode 817436a8。

kd> dd 81743e68
81743e68 0000000d 81743cd0 00000000 00000000
81743e78 00000000 817436a8 00000000 00000000
81743e88 00000000 00000000 00000000 00000000
81743e98 00000000 00000000 0b018010 42696350
81743ea8 00000300 00000000 04000000 04000000
81743eb8 00000000 00000000 ffffffff 00000000
81743ec8 00000000 00000000 00000000 00000000
81743ed8 00000000 00000000 00000000 00000000

DevNode的PDO又指回了0x81743cd0。同时我们也找到了它的兄弟和孩子:-)。

kd> !devnode 817436a8
DevNode 0x817436a8 for PDO 0x81743cd0
Parent 0x8175bf28 Sibling 0000000000 Child 0000000000
InstancePath is "PCI\VEN_1011&DEV_0009&SUBSYS_21140A00&REV_20\3&267a616a&0&50"
ServiceName is "DC21x4"
Flags (0x000421d8) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_HAS_BOOT_CONFIG,
DNF_BOOT_CONFIG_RESERVED, DNF_RESOURCE_ASSIGNED,
DNF_STARTED

下面是它的兄弟们的关系。

kd> !devnode 0x8174bb88
DevNode 0x8174bb88 for PDO 0x8176b030
Parent 0x817395c8 Sibling 0000000000 Child 0000000000
InstancePath is "IDE\DiskVirtual_HD______________________________1._1____\5&35dc7040&0&0.0.0"
ServiceName is "disk"
Flags (0x00040458) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_NO_RESOURCE_REQUIRED,
DNF_STARTED
UserFlags (0x00000008) DNUF_NOT_DISABLEABLE
DisableableDepends = 1 (including self)


kd> !devnode 0x817395c8
DevNode 0x817395c8 for PDO 0x81739c90
Parent 0x81743868 Sibling 0x817394e8 Child 0x8174bb88
InstancePath is "PCIIDE\IDEChannel\4&10bf2f88&0&0"
ServiceName is "atapi"
Flags (0x000421d8) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_HAS_BOOT_CONFIG,
DNF_BOOT_CONFIG_RESERVED, DNF_RESOURCE_ASSIGNED,
DNF_STARTED
UserFlags (0x00000008) DNUF_NOT_DISABLEABLE
DisableableDepends = 2 (including self)


kd> !devnode 0x81743868
DevNode 0x81743868 for PDO 0x81741a30
Parent 0x8175bf28 Sibling 0x81743788 Child 0x817395c8
InstancePath is "PCI\VEN_8086&DEV_7111&SUBSYS_00000000&REV_01\3&267a616a&0&39"
ServiceName is "intelide"
Flags (0x000421d8) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_HAS_BOOT_CONFIG,
DNF_BOOT_CONFIG_RESERVED, DNF_RESOURCE_ASSIGNED,
DNF_STARTED
DisableableDepends = 1 (from children)


kd> !devnode 0x81743788
DevNode 0x81743788 for PDO 0x81743030
Parent 0x8175bf28 Sibling 0x817436a8 Child 0000000000
InstancePath is "PCI\VEN_5333&DEV_8811&SUBSYS_00000000&REV_00\3&267a616a&0&40"
ServiceName is "vpc-s3"
Flags (0x000421d8) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_HAS_BOOT_CONFIG,
DNF_BOOT_CONFIG_RESERVED, DNF_RESOURCE_ASSIGNED,
DNF_STARTED
UserFlags (0x00000008) DNUF_NOT_DISABLEABLE
DisableableDepends = 1 (including self)


kd> !devnode 0x817436a8
DevNode 0x817436a8 for PDO 0x81743cd0
Parent 0x8175bf28 Sibling 0000000000 Child 0000000000
InstancePath is "PCI\VEN_1011&DEV_0009&SUBSYS_21140A00&REV_20\3&267a616a&0&50"
ServiceName is "DC21x4"
Flags (0x000421d8) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_HAS_BOOT_CONFIG,
DNF_BOOT_CONFIG_RESERVED, DNF_RESOURCE_ASSIGNED,
DNF_STARTED


kd> !devnode 0x817395c8
DevNode 0x817395c8 for PDO 0x81739c90
Parent 0x81743868 Sibling 0x817394e8 Child 0x8174bb88
InstancePath is "PCIIDE\IDEChannel\4&10bf2f88&0&0"
ServiceName is "atapi"
Flags (0x000421d8) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_HAS_BOOT_CONFIG,
DNF_BOOT_CONFIG_RESERVED, DNF_RESOURCE_ASSIGNED,
DNF_STARTED
UserFlags (0x00000008) DNUF_NOT_DISABLEABLE
DisableableDepends = 2 (including self)


kd> !devnode 0x817394e8
DevNode 0x817394e8 for PDO 0x81739ab0
Parent 0x81743868 Sibling 0000000000 Child 0x8176b868
InstancePath is "PCIIDE\IDEChannel\4&10bf2f88&0&1"
ServiceName is "atapi"
Flags (0x000421d8) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_HAS_BOOT_CONFIG,
DNF_BOOT_CONFIG_RESERVED, DNF_RESOURCE_ASSIGNED,
DNF_STARTED


kd> !devnode 0x8176b868
DevNode 0x8176b868 for PDO 0x8176b350
Parent 0x817394e8 Sibling 0000000000 Child 0000000000
InstancePath is "IDE\CdRomMS_C/DVD-ROM____________________________3.0_____\5&cfb56de&0&0.0.0"
ServiceName is "cdrom"
TargetDeviceNotify List - f 0xe1257f48 b 0xe1ed65c8
Flags (0x00040458) DNF_PROCESSED, DNF_ENUMERATED,
DNF_ADDED, DNF_NO_RESOURCE_REQUIRED,
DNF_STARTED

2 问题

本方法也存在问题。首先0x20的偏移并不是稳定的。当然我们也有办法,搜索DevObjExt指向的内存如果某个
地址值又指了回来,那么这个地址到DevObjExt就是偏移。不过,搜索内存依然有风险。

Forbid Setting Windows NT MAC Address

文档名称:Forbid Setting Windows NT MAC Address
文档维护:welfear
创建时间:2008年6月26日


目录

0 背景

1 分析

2 方法

3 结论


0 背景

让用户随意修改网卡的MAC地址而不是使用本来的物理地址其危害和麻烦都是显然的。当我们想去实现相关
功能的时候,我们发现MSDN提供的API有太多的限制。感谢yanky@dev.gsc.com用灰盒测试的方法找到了本文
最后的结论。习惯性的,我们会直接去网卡驱动里找实现方法而不是用Win32 API。

1 分析

下面是唯一的一段关于直接查询网卡信息的文字描述:
"Before an application can use IOCTL_NDIS_QUERY_GLOBAL_STATS,it must call the CreateFile function
to open a handle to the network adapter. In this CreateFile call, the application passes a
pointer to a null-terminated string that specifies the name of the device that NDIS registered.
For NT-based operating systems, the application can retrieve the name from the ServiceName value
of the "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\NetworkCards\Nnn" key
in the registry, where Nnn is the string for the adapter's instance number. The string should
be of the form "\\.\Xxx", where Xxx is the string for the adapter's service name."

可惜的是文字太少,还没有实质性的内容。那么,只好调试了。
我们对比HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\NetworkCards\Nnn
中的内容就可以找到网卡驱动的名字。下面是调试机器上的网卡。

kd> !object \device\{6A665379-4AE7-45D1-9C36-B3B0471287F6}
Object: 81652788 Type: (817a9ca0) Device
ObjectHeader: 81652770
HandleCount: 0 PointerCount: 3
Directory Object: e10078f8 Name: {6A665379-4AE7-45D1-9C36-B3B0471287F6}

哦,还真有这个东西。

kd> !devobj 81652788
Device object (81652788) is for:
{6A665379-4AE7-45D1-9C36-B3B0471287F6} \Driver\rtl8139 DriverObject 8165e510
Current Irp 00000000 RefCount 0 Type 00000017 Flags 00002050
Dacl e12b5494 DevExt 81652840 DevObjExt 81652d88
ExtensionFlags (0000000000)
AttachedTo (Lower) 8173f3e0 \Driver\PCI
Device queue is not busy.

kd> !drvobj 8165e510
Driver object (8165e510) is for:
\Driver\rtl8139
Driver Extension List: (id , addr)
(4e4d4944 8165e708)
Device Object list:
81652788

kd> dt _DRIVER_OBJECT 8165e510
+0x000 Type : 4
+0x002 Size : 168
+0x004 DeviceObject : 0x81652788 _DEVICE_OBJECT
+0x008 Flags : 0x12
+0x00c DriverStart : 0xf9cf1000
+0x010 DriverSize : 0x5200
+0x014 DriverSection : 0x8165baf8
+0x018 DriverExtension : 0x8165e5b8 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "\Driver\rtl8139"
+0x024 HardwareDatabase : 0x8068ee90 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch : (null)
+0x02c DriverInit : 0xf9cf5480 RTL8139!DriverEntry+0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : 0xf988389b NDIS!ndisMUnload+0
+0x038 MajorFunction : [28] 0xf9872e6b NDIS!ndisCreateIrpHandler+0

RTL8139这块网卡很多人使用。不过MajorFunction很有意思,居然设置在NDIS中。再看看别的,比如:
IRP_MJ_DEVICE_CONTROL。

kd> dd 8165e510 + 38
8165e548 f9872e6b f98791f4 f9872d9c f98791f4
8165e558 f98791f4 f98791f4 f98791f4 f98791f4
8165e568 f98791f4 f98791f4 f98791f4 f98791f4
8165e578 f98791f4 f98791f4 f9879010 f98791f4
8165e588 f98791f4 f98791f4 f98791f4 f98791f4
8165e598 f98791f4 f98791f4 f9886877 f9879415
8165e5a8 f98791f4 f98791f4 f98791f4 f987bab9
8165e5b8 8165e510 f987f5b4 00000000 0010000e

kd> u f98791f4
NDIS!ndisDummyIrpHandler:
f98791f4 8bff mov edi,edi
f98791f6 55 push ebp
f98791f7 8bec mov ebp,esp
f98791f9 8b4d0c mov ecx,dword ptr [ebp+0Ch]
f98791fc 8b5160 mov edx,dword ptr [ecx+60h]
f98791ff 56 push esi
f9879200 57 push edi
f9879201 8b7d08 mov edi,dword ptr [ebp+8]
f9879204 8b4728 mov eax,dword ptr [edi+28h]
f9879207 83c048 add eax,48h
f987920a 8b30 mov esi,dword ptr [eax]
f987920c 81fe4e444d50 cmp esi,504D444Eh
f9879212 0f858c020000 jne NDIS!ndisDummyIrpHandler+0x31 (f98794a4)

在网卡驱动初试化中会调用NdisIMInitializeDeviceInstance。怪不得,文档中肯定的说设备名字一定是
GUID的形式,原来设备的相关初试化都在NDIS中进行。这样一来,本文所描述的方法有普遍性,因为所有的
网卡的行为都是NDIS的,而常见的NDIS版本有两个:5、6。

下面我们来过滤改变网卡MAC地址的时候会经过哪些IOCTL。经过实验得到0x0017000e和0x0017003e

IOCTL_NDIS_QUERY_SELECTED_STATS 3
IOCTL_NDIS_RESERVED 7

这两个都不是我们想要的。顺便说一下,本来在改MAC地址的时候是不用重启机器的,而在用device filter
过滤的时候,改变MAC地址会提示下次开机生效,后用直接HooK的方法才正常。

无奈之下只好去翻NDIS的代码,还是去找NDIS4的老古董。

如下:

//
// Fill in the NDIS request.
//
GlobalRequest->Request.RequestType = NdisRequestQueryStatistics;
GlobalRequest->Request.DATA.QUERY_INFORMATION.Oid = *((PULONG)(Irp->AssociatedIrp.SystemBuffer));
GlobalRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = MDL_ADDRESS (Irp->MdlAddress);
GlobalRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = MDL_SIZE (Irp->MdlAddress);
GlobalRequest->Request.DATA.QUERY_INFORMATION.BytesWritten = 0;
GlobalRequest->Request.DATA.QUERY_INFORMATION.BytesNeeded = 0;
Status = (*Miniport->DriverHandle->MiniportCharacteristics.CoRequestHandler)(
Miniport->MiniportAdapterContext,
NULL,
&GlobalRequest->Request);

所以,用DeviceIoControl中设置Input为OID,并分配足够的内存就能成功。而最后一行的代码提醒了我们,
和网卡驱动通信不单是IOCTL还有它自己注册的HANDLE,比如这里就是用CoRequestHandler这个handler。
下面是所有的通过NdisMRegisterMiniport注册的handler:
CheckForHangHandler、DisableInterruptHandler、EnableInterruptHandler、HaltHandler、HandleInterruptHandler
InitializeHandler、ISRHandler、QueryInformationHandler、ReconfigureHandler、ResetHandler、SendHandler
SetInformationHandler、TransferDataHandler、ReturnPacketHandler、SendPacketsHandler、AllocateCompleteHandler
CoCreateVcHandler、CoDeleteVcHandler、CoActivateVcHandler、CoDeactivateVcHandler、CoSendPacketsHandler
CoRequestHandler、CancelSendPacketsHandler、PnPEventNotifyHandler、AdapterShutdownHandler

这里有ResetHandle和SetInformationHandler对我们来说很重要。当我们通过网卡的属性页设置MAC地址的时候
发现网卡状态变化是Reset过程。还好,ResetHandle和SetInformationHandler的区别就是Reset会去注册表
重新初试化而不是在内存中。当然如果有一天人家改成SetInformationHandler我们就要换方法了。


2 方法

下面的事情就比较清楚了,但还是有一个问题:我们如何及时修改注册表。如果我们用过滤设备或直接HOOK
原设备,就要先保存原来的设置,并在开机时设置回去。而更简单的方法是使用注册表回调机制。在MSND中
有一个函数可以实现:RegNotifyChangeKeyValue,但我们要在驱动里实现,所以这个方法的风险就在未公开
的内核API上,很显然就是ZwNotifyChangeKey。
ZwNotifyChangeKey(HANDLE KeyHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,CompletionFilter,WatchTree,PVOID Buffer,ULONG BufferSize,
BOOLEAN Asynchronous);在ifs DDK中有它的声明,看来微软并不反对我们使用它。
最后说一下思路,首先找到HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\NetworkCards\N
下的N值,然后打开HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\N
保存networkaddress的值,最后在每次得到通知的时候写回去。


3 结论

防止改MAC用了一些小技巧,成功也有偶然的成分。不过安全总是相对的,在大部分时候并没有问题。
市面上常见的修改MAC地址软件,比如smac、macshif、changemac等都是直接修改注册表后重启实现的,
也不能绕过我们的方法。

Forbid Setting Windows NT IP Address

文档名称:Forbid Setting Windows NT IP Address
文档维护:welfear
创建时间:2008年6月19日



目录

0 背景

1 分析

2 方法

3 结论


0 背景

Windows NT中的IP地址操作一直是个秘密。MSDN上的API只能操作动态IP,但是却不能操作主IP。
VCKbase上有文章论述如何调用未公开的API来实现操作主IP的功能。不过本文的目的并不在于此,
研究这方面的技术细节是为了在我们的产品中加入防止用户自己随意改变IP的功能。实现此功能
可以加强我们产品的运行基础,然而以前的实现并不是很好:-)。


1 分析

通过观察在改变改动系统IP的时候,tcpip.sys经过了哪些命令码可以找到些蛛丝马迹。无论
用户通过什么方式改动系统IP最后都要到tcpip.sys里设置。tcpip.sys创建的\device\tcp用来接收
这些命令。我们发现有如下命令码:

0x00120003
0x00128004
0x0012801c
0x00128020
0x00120028
0x00120040
0x0012006c
0x00120090

当然,上面的顺序是经过排列的。下面介绍为什么这么排列。这些命令码其实就是DeviceIoControl中的
第二个参数dwIoControlCode。它是通过下面的宏得到的:

#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

哦,好。它们的高16位都一样是0x0012,也就是DeviceType。0x0012是网络设备的意思。
它后面是Access,访问权限的意思,我们忽略它。最低两位是Method,关系也不大,也忽略。
现在我们要计算出关键的部分:Function的值。
经过16进制到2进制的转换,又去掉高14位和低2位后(恼火的计算过程:-(),得到了如下结果:

0、1、7、8、10、16、27、36。

翻翻泄露的源代码我们只能找到一些nt4时代的老古董:

IOCTL_ICMP_ECHO_REQUEST 0
IOCTL_IP_SET_ADDRESS 1
IOCTL_IP_ADD_NTE 7
IOCTL_IP_DELETE_NTE 8

而10、16、27、36我们不得而知:-(。


2 方法

下面一个一个来分析。

在功能码为10时的函数栈如下:

f59e8b8c 804e4d77 tcpip!Dispatch+0x5d
f59e8b9c f9efe754 nt!IopfCallDriver+0x31
f59e8c34 804e4d77 netflt!Dispatch+0x664
f59e8c44 8056b9ab nt!IopfCallDriver+0x31
f59e8c58 8057e9f7 nt!IopSynchronousServiceTail+0x60
f59e8d00 80580bfa nt!IopXxxControlFile+0x611
f59e8d34 804e006b nt!NtDeviceIoControlFile+0x2a
f59e8d34 7c92eb94 nt!KiFastCallEntry+0xf8
00bcfcfc 71a02092 ntdll!RtlpGetStackLimits+0x10
*** WARNING: symbols timestamp is wrong 0x41214604 0x3ef274f8 for mswsock.dll
00bcfd30 719c538f wshtcpip!WSHSetSocketInformation+0x6a7
00bcfd54 00000000 mswsock!InsertNameSpace+0x22

在功能码为16时的函数栈如下:

f5ea3c34 804e4d77 tcpip!Dispatch+0x5b
f5ea3c44 8056b9ab nt!IopfCallDriver+0x31
f5ea3c58 8057e9f7 nt!IopSynchronousServiceTail+0x60
f5ea3d00 80580bfa nt!IopXxxControlFile+0x611
f5ea3d34 804e006b nt!NtDeviceIoControlFile+0x2a
f5ea3d34 7c92eb94 nt!KiFastCallEntry+0xf8
014cf5b0 76d32d73 ntdll!RtlpGetStackLimits+0x10
014cf5d4 76d3315c iphlpapi!GetUniDirectionalAdapterInfo+0x30
014cf834 76d3366c iphlpapi!GetAdapterList+0x34b
014cf86c 76d361af iphlpapi!GetAdapterInfo+0x29
*** WARNING: symbols timestamp is wrong 0x41214568 0x3ef274df for NETSHELL.dll
014cf8c0 747b2c35 iphlpapi!GetAdapterInfoEx+0x1c
014cfb40 747cf6dc NETSHELL!___PchSym_ (NETSHELL+0x42c35)
014cfbc8 747d0d32 NETSHELL!___PchSym_ (NETSHELL+0x5f6dc)
014cfbec 747cd7a4 NETSHELL!___PchSym_ (NETSHELL+0x60d32)
014cfc10 747ce7eb NETSHELL!___PchSym_ (NETSHELL+0x5d7a4)
014cfc24 77d18709 NETSHELL!___PchSym_ (NETSHELL+0x5e7eb)
WARNING: Frame IP not in any known module. Following frames may be wrong.
014cfc50 77d19655 0x77d18709
014cfcb8 77d1958f 0x77d19655
014cfd10 77d189e8 0x77d1958f
014cfd20 74a6155a 0x77d189e8

在功能码为36时的函数栈如下:

f5ea3c34 804e4d77 tcpip!Dispatch+0x5b
f5ea3c44 8056b9ab nt!IopfCallDriver+0x31
f5ea3c58 8057e9f7 nt!IopSynchronousServiceTail+0x60
f5ea3d00 80580bfa nt!IopXxxControlFile+0x611
f5ea3d34 804e006b nt!NtDeviceIoControlFile+0x2a
f5ea3d34 7c92eb94 nt!KiFastCallEntry+0xf8
014cf520 76d328b4 ntdll!RtlpGetStackLimits+0x10
014cf5a8 76d32983 iphlpapi!GetInterfaceInfo+0x86
014cf5e0 76d330d1 iphlpapi!GetAdapterOrderMap+0xb5
014cf834 76d3366c iphlpapi!GetAdapterList+0x46
014cf86c 76d361af iphlpapi!GetAdapterInfo+0x29
014cf8c0 747b2c6b iphlpapi!GetAdapterInfoEx+0x1c
014cfb40 747cf6dc NETSHELL!___PchSym_ (NETSHELL+0x42c6b)
014cfbc8 747d0d32 NETSHELL!___PchSym_ (NETSHELL+0x5f6dc)
014cfbec 747cd7a4 NETSHELL!___PchSym_ (NETSHELL+0x60d32)
014cfc10 747ce7eb NETSHELL!___PchSym_ (NETSHELL+0x5d7a4)
014cfc24 77d18709 NETSHELL!___PchSym_ (NETSHELL+0x5e7eb)
WARNING: Frame IP not in any known module. Following frames may be wrong.
014cfc50 77d19655 0x77d18709
014cfcb8 77d1958f 0x77d19655
014cfd10 77d189e8 0x77d1958f

在功能码为27时的函数栈如下:

f5ea3c34 804e4d77 tcpip!Dispatch+0x5d
f5ea3c44 8056b9ab nt!IopfCallDriver+0x31
f5ea3c58 8057e9f7 nt!IopSynchronousServiceTail+0x60
f5ea3d00 80580bfa nt!IopXxxControlFile+0x611
f5ea3d34 804e006b nt!NtDeviceIoControlFile+0x2a
f5ea3d34 7c92eb94 nt!KiFastCallEntry+0xf8
00edcfec 76d36c47 ntdll!RtlpGetStackLimits+0x10
00edd07c 76d36b7e iphlpapi!NhpAllocateAndGetInterfaceInfoFromStack+0x78
00edd0a4 76d36b19 iphlpapi!NhGetInterfaceNameFromDeviceGuid+0x20
00edd0c4 76d36acd iphlpapi!MapAdapterNameToFriendlyName+0x3a
00edd7b8 76d33d43 iphlpapi!AddIPv4InterfaceInfo+0xe2
00edd7dc 76d34009 iphlpapi!ForEachIPv4Interface+0x45
00edd858 76d33ddc iphlpapi!GetAdapterAddresses+0xcb
00edd8c8 76d33da7 iphlpapi!GetAdapterAddressesEx+0x26
00edd8e4 747ba376 iphlpapi!GetAdaptersAddresses+0x60
WARNING: Frame IP not in any known module. Following frames may be wrong.
00eddc7c 7c92fb71 0x747ba376
00eddd34 7c930732 ntdll!RtlpInheritAcl2+0xd0
00edde44 7c9306ab ntdll!RtlCompactHeap+0x31
00edde60 7c935d7d ntdll!RtlIsValidHandle+0x17
7c930732 ffff9090 ntdll!RtlIsDosDeviceName_Ustr+0x9b
7c93073a e0667c96 0xffff9090
7c93073e c0337c96 0xe0667c96
7c930742 d18bfe8b 0xc0337c96
7c930746 f302e9c1 0xd18bfe8b
7c93074a 83ca8bab 0xf302e9c1
7c93074e aaf303e1 0x83ca8bab
7c930752 ffff7ce9 0xaaf303e1
7c930756 909090ff 0xffff7ce9
7c93075a ff8b9090 0x909090ff
7c93075e 83ec8b55 0xff8b9090
7c930762 56531cec 0x83ec8b55
7c930766 bfdb3357 0x56531cec
7c93076a 7c99c3a0 0xbfdb3357
7c93076e 99c380be ntdll!RtlpDosLPTDevice (ntdll+0x7c3a0)
7c99c3a0 00000000 0x99c380be


功能码16和Adapter有关,功能码36和Interface有关。
Adapter和Interface分别对应数据链路层信息和网络层信息。

功能码27和地址信息有关。

下面是改变主IP时各模块间的关系:

f9e7490c 8056b9ab nt!IopfCallDriver+0x31
f9e74920 8057e9f7 nt!IopSynchronousServiceTail+0x60
f9e749c8 80580bfa nt!IopXxxControlFile+0x611
f9e749fc 804e006b nt!NtDeviceIoControlFile+0x2a
f9e749fc 804de243 nt!KiFastCallEntry+0xf8
f9e74a9c f8267600 nt!ZwDeviceIoControlFile+0x11
f9e74ae4 f826758d netbt!SetTcpInfo+0x64
f9e74b00 f82674c5 netbt!NbtSetTcpInfo+0x5d
f9e74b28 f8270386 netbt!NbtOpenAndAssocConnection+0x12e
f9e74b54 f8284049 netbt!NbtNewDhcpAddress+0x146
f9e74bf8 f8281eeb netbt!NbtAddressAdd+0x176
f9e74c14 f9d2abd7 netbt!TdiAddressArrival+0x4b
f9e74c38 f9d2b2e8 TDI!TdiNotifyPnpClientList+0xd9
f9e74c5c f9d2b51a TDI!TdiExecuteRequest+0x382
f9e74c98 f9d2b745 TDI!TdiHandleSerializedRequest+0x1c4
f9e74cb4 f829d212 TDI!TdiRegisterNetAddress+0x14b
f9e74d00 f829d40d tcpip!NotifyAddrChange+0xef
f9e74d38 f829d343 tcpip!IPAddAddrComplete+0xdf
f9e74d58 f9d293e4 tcpip!CompleteIPSetNTEAddrRequestDelayed+0x25
f9e74d74 804e57fe TDI!CTEpEventHandler+0x32
f9e74dac 8057efed nt!ExpWorkerThread+0x100
f9e74ddc 804fb477 nt!PspSystemThreadStartup+0x34
00000000 00000000 nt!KiThreadStartup+0x16

f61c6c34 804e4d77 tcpip!Dispatch+0x2e
f61c6c44 8056b9ab nt!IopfCallDriver+0x31
f61c6c58 8057e9f7 nt!IopSynchronousServiceTail+0x60
f61c6d00 80580bfa nt!IopXxxControlFile+0x611
f61c6d34 804e006b nt!NtDeviceIoControlFile+0x2a
f61c6d34 7c92eb94 nt!KiFastCallEntry+0xf8
0274f204 76d61b7e ntdll!RtlpGetStackLimits+0x10
WARNING: Frame IP not in any known module. Following frames may be wrong.
0274f2dc 7c931e75 0x76d61b7e
0274f380 7c92e57c ntdll!RtlAppendUnicodeToString+0x4c
0274f38c 7c930570 ntdll!ZwConnectPort+0x2
0274f3bc 00000000 ntdll!RtlUpcaseUnicodeToOemN+0x4b8

TDI.sys通过tcpip.sys注册的接口直接访问tcpip.sys。
DDK中有关于TdiRegisterPnPHandlers的介绍,这里不多说。

3 结论

我们直接把2号功能码和27号功能码返回失败。系统提示要重新启动后才能生效。到此,我们的目的基本
达到了。如果不想让系统提示重新后生效,就要欺骗一下,这次我们返回成功。系统没有提示,到在
使用ipconfig时,ipconfig崩溃。最后我们去掉27号功能码,只拦截2号功能码,ipconfig也没有问题
了:-)。

2008年的其他牢骚

偶然间看了看MFC2005的代码,感觉它的风格和Vista DDK里东西很象,看过之后都有想吐的
感觉。还是看看微软在做什么吧,这个东西下载了,可惜没装上,没代码也不想装了。http://blogs.msdn.com/vcblog/archive/2007/11/09/
quick-tour-of-new-mfc-functionality.aspx
不过更邪恶的是Vista 64,连驱动都不让搞了。不过总是有人要起来反抗的。
http://www.linchpinlabs.com/resources/atsiv/usage-design.htm
Subverting Vista kernel 是很酷的。

ZwXxxFile会把调用模式设置为KernelMode,这样便可以绕过用户态内存检查代码。尽管这种检查没有Linux做的完备。在Linux中直接调用file->f_op->read或file->f_op->aio_read就可
以了。
最近想看点新书了,就找了找,找了一本《windows via c/c++》。比较前四版来看,第五版
变化不大。
《Windows® Internals: Including Windows Server 2008 and Windows Vista》要明年才能看到,等吧。
天天蓝的同学应该看看这个:
http://www.dumpanalysis.org/

"Many kernel developers have long demanded an in-kernel debugger. Unfortunately, Linus does not want a debugger in his tree. He believes that debuggers lead to bad fixes by misinformed developers. No one can argue with his logica fix derived from real understanding of the code is certainly more likely to be correct. Nonetheless, plenty of kernel developers want an official in-kernel debugger. Because it is unlikely to happen anytime soon, a number of patches have arisen that add kernel-debugging support to the standard Linux kernel. Despite being external unofficial patches, these tools are quite well featured and powerful. Before you delve into these solutions, however, it's a good idea to look at how much help the standard Linux debugger, gdb, will give you." --Robert Love

Linux kernel 2.6.26出来了,带着kdb一起出来的。
http://oslab.info/index.php/Misc/KGDB
公司老大一声令下给我又弄一台机器,瞬间结束了我调虚拟机的生涯。
http://www.wd-3.com/archive/RemoteDbg.htm

不过,Linux还是要扔进虚拟机里的,嘿嘿。。。。。。。。。


IoRegisterDriverReinitialization很恶心,尤其是在DDK里的对它介绍,看了半天还是不大
确定它到底是做什么用的。但事后一想,还是很佩服它的设计者。WDM有AddDevice,那非WDM
总也得有个对应的东西吧?没错,它就是做这个的。在调用DriverEntry的时候,也就是在
IopLoadUnloadDriver里,调用DriverEntry之后,就是调用在全局列队里的重新初始化函数。
但这里有个细节,它是边移除边调用。这样一来,在DriverEntry里使用
IoRegisterDriverReinitialization并在注册的重新初始化里再次无条件的调用IoRegisterDriverReinitialization,那么死循环就是一定的了。因此,是在一定条件下再次
调用。不过,再DriverEntry之外调用就没那么麻烦了,这样做可以得到其它驱动的初始化结果。
现在流行复古,所以PsGetVersion和IoReadPartitionTable之流就是不可避免的了,还好
MmGetSystemRoutineAddress一直不错,它不仅仅可以搞定ntos就连hall它也不放过。

google是用GET方法处理URL的,可能是CGI吧,提高效率。ACPI是一个后门,虚拟光驱类软件
经常利用它。
老婆的同学出嫁了。婚礼很浪漫。
回到家乡,家乡人还是那么淳朴。
容易得到的术,难得的道。


http://blogs.msdn.com/winfs/default.aspx
http://www.openrce.org/articles/
http://www.microsoft.com/presspass/exec/de/default.mspx
http://www.microsoft.com/presspass/exec/techfellow/default.mspx
http://blogs.msdn.com/peterwie/
http://blogs.msdn.com/greg_schechter/archive/2006/03/25/561167.aspx
http://blogs.msdn.com/spatdsg/
http://www.alex-ionescu.com/


CString s;
printf("%s", s);
看看CString,也不用看太多,
#define MAX_LINE_LEN 2048
#define MAX_TAGS 63
#define MAX_SUBTOKENS 8
class CString
{
char szString [ MAX_LINE_LEN+1 ];
public:
CString() { szString [ 0 ] = '\0'; }
.....................
AllocSysString和SysAllocString得到的是BSTR,它前四个字节是长度。
所以长度为*((long *)x-1)。
_bstr_t居然是class,在comdef.h里。
很邪恶吧?
更邪恶的是有符号和无符号数比较,
UINT u;
INT i;
if (u > i)
.......................
有符号数会被当做很大的无符号数,前提是它真是的负数。
至于64位windows编程倒不用担心,就是指针位数变了。
微软的编译器使用了LLP64的方式,可能它是觉得32位为计算之用已经足够。
另外一个比较诡异的事是2K和它之后的操作系统对Boot Start Driver的处理
并不一致。
说点细节吧,netflt start 1 no group tcpip start 1 group pnp_tdi。
我原来的理解是无论tcpip start是0还是1,只要我的netflt为1,无组,那么就
应该可以挂在tcpip上。
可事实是2K上它们的顺序是反的。我看了IoInitSystem的代码,认为只有
一种可能会发生这种情况,就是它们Root树的位置不同。当然修改start为2,
也可以解决问题。
Linux里的KVM值得关注
学习完全虚拟化技术的好资料,vmware我就不用了。
而文件系统方面的好书是《File System Forensic Analysis》。
对于高级文件系统XFS、reiserfs就只好去看代码了。

TDI过滤驱动分析

文档名称:TDI过滤驱动分析
文档维护:welfear
创建时间:2008年3月6日
更新时间:2008年3月7日
更新内容:Vista中TDI驱动的变化
更新时间:2008年5月8日
更新内容:过滤GET/POST请求方法



目录

0 介绍
0.1 TDI驱动作用
0.2 Windows NT网络总体结构

1. 过滤设备
1.1 绑定目标
1.2 分发函数
1.3 过滤地址
1.4 过滤内容
1.4.1 过滤HTTP
1.4.2 过滤DNS

2. VISTA网络结构

3. 驱动代码分析
3.1 主要数据结构分析
3.2 主要算法分析

4. 附属内容
4.1 HTTP协议GET请求数据
4.2 HTTP协议POST请求数据



0. 介绍


0.1 TDI驱动作用

TDI协议驱动主要应用于版本号在nt4至nt5之间的操作系统,本文档对TDI驱动的分析主要参考nt4所提供
的TDI驱动。TDI是Transport Driver Interface首字母缩写,主要提供网络层协议和传输层协议的实现。

0.2 Windows NT网络总体结构

网络应用程序一般通过MSDN提供的ws2_32.dll的文档使用winsock网络接口。如果在注册表里设置了其它
的SPI服务,Windows NT会加载相映的动态连接库实现应用层的winsock API过滤。ws2_32.dll通过查找
注册表里的服务提供者信息,调用不同服务提供者的实现接口。相对于TCP/IP,程序会进入msafd.dll和
wshtcpip.dll中。在wshtcpip.dll中,通过调用ntdll.dll中的Native API把请求发送到afd.sys中。AFD
是一个文件系统驱动,所以Windows NT的网络驱动和文件密切相关。然后请求到达TDI驱动,对于TCP/IP
对应的驱动是tcpip.sys。最后请求会传递到NDIS中通过miniport驱动发送或接收网卡数据。以上是网络
数据包的大致流程。值得说明的是AFD(Ancillary Function Driver)的设计,通过设计统一的接口和注册
表中的信息达到实现不同协议栈的目的。不过这部分设计也有intel公司功劳,因为代码中有很多intel
公司工程师的署名:-)。


1. 过滤设备


1.1 绑定目标

TDI会创建四个网络设备而不是三个。它们是\Device\Tcp、\Device\Udp、\Device\RawIp、\Device\Ip,
其中的\Device\Ip我们不必关心。真正的传送IP数据的是\Device\RawIp。就我们的过滤目的而言,IP设
备都不用关心。这样,我们使用IoCreateDevice创建两个我们自己的设备,并通过IoAttachDevice放到
\Device\Tcp和\Device\Udp之上。对IoAttachDevice的使用要小心,IoAttachDevice会用IoCreateFile
打开目的设备,绑定设备之后在关闭,但那时我们的设备已经在设备栈之上,所以也会收到close IRP。
同时为了以后使用方便我们保存了TDI设备的地址。创建的设备要设置Flags为DO_DIRECT_IO,因为TDI设
备都使用这个方式。

1.2 分发函数

除了IRP_MJ_INTERNAL_DEVICE_CONTROL之外,其它的IRP都被发送到TCPDispatch之中。在TCPDispatch里
有如下几种情况:

1. \Device\Ip的IRP被送到IPDispatch之中。这些IRP可能是从ipconfig、ping、route中发出的。

1.1 IPCleanup负责清理未处理IRP。

1.2 IPDispatchDeviceControl中先处理IOCTL_ICMP_ECHO_REQUEST调用关系如下:
DispatchEchoRequest->ICMPEchoRequest->ICMPEcho->SendEcho->IPTransmit->SendIPPacket。
IOCTL_ICMP_ECHO_REQUEST支持了SDK中提供的icmp.dll的接口实现。ICMPEchoRequest可以被
内核协议栈直接使用也可以接受用户请求。IOCTL_IP_GET_NTE_INFO、IOCTL_IP_ADD_NTE、
IOCTL_IP_DELETE_NTE提供路由表设置功能。IOCTL_IP_SET_DHCP_INTERFACE提供DHCP设置功能。
IOCTL_IP_SET_ADDRESS提供地址设置功能。用户可以通过interface系列API使用以上功能。
IOCTL_IP_SET_FILTER_POINTER提供对IP过滤驱动的支持。

2. 其它三个设备统一在TCPDispatch中得到分配。

2.1 处理IRP_MJ_DEVICE_CONTROL时先使用TdiMapUserRequest把用户I/O Control code 转化成内部
成MinorFunction。比如IOCTL_TDI_CONNECT变成TDI_CONNECT。调用TCPDispatchDeviceControl
和TCPDispatchInternalDeviceControl。前者是用来实现IOCTL_TCP_QUERY_INFORMATION_EX和
IOCTL_TCP_SET_INFORMATION_EX的。不过在windows 2000之后IRP_MJ_DEVICE_CONTROL并不再需
要转换了。

2.2 为IRP_MJ_QUERY_SECURITY保留接口。看来微软早意识到RawIP的安全问题,不过这个接口在XP的
SP2补丁之后才起作用。

2.3 TCPCreate、TCPClose、TCPCleanup几个分派函数处理TDI_CONTROL_CHANNEL_FILE、
TDI_CONNECTION_FILE和TDI_TRANSPORT_ADDRESS_FILE。TDI_CONTROL_CHANNEL_FILE对应EA为空
的情况。TCPCreate实现如下:得到从NtCreateFile中的Ea(extra缩写)参数,如果为空,则要
创建的是TDI_CONTROL_CHANNEL_FILE。如果不为空,用FindEA查找TdiTransportAddress,如果
找到用TdiOpenAddress建立地址对象。传输地址对象是三个设备都可以有的。再用FindEA查找
TdiConnectionContext,如果找到则用TdiOpenConnection建立连接对象,并且只有Tcp设备可以
建立。

2.4 TCPDispatchInternalDeviceControl实现了TDI的大多数功能。和常见的文件系统驱动类似,TDI
驱动使用由AFD文件系统驱动建立的FsContext文件控制块,而FsContext2保存了地址对象类型。
如果FsContext2为TDI_CONNECTION_FILE,也就是连接对象,有这几种IRP处理TDI_RECEIVE、
TDI_DISASSOCIATE_ADDRESS、TDI_CONNECTTDI_DISCONNECT、TDI_LISTENTDI_ACCEPT、TDI_SEND、
TDI_ASSOCIATE_ADDRESS。
如果FsContext2为TDI_TRANSPORT_ADDRESS_FILE,要处理TDI_SET_EVENT_HANDLER、
TDI_SEND_DATAGRAM、TDI_RECEIVE_DATAGRAM。
最后两种TDI_QUERY_INFORMATION和TDI_SET_INFORMATION三个设备都可以处理。

TdiMapUserRequest用于把IRP_MJ_DEVICE_CONTROL映射为IRP_MJ_INTERNAL_DEVICE_CONTROL。
通过AFD.sys发送的网络请求被转化成IRP_MJ_INTERNAL_DEVICE_CONTROL,所以可以先不考虑
IRP_MJ_DEVICE_CONTROL。另外,WinNT组件内部使用IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER
和IOCTL_TDI_QUERY_DIRECT_SENDDG_HANDLER来直接发送数据包,这个未公开的机制可以绕过
我们的过滤。在必要时也要考虑在内。

1.3 过滤地址

1.3.1 本地地址

本地地址放在EAName之后,TRANSPORT_ADDRESS结构里的TDI_ADDRESS_IP中的sin_port和in_addr。

1.3.2 远程地址

TCP协议的远程地址在(PTDI_REQUEST_KERNEL_CONNECT)&(IrpSp->Parameters)之中。
而RawIp和UDP协议的远程地址在(PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters)之中。

1.4 过滤内容

过滤TDI_SEND、TDI_RECEIVE、TDI_SEND_DATAGRAM、TDI_RECEIVE_DATAGRAM时查看irp->MdlAddress。

1.4.1 过滤HTTP

本节参考RFC1945、2068、2616关于HTTP 1.0/1.1版本的协议标准和RFC2518、3253关于WebDav的描述。

1. 过滤请求。需要过滤的请求报文有GET和POST两种。请求行格式为:请求 URI HTTP版本。
实例中的GET请求为: GET /cgi-bin/cvstrac/NetWorkAudit/wiki HTTP/1.1\r\n
实例中的POST请求为:POST /cgi-bin/cvstrac/NetWorkAudit/login HTTP/1.1\r\n
报文头部主要有:
Accept: image/gif, image/x-xbitmap, image/jpeg, ......application/msword, */*\r\n
Referer: http://192.168.0.8/cgi-bin/cvstrac/NetWor......NetWorkAudit/wiki\r\n
Accept-Language: zh-cn\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Accept-Encoding: gzip, deflate\r\n
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NE......7)\r\n
Host: 192.168.0.8\r\n
Content-Length: 80\r\n
Connection: Keep-Alive\r\n
Cache-Control: no-cache\r\n
比较重要的是Content-Length,冒号后面是body部分的长度。
身体部分。只有POST请求有body部分。body跟在头部之后并多空一行。比如POST表单参数:
nxp=%2Fcgi-bin%2Fcvstrac%2FNetWorkAudit%2Fwiki&u=welear&p=welfar&in=%B5%C7%C2%BC

2. 过滤响应。响应行格式为HTTP版本号 状态码 状态码解释。头部与身体和请求一样。例如:
HTTP/1.1 302 Moved Temporarily\r\n
Date: Tue, 11 Mar 2008 09:32:00 GM\r\n
Server: Apache/1.3.19 (Unix) (Red-Hat/Linux)\r\n
Location: /cgi......\r\n
Content-Length: 106\r\n
Keep-Alive: timeout=15, max=100\r\n
Connection: Keep-Alive\r\n
Content-Type: text/html; charset=GB2312\r\n
其中比较重要的是Content-Type和Content-Length。过滤时判断状态码为200即可。
不过过滤断点续传还需要进一步研究。

过滤需要根据需求判断头部信息,保存身体部分内容。用可选字段Host可以得到用户键入浏览器URI地址。
判断用户意图还需要过滤GET请求的文件的后缀名。一般用html和htm作为网页的默认后缀名,用
asp、aspx、php、jsp作为动态网页的默认后缀名。POST请求并不过滤后缀和post参数。如果Host字段不可
用,那么就必须使用下面的《过滤DNS》一节的方法。

1.4.2 过滤DNS

过滤DNS数据包是为还原域名功能所做的必要准备。DNS查询和响应有可能使用UDP协议也有可能使用
TCP协议,在实际测试中发现发送DNS数据包时并不使用Connect。DNS的查询和响应使用统一的包格式,
各字段含义如下:

1. 标识。2字节,用来确定查询和响应的对应关系。

2. 标志。2字节,表示协议包含义细节。
OR(1bit):0代表查询,1代表响应。
opcode(4bit):0代表标准查询,1代表反向查询,2代表服务器状态请求。
AA(1bit):名字服务器授权该域。
TC(1bit):代表超过512字节可以被截断。
RD(1bit):代表期望查询。
RA(1bit):代表递归查询。
zero(3bit):0。
rcode(4bit):0代表没有差错,3代表名字差错。

3. 问题数、资源记录数、授权资源记录数、额外资源记录数。它们每个字段占2字节,代表各种
记录数。一般问题数或资源数为1,其它都是0。


2. VISTA网络结构


Vista在网络部分做了比较大的改动。用WSK(Winsock Kernel)和WFP(Windows Filtering Platform)代替
TDI驱动。

2.1 Winsock Kernel

由ISO的7个分层协议到绝大多数现实使用的4层简化网络协议为操作系统的网络实现奠定了设计基础。
在WinNT的网络中,设计者又把问题分为两个方面来看,也就是TDI和NDIS。NDIS实现了标准网络协议
和网卡的结合问题,也就是网络层和传输层与数据链路层和物理层的衔接问题。以前的TDI主要包括
Socket Emulator、NetBios Emulator、Redirector等。这样一来,Socket接口只是在应用层起作用。
这些TDI最后依然要使用以socket为接口的网络协议,而且TDI中有一些接口完全可以放在一起,减少
代码量。在Vista的设计中,socket被放在内核中用作TDI和NDIS的接口,而原来的TDI有了新的位置,
就是WSK Application,实现WSK Client NPI。下面是Vista DDK原文:
"WSK applications discover and attach to the WSK subsystem by using a set of WSK
registration functions. Applications can use these functions to dynamically detect
when the WSK subsystem is available and to exchange dispatch tables that constitute
the provider and client side implementations of the WSK NPI."
这里的WSK subsystem就是socket在内核部分的实现者。
WSK Client使用Network Module Registrar(NMR)提供的接口向Provider Module注册自己。最重要的是
WSK Client必须使用address family、socket type、protocol参数转换为TDI Transports的设备名字,
调用WSK Subsystem提供的WskControlClient,并设置好WSK_TDI_DEVICENAME_MAPPING参数。
最后,微软这么设计可能还有一个原因:Unix系列操作系统都是在内核实现socket网络接口,这样做也算
和别人一样了,还有大量的开源操作系统可以参考。以socket为接口的网络设计已经被实现的很好了。

2.2 Windows Filtering Platform

WFP是TDI Filter Driver的替代者。vista提供了统一接口实现过滤引擎,而我们又变成了它的客户。:-(


4. 附属内容


4.1 HTTP协议GET请求数据

0000 00 11 09 8d ec 80 00 0a eb 86 d9 d4 08 00 45 00 ........ ......E.
0010 02 0a 11 38 40 00 40 06 a6 2a c0 a8 00 33 c0 a8 ...8@.@. .*...3..
0020 00 08 05 8e 00 50 3b 50 27 49 10 ed e2 31 50 18 .....P;P 'I...1P.
0030 fa 84 d6 0d 00 00 47 45 54 20 2f 63 67 69 2d 62 ......GE T /cgi-b
0040 69 6e 2f 63 76 73 74 72 61 63 2f 4e 65 74 57 6f in/cvstr ac/NetWo
0050 72 6b 41 75 64 69 74 2f 6c 6f 67 69 6e 3f 6e 78 rkAudit/ login?nx
0060 70 3d 2f 63 67 69 2d 62 69 6e 2f 63 76 73 74 72 p=/cgi-b in/cvstr
0070 61 63 2f 4e 65 74 57 6f 72 6b 41 75 64 69 74 2f ac/NetWo rkAudit/
0080 77 69 6b 69 20 48 54 54 50 2f 31 2e 31 0d 0a 41 wiki HTT P/1.1..A
0090 63 63 65 70 74 3a 20 69 6d 61 67 65 2f 67 69 66 ccept: i mage/gif
00a0 2c 20 69 6d 61 67 65 2f 78 2d 78 62 69 74 6d 61 , image/ x-xbitma
00b0 70 2c 20 69 6d 61 67 65 2f 6a 70 65 67 2c 20 69 p, image /jpeg, i
00c0 6d 61 67 65 2f 70 6a 70 65 67 2c 20 61 70 70 6c mage/pjp eg, appl
00d0 69 63 61 74 69 6f 6e 2f 78 2d 73 68 6f 63 6b 77 ication/ x-shockw
00e0 61 76 65 2d 66 6c 61 73 68 2c 20 61 70 70 6c 69 ave-flas h, appli
00f0 63 61 74 69 6f 6e 2f 76 6e 64 2e 6d 73 2d 65 78 cation/v nd.ms-ex
0100 63 65 6c 2c 20 61 70 70 6c 69 63 61 74 69 6f 6e cel, app lication
0110 2f 76 6e 64 2e 6d 73 2d 70 6f 77 65 72 70 6f 69 /vnd.ms- powerpoi
0120 6e 74 2c 20 61 70 70 6c 69 63 61 74 69 6f 6e 2f nt, appl ication/
0130 6d 73 77 6f 72 64 2c 20 2a 2f 2a 0d 0a 52 65 66 msword, */*..Ref
0140 65 72 65 72 3a 20 68 74 74 70 3a 2f 2f 31 39 32 erer: ht tp://192
0150 2e 31 36 38 2e 30 2e 38 0d 0a 41 63 63 65 70 74 .168.0.8 ..Accept
0160 2d 4c 61 6e 67 75 61 67 65 3a 20 7a 68 2d 63 6e -Languag e: zh-cn
0170 0d 0a 41 63 63 65 70 74 2d 45 6e 63 6f 64 69 6e ..Accept -Encodin
0180 67 3a 20 67 7a 69 70 2c 20 64 65 66 6c 61 74 65 g: gzip, deflate
0190 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 4d 6f ..User-A gent: Mo
01a0 7a 69 6c 6c 61 2f 34 2e 30 20 28 63 6f 6d 70 61 zilla/4. 0 (compa
01b0 74 69 62 6c 65 3b 20 4d 53 49 45 20 36 2e 30 3b tible; M SIE 6.0;
01c0 20 57 69 6e 64 6f 77 73 20 4e 54 20 35 2e 31 3b Windows NT 5.1;
01d0 20 53 56 31 3b 20 2e 4e 45 54 20 43 4c 52 20 32 SV1; .N ET CLR 2
01e0 2e 30 2e 35 30 37 32 37 29 0d 0a 48 6f 73 74 3a .0.50727 )..Host:
01f0 20 31 39 32 2e 31 36 38 2e 30 2e 38 0d 0a 43 6f 192.168 .0.8..Co
0200 6e 6e 65 63 74 69 6f 6e 3a 20 4b 65 65 70 2d 41 nnection : Keep-A
0210 6c 69 76 65 0d 0a 0d 0a live....

4.2 HTTP协议POST请求数据

0000 00 11 09 8d ec 80 00 0a eb 86 d9 d4 08 00 45 00 ........ ......E.
0010 02 dc 19 b7 40 00 40 06 9c d9 c0 a8 00 33 c0 a8 ....@.@. .....3..
0020 00 08 05 94 00 50 35 a6 5d ad 4c c0 7c 0c 50 18 .....P5. ].L.|.P.
0030 fa f0 81 bb 00 00 50 4f 53 54 20 2f 63 67 69 2d ......PO ST /cgi-
0040 62 69 6e 2f 63 76 73 74 72 61 63 2f 4e 65 74 57 bin/cvst rac/NetW
0050 6f 72 6b 41 75 64 69 74 2f 6c 6f 67 69 6e 20 48 orkAudit /login H
0060 54 54 50 2f 31 2e 31 0d 0a 41 63 63 65 70 74 3a TTP/1.1. .Accept:
0070 20 69 6d 61 67 65 2f 67 69 66 2c 20 69 6d 61 67 image/g if, imag
0080 65 2f 78 2d 78 62 69 74 6d 61 70 2c 20 69 6d 61 e/x-xbit map, ima
0090 67 65 2f 6a 70 65 67 2c 20 69 6d 61 67 65 2f 70 ge/jpeg, image/p
00a0 6a 70 65 67 2c 20 61 70 70 6c 69 63 61 74 69 6f jpeg, ap plicatio
00b0 6e 2f 78 2d 73 68 6f 63 6b 77 61 76 65 2d 66 6c n/x-shoc kwave-fl
00c0 61 73 68 2c 20 61 70 70 6c 69 63 61 74 69 6f 6e ash, app lication
00d0 2f 76 6e 64 2e 6d 73 2d 65 78 63 65 6c 2c 20 61 /vnd.ms- excel, a
00e0 70 70 6c 69 63 61 74 69 6f 6e 2f 76 6e 64 2e 6d pplicati on/vnd.m
00f0 73 2d 70 6f 77 65 72 70 6f 69 6e 74 2c 20 61 70 s-powerp oint, ap
0100 70 6c 69 63 61 74 69 6f 6e 2f 6d 73 77 6f 72 64 plicatio n/msword
0110 2c 20 2a 2f 2a 0d 0a 52 65 66 65 72 65 72 3a 20 , */*..R eferer:
0120 68 74 74 70 3a 2f 2f 31 39 32 2e 31 36 38 2e 30 http://1 92.168.0
0130 2e 38 2f 63 67 69 2d 62 69 6e 2f 63 76 73 74 72 .8/cgi-b in/cvstr
0140 61 63 2f 4e 65 74 57 6f 72 6b 41 75 64 69 74 2f ac/NetWo rkAudit/
0150 6c 6f 67 69 6e 3f 6e 78 70 3d 2f 63 67 69 2d 62 login?nx p=/cgi-b
0160 69 6e 2f 63 76 73 74 72 61 63 2f 4e 65 74 57 6f in/cvstr ac/NetWo
0170 72 6b 41 75 64 69 74 2f 77 69 6b 69 0d 0a 41 63 rkAudit/ wiki..Ac
0180 63 65 70 74 2d 4c 61 6e 67 75 61 67 65 3a 20 7a cept-Lan guage: z
0190 68 2d 63 6e 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 h-cn..Co ntent-Ty
01a0 70 65 3a 20 61 70 70 6c 69 63 61 74 69 6f 6e 2f pe: appl ication/
01b0 78 2d 77 77 77 2d 66 6f 72 6d 2d 75 72 6c 65 6e x-www-fo rm-urlen
01c0 63 6f 64 65 64 0d 0a 41 63 63 65 70 74 2d 45 6e coded..A ccept-En
01d0 63 6f 64 69 6e 67 3a 20 67 7a 69 70 2c 20 64 65 coding: gzip, de
01e0 66 6c 61 74 65 0d 0a 55 73 65 72 2d 41 67 65 6e flate..U ser-Agen
01f0 74 3a 20 4d 6f 7a 69 6c 6c 61 2f 34 2e 30 20 28 t: Mozil la/4.0 (
0200 63 6f 6d 70 61 74 69 62 6c 65 3b 20 4d 53 49 45 compatib le; MSIE
0210 20 36 2e 30 3b 20 57 69 6e 64 6f 77 73 20 4e 54 6.0; Wi ndows NT
0220 20 35 2e 31 3b 20 53 56 31 3b 20 2e 4e 45 54 20 5.1; SV 1; .NET
0230 43 4c 52 20 32 2e 30 2e 35 30 37 32 37 29 0d 0a CLR 2.0. 50727)..
0240 48 6f 73 74 3a 20 31 39 32 2e 31 36 38 2e 30 2e Host: 19 2.168.0.
0250 38 0d 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 8..Conte nt-Lengt
0260 68 3a 20 38 30 0d 0a 43 6f 6e 6e 65 63 74 69 6f h: 80..C onnectio
0270 6e 3a 20 4b 65 65 70 2d 41 6c 69 76 65 0d 0a 43 n: Keep- Alive..C
0280 61 63 68 65 2d 43 6f 6e 74 72 6f 6c 3a 20 6e 6f ache-Con trol: no
0290 2d 63 61 63 68 65 0d 0a 0d 0a 6e 78 70 3d 25 32 -cache.. ..nxp=%2
02a0 46 63 67 69 2d 62 69 6e 25 32 46 63 76 73 74 72 Fcgi-bin %2Fcvstr
02b0 61 63 25 32 46 4e 65 74 57 6f 72 6b 41 75 64 69 ac%2FNet WorkAudi
02c0 74 25 32 46 77 69 6b 69 26 75 3d 77 65 6c 65 61 t%2Fwiki &u=welea
02d0 72 26 70 3d 77 65 6c 66 61 72 26 69 6e 3d 25 42 r&p=welf ar&in=%B
02e0 35 25 43 37 25 43 32 25 42 43 5%C7%C2% BC

第一次离职总结

今天开始和neusoft彻底没了关系。
昨天喝了很多,也说了很多。
无论是以前朋友或是敌人,都很感谢。这些人让我不断进步。
blackhat、whitehat都曾经给过我力量。
以前前辈说的话,现在慢慢理解了。
我们都生活在轮回之中......(本来想写多点,可是网吧的机器太破了一一!)
再见了,朋友们,我将来会想念你们的。
再见了,敌人们,我曾经热衷于憎恨你们。
还是写点总结吧,以下内容比较乱也不成系统。
公司
薪资待遇低
职业规划模糊
官僚气流行
1.NS习惯思维是考查员工。考查时间比较长,一般人没耐心等完就走了,所以大家感觉工资不高。
2.NS这样的大公司里员工一般都是零件的角色。员工在一个工作时间长了没变化,工作单调了,自然会走。
3.一般想干事业的人是不会在官僚气很重的公司待下去。搞技术的人更是这样。
部门
纵容能力不足的人
虚事实做,实事虚做
忽视员工心理需要
开会效率低下
指导少,指责多
压抑员工交流
上面说的比较具体,再胡乱说两句。没有责罚的要求就不是要求。员工是公司第一客户。公司的竞争就是人的竞争。员工是领导的比例放大。
结论
层次不高的战略定位,混乱无能的管理,流于形式的制度,没有收益权的员工只好离开。
最后引用老牛的一句话:“财聚人散,财散人聚”。

2008年4月的牢骚

www.rootkit.com完成迁移了,和我开blog时间差不多,纪念一下。Hoglund发文《IRP hooking and Deivice Chains》。
IoCreateDevice简单分析
函数原型为:
NTSTATUS
IoCreateDevice(
IN PDRIVER_OBJECT DriverObject,
IN ULONG DeviceExtensionSize,
IN PUNICODE_STRING DeviceName OPTIONAL,
IN DEVICE_TYPE DeviceType,
IN ULONG DeviceCharacteristics,
IN BOOLEAN Exclusive,
OUT PDEVICE_OBJECT *DeviceObject
);
1、先查看DeviceCharacteristics参数中的FILE_AUTOGENERATED_DEVICE_NAME属性如果存在,则要自动生成一个设备名字。IopUniqueDeviceObjectNumber用来保存最大数字,每次使用都会加1。调用IopCreateDefaultDeviceSecurityDescriptor产生默认的设备安全描述符。根据DeviceType设置SectorSize的数值,主要看文件系统相关的类型。CDROM被设置为2048,其它的被设置为512。
2、初始化对象属性,设置Attributes字段为OBJ_EXCLUSIVE、OBJ_PERMANENT属性。再计算好设备对象和设备扩展大小的8字节对齐后,用IoDeviceObjectType参数调用ObCreateObject,如果返回名字冲突STATUS_OBJECT_NAME_COLLISION,那么重新执行以上操作。
3、填充设备对象的数据。设备对象定义如下:
typedef struct _DEVICE_OBJECT {
CSHORT Type; //IO_TYPE_DEVICE
USHORT Size; //sizeof( DEVICE_OBJECT ) + DeviceExtensionSize
LONG ReferenceCount;
struct _DRIVER_OBJECT *DriverObject;
struct _DEVICE_OBJECT *NextDevice;
struct _DEVICE_OBJECT *AttachedDevice;
struct _IRP *CurrentIrp;
PIO_TIMER Timer;
ULONG Flags; //DO_EXCLUSIVE DO_DEVICE_HAS_NAME
ULONG Characteristics; //参数DeviceCharacteristics
PVPB Vpb;
PVOID DeviceExtension;
DEVICE_TYPE DeviceType; //参数DeviceType
CCHAR StackSize; // 1
union {
LIST_ENTRY ListEntry;
WAIT_CONTEXT_BLOCK Wcb;
} Queue; //文件系统列队
ULONG AlignmentRequirement; //视硬件平台而定 HalGetDmaAlignmentRequirement() - 1
KDEVICE_QUEUE DeviceQueue; //非文件系统驱动列队
KDPC Dpc;
ULONG ActiveThreadCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
KEVENT DeviceLock;
USHORT SectorSize; //CDROM为2048,DISK为512
USHORT Spare1;
struct _DEVOBJ_EXTENSION *DeviceObjectExtension;
PVOID Reserved;
} DEVICE_OBJECT;
4、如果设备是磁盘类的,需要调用IopCreateVpb创建vpb。Vpb->RealDevice会指回DeviceObject。vpb是卷、文件系统和磁盘驱动之间的桥梁。
5、调用ObInsertObject得到HANDLE之后,再NtClose关闭。调用 IopInsertRemoveDevice把设备对象和驱动对象联系起来。DriverObject->DeviceObject -->> DeviceObject DeviceObject->NextDevice -->> 同一driver创建的设备。 DeviceObject->DriverObject -->> Driver,这样设备和驱动也联系起来了。
IoDetachDevice也不是那么容易,下面是它的流程。
1、先看看Flags中DO_SHUTDOWN_REGISTERED是否注册关机通知。
2、然后去掉Timer中的时间设置。
3、如果Flags中设置DO_DEVICE_HAS_NAME,那么去掉对象的名字使它变成临时对象。
4、用IopCompleteUnloadOrDelete删掉设备栈。



磁盘在逻辑上很好理解,可以简单的把它看做是上厕所用的卷纸。这样就有了所谓的Cylinders、Heads、Sector。
磁盘区可以分为:MBR、DBR、FAT、FDA、DATA。
MBR(Master Boot Record):位于0柱面0磁道1扇面,保存系统引导代码和磁盘分区表。代码占用446字节,DPT(Disk Partition Table)占用64字节,最后两字节是55AA。MBR占用63扇面,但只使用1扇面。
DBR(DOS Boot Record):位于0柱面1磁道1扇面,保存操作系统引导代码和BPB(BIOS Parameter Block)数据。
FAT(File Allocation Table):FAT有12、16、32三种,FAT之后是FAT的复本。
FDT(File Directory Table):FAT32中FDT被融合进DATA区了。



| -------->\Device\volsnap (volsnap) |
|irp | | |
| | |irp |
FSD(NTFS) | | |
vpb->realdevice ----|------->\Device\HarddiskX\VolumeX (ftdisk) vpb ---->
|irp | |
| | |
MED irp | |irp
vpb->device---------- |
|
\Device\partmgr (partmgr)
|
|irp
|
\Device\HarddiskX\DRX (disk)
|
|irp
|
\Device\ide\ideportX (atapi)


Windows NT和传奇人物的故事见如下连接:
自己写的东西就不拿出来现丑了。
Gary Kimura是华盛顿大学教授和微软员工(也是我心里偶像=_=!)。
现在可以得到的FAT代码都是他的大作。
不知道他在学校给学生上课的时候会不会透露NTFS的内幕给他的学生(一一!)。
和我一样崇拜的人可以在这看看他的照片:
http://www.cs.washington.edu/homes/garyki/

如果问IRP是什么,那么就不得不说起Darryl Havens。
如果你被这个东西搞的迷迷糊糊又十分佩服其高深,那你一定想看看设计者吧?
他的这张照片比较帅,嘿嘿。

http://www.msblog.org/ 关注微软,应该常去看看。
http://www.isjfk.org/ 看看搞Java的人都在忙什么 :-)。
http://www.joelonsoftware.com/ 如何理解软件。
http://www.joelonsoftware.com/articles/fog0000000339.html 打开编辑器就OK了。

进入IT教育行业可以使我获得较高收入,为此我也困惑了很久。不过,一个故事改变了我。见记录片《默格勒先生的礼物》。
学习的道理是相通的。就象练武,有的人喜欢练内功,有的人喜欢练外功。
刚开始学习的人,总是喜欢花架子。不过随着对学习理解的不断深入,有的人会把功夫下在打基础上而提高自己的修养。但也有的人仍然浮于表面而无法 入门。这个过程不只是知识的积累过程,也是一个心态调整的过程。心态好的人由于基础好而更容易学习新的知识,尽管这些人开始的时候表现为学习很慢。
不可否认,中国大多数从业者还处在行业低端。水平不够,自然心态不好。而且想要入行的人,在入行之前接受了太多的误导信息。他们的心态更加糟 糕。很多从教育机构出来的人结果也并不好。天下没有免费的午餐,他们想要入行,还是要把功夫补上的。也许有人会说这是老师的问题,不过我在给学生上过课之 后并不这么觉得。更让人忧虑的是在各种更加方便、傻瓜的编程方式、工具开发出来以后,更多的人沉迷其中,找不到方向。这就象我们即使可以使用智能ABC书 写汉字,但也要苦练书法一样。编程高手们还是喜欢用vi(m)、emacs、ultraedit、甚至是记事本。工具只是工具,我们不应该被工具束缚住。
所以几年内我不大会去教育机构。如果觉得自己该干什么就动手去干什么。如果真想做点什么,未必一定身在其中。
最近看VISTA DDK 6000文档,和一年前一样。一年前看的是2003的SDK、IFS DDK。那时候只有一个感觉:windows的设计确实先进。可看了Vista的文档,我还是觉得眼前一亮非常精彩。我建议想学windows朋友也来看 看MSDN。如果你找不到好书,反而耽误时间。我们总骂微软如何如何,但看看人家的文档,再比较下我们的教材,就剩惭愧二字。
至于说分享代码,我只知道Richard stallman 没有过后悔的言论。对于热爱软件而又有深厚功底的程序员来说,分享代码是一件享受的事情。
文化如下:
http://www.aka.org.cn/Docs/hacker-howto_2001.html


非常羡慕数学好的同学。
值得关注:
https://www.xfocus.net/bbs/index.php?act=ST&f=2&t=66683

学计算机已经有些年头了,虽然有点长进,但远远谈不上深入。
周末同事问我Linux方面的事情。我们交谈开始时还很自信。可渐渐的信心一点点消失,直到脑袋里一片空白。更加惭愧的是对TCP/IP详解2提到的路由算法和Linux kernel 2.6的文件缓存算法radix tree一点印象都没有。

binary search tree:
http://www.cs.fiu.edu/~weiss/dsaa_c2e/tree.c
压缩方面的应用见:
https://www.xfocus.net/bbs/index.php?act=ST&f=3&t=66431

AVL tree:
http://www.cs.fiu.edu/~weiss/dsaa_c2e/avltree.c

AVL tree要求任何节点的左右子数高度差最多为1。而RB tree要比AVL的条件宽,在特殊情况下就变成AVL tree。Windows Server 2003的虚拟内存管理使用AVL tree。

单旋可以平衡外侧插入的情况。而双旋可以平衡内侧插入的情况。叫双旋的原因是经过了两次单旋。根据平衡树一边大一边小的特点,旋转(改变)根节点会平衡子树的长度差距。

radix tree:
http://www.gelato.unsw.edu.au/lxr/source/lib/radix-tree.c
Linux Cache:
http://www.ibm.com/developerworks/cn/linux/l-cache/
FreeBSD Route:
http://blog.chinaunix.net/u/9831/showart_58142.html

至于思想嘛:hashtable + searchtree


还在Neusoft的同事给了我三本书。其中有一本季羡林的著作合集《季羡林谈人生》。随手翻了三篇就已经爱不释手了。虽然成文多年,但文章还是给了我强烈的震撼。书中随处可以看到一些被谈论过无数遍的话题被重新赋予新的观点和见解。

可自己又何时可以随意扮演
完美者、给予者、实践者、浪漫者、观察者、质问者、享乐者、支配者、媒介者
不同的角色切换
完美型、全爱型、成就型、艺术型、智能型、忠诚型、丰富型、能力型、和平型
不同类型
驾御自己的性格,改变自己的命运。

乱糟糟的写了一堆,说点实际的。
Addylee 和我聊过网卡负载平衡的问题。这方面的软件早就有了,比如NICExpress。但我们聊的问题本应该是miniport driver,但这家伙却有新的想法。他想在网络连接里隐藏真实的网卡只显示虚拟网卡。我的反应是双击网络连接图标时一定调用了API GetInterfacesInfo。然后去找GetInterfacesInfo的代码,发现和SYSTEM\CurrentControlSet\ Control\Network下的键值有关。不过,DDK里好象没有提到这个东西。那是谁把“本地连接”写进去的呢?
晚上终于忍不住了,用 RegMon找到了“真凶”。Network Connection,以svchost为宿主的服务。如果miniport driver的inf指出驱动是实际网卡,那么网络连接里就是“本地连接N”,否则就是显示驱动描述字符。那么接下来,Interface系列API再向 \Device\Tcp里发送查询信息Irp就可以得到接口参数了。不过,要想达到老兄说的目的还是不大好办,要两边一起骗。

今天更新了TDI挂接的那篇博客,在看之前不妨回顾下Addylee关于NDIS驱动的文章:
http://www.xfocus.net/articles/200605/865.html


题目有点大。如果Vista真的广泛使用.net提供的WPF,而通过DirectX技术访问显卡,那么我还
要有很长的路要走。现在我有两个问题需要确定:一、终端服务能否截获DX,二、UltraVNC在Vista下的表现究竟怎么样。在看了《探究windows 2003终端服务实现内幕》后,我找到了
这本《Windows Graphics Programming Win32 GDI and DirectDraw》。以前对Win32的研究确实
很少,没想到这已经是八年前的书了,而且众多windows kernel剖析书籍也没有提供相应的知
识。在网络中搜索了很久似乎也没有结果,很多人都私藏等着卖钱。当然我知道这条路并不好
走,眼下有几个不是资料的“资料”要去分析。Vista Xp DDK、UltraVNC的驱动、高效截屏的
代码、Feng Yuan和WebCrazy的研究成果。


看到项目里的代码使用了ObQueryObjectName心里一凉。细一看,还好。不是文件,只是普通
的设备。如果文件是用同步打开,那么这次Query可能要使你的代码睡到关机。
在UltraVNC里找了一大堆驱动,还不知道哪个是需要看的,还有终端服务的两个rdpdd.dll和
rdpcdd.sys驱动。如果没有Ctrl+F5的强大能力,事情真是不敢想象。
PnP也不是省油的灯。IoRegisterPlugPlayNotification貌似是在设备安装成功以后才起作用
的。不过,使用Device Interface Class是很方便的事。最后还是选择在它之前的IRP_MN_START_DEVICE里做坏事吧。


最近对图形方面的东西很有兴趣。我记得给我留下深刻印象的3D特技是29A病毒杂志的封面。
虽然以前看过游戏开发方面的书,但都不怎么深入。mirror驱动的理论部分已经调研得差不多
了,下周可以开发了。本来应该进行知识梳理,但考虑到现在的非常时期,还是不能停下脚
步。再过一个月,应该可以确定我一两年内的工作和发展了。

《微软和开源》里提到了DirectX和OpenGL的故事。
http://chrishecker.com/OpenGL
http://www.directx.com/home.htm
http://www.mesa3d.org

John Carmack对它们的看法:http://www.directx.com/carmack.htm

入门教程:
http://www.euclideanspace.com/

书:
《3D Math Primer for Graphics and Game Development》

游戏:
http://www.gamedev.net/
http://www.gamasutra.com/


ZwCreateFile不厚道。FILE_NO_INTERMEDIATE_BUFFERING给了我点提示,要不然不知道要卡我多久。 IoBuildSynchronousFsdRequest还是比较厚道的,在介绍Length的时候提了一句,可他的把兄弟 IoBuildAsynchronousFsdRequest却守口如瓶。ZwReadFile应该是有问题的,我以为他会帮我对齐长度和地址,可他却没 有,太伤我心了。
最近磁盘玩的比较多,看看这个吧:
http://blog.csdn.net/hotsolaris/archive/2007/10/20/1834162.aspx