⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 29a-7.024

📁 从29A上收集的病毒源码
💻 024
📖 第 1 页 / 共 4 页
字号:
	We will use class ObjectNameInformation and ObjectAllTypesInformation.
ObjectNameInfromation class will fill the buffer with OBJECT_NAME_INFORMATION 
structure, ObjectAllTypesInformation class with OBJECT_ALL_TYPES_INFORMATION 
structure then.

	#define ObjectNameInformation 1
	#define ObjectAllTypesInformation 3

	typedef struct _OBJECT_NAME_INFORMATION {
		UNICODE_STRING Name;
	} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;

	Name determines the name of the handle.


	typedef struct _OBJECT_TYPE_INFORMATION {
		UNICODE_STRING Name;
		ULONG ObjectCount;
		ULONG HandleCount;
		ULONG Reserved1[4];
		ULONG PeakObjectCount;
		ULONG PeakHandleCount;
		ULONG Reserved2[4];
		ULONG InvalidAttributes;
		GENERIC_MAPPING GenericMapping;
		ULONG ValidAccess;
		UCHAR Unknown;
		BOOLEAN MaintainHandleDatabase;
		POOL_TYPE PoolType;
		ULONG PagedPoolUsage;
		ULONG NonPagedPoolUsage;
	} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;

	typedef struct _OBJECT_ALL_TYPES_INFORMATION {
		ULONG NumberOfTypes;
		OBJECT_TYPE_INFORMATION TypeInformation;
	} OBJECT_ALL_TYPES_INFORMATION, *POBJECT_ALL_TYPES_INFORMATION;

	Name determines the name of type object which immediately follows 
each OBJECT_TYPE_INFORMATION structure. The next OBJECT_TYPE_INFORMATION 
structure follows this Name, starting on the first four-byte boundary.
	
	ObjectTypeNumber from SYSTEM_HANDLE_INFORMATION structure is an index 
to TypeInformation array.

	Harder is to get the name of handle from other process. There are two 
possibilities how to name it. First is to copy the handle via NtDuplicateObject 
to our process and then to name it. This method will fail for some specific 
types of handles. But it will fail only for few, so we can stay calm and use 
this.

	NtDuplicateObject(
		IN HANDLE SourceProcessHandle,
		IN HANDLE SourceHandle,
		IN HANDLE TargetProcessHandle,
		OUT PHANDLE TargetHandle OPTIONAL,
		IN ACCESS_MASK DesiredAccess,
		IN ULONG Attributes,
		IN ULONG Options
	);

	SourceProcessHandle is a handle of process which owns SourceHandle 
which is the handle we want to copy. TargetProcessHandle is handle of process 
where to copy. This will be handle to our process in our case. TargetHandle 
is the pointer on handle where to save a copy of original handle. DesiredAccess 
should be set to PROCESS_QUERY_INFORMATION, Attribures and Options to 0.

	Second naming method which works with any handle is to use system 
driver. Source code for this is available in OpHandle project on my site 
http://rootkit.host.sk.



=====[ 10. Ports ]==============================================================

	The easiest way to enumarate open ports is to use functions called 
AllocateAndGetTcpTableFromStack and AllocateAndGetUdpTableFromStack, and or
AllocateAndGetTcpExTableFromStack and AllocateAndGetUdpExTableFromStack from
iphlpapi.dll. The Ex functions are available since Windows XP.


	typedef struct _MIB_TCPROW {
		DWORD dwState;
		DWORD dwLocalAddr;
		DWORD dwLocalPort;
		DWORD dwRemoteAddr;
		DWORD dwRemotePort;
	} MIB_TCPROW, *PMIB_TCPROW;

	typedef struct _MIB_TCPTABLE {
		DWORD dwNumEntries;
		MIB_TCPROW table[ANY_SIZE];
	} MIB_TCPTABLE, *PMIB_TCPTABLE;

	typedef struct _MIB_UDPROW {
		DWORD dwLocalAddr;
		DWORD dwLocalPort;
	} MIB_UDPROW, *PMIB_UDPROW;

	typedef struct _MIB_UDPTABLE {
		DWORD dwNumEntries;
		MIB_UDPROW table[ANY_SIZE];
	} MIB_UDPTABLE, *PMIB_UDPTABLE;

	typedef struct _MIB_TCPROW_EX
	{
		DWORD dwState;
		DWORD dwLocalAddr;
		DWORD dwLocalPort;
		DWORD dwRemoteAddr;
		DWORD dwRemotePort;
		DWORD dwProcessId;
	} MIB_TCPROW_EX, *PMIB_TCPROW_EX;

	typedef struct _MIB_TCPTABLE_EX
	{
		DWORD dwNumEntries;
		MIB_TCPROW_EX table[ANY_SIZE];
	} MIB_TCPTABLE_EX, *PMIB_TCPTABLE_EX;

	typedef struct _MIB_UDPROW_EX
	{
		DWORD dwLocalAddr;
		DWORD dwLocalPort;
		DWORD dwProcessId;
	} MIB_UDPROW_EX, *PMIB_UDPROW_EX;

	typedef struct _MIB_UDPTABLE_EX
	{
		DWORD dwNumEntries;
		MIB_UDPROW_EX table[ANY_SIZE];
	} MIB_UDPTABLE_EX, *PMIB_UDPTABLE_EX;

	DWORD WINAPI AllocateAndGetTcpTableFromStack(
		OUT PMIB_TCPTABLE *pTcpTable,
		IN BOOL bOrder,
		IN HANDLE hAllocHeap,
		IN DWORD dwAllocFlags,
		IN DWORD dwProtocolVersion;
	);

	DWORD WINAPI AllocateAndGetUdpTableFromStack(
		OUT PMIB_UDPTABLE *pUdpTable,
		IN BOOL bOrder,
		IN HANDLE hAllocHeap,
		IN DWORD dwAllocFlags,
		IN DWORD dwProtocolVersion;
	);

	DWORD WINAPI AllocateAndGetTcpExTableFromStack(
		OUT PMIB_TCPTABLE_EX *pTcpTableEx,
		IN BOOL bOrder,
		IN HANDLE hAllocHeap,
		IN DWORD dwAllocFlags,
		IN DWORD dwProtocolVersion;
	);

	DWORD WINAPI AllocateAndGetUdpExTableFromStack(
		OUT PMIB_UDPTABLE_EX *pUdpTableEx,
		IN BOOL bOrder,
		IN HANDLE hAllocHeap,
		IN DWORD dwAllocFlags,
		IN DWORD dwProtocolVersion;
	);

	

	There is another way to do this stuff. When program creates a socket
and starts listening it surely has an open handle for it and for open port.
We can enumerate all open handles in the system and send them special buffer 
via NtDeviceIoControlFile to find out whether the handle is for open port 
or not. This will also give us information about the port. Because there are 
a lot of open handles we will test only handles which type is File and name 
is \Device\Tcp or \Device\Udp. Open ports have only this type and name.

	When we look to the code of iphlpapi.dll functions above we find out 
that these functions also calls NtDeviceIoControlFile and sends special buffer 
to get a list of all open ports in the system. That mean only functions we 
need to hook for hiding ports is NtDeviceIoControlFile.

	NTSTATUS NtDeviceIoControlFile(
		IN HANDLE FileHandle
		IN HANDLE Event OPTIONAL,
		IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
		IN PVOID ApcContext OPTIONAL,
		OUT PIO_STATUS_BLOCK IoStatusBlock,
		IN ULONG IoControlCode,
		IN PVOID InputBuffer OPTIONAL,
		IN ULONG InputBufferLength,
		OUT PVOID OutputBuffer OPTIONAL,
		IN ULONG OutputBufferLength
	);	

	Interesting agruments for us now are FileHandle which specify a handle 
of device to communicate with, IoStatusBlock which points to a variable that 
receives the final completion status and information about the requested 
operation, IoControlCode that is a number specifying type of the device, 
method, file access and a function. InputBuffer contains input data that are 
InputBufferLength bytes long and similarly OutputBuffer and OutputbufferLength.

       
=====[ 10.1 Netstat, OpPorts on WinXP, FPort on WinXP ]=========================

	Getting a list of all open ports is the first way which is used by e.g. 
OpPorts and FPort on Windows XP and also Netstat.
	Programs calls here NtDeviceIoControlFile twice with IoControlCode 
0x000120003. OutputBuffer is filled after a second call. Name of FileHandle is 
here alwats \Device\Tcp. InputBuffer differs for different types of call:

	1) To get an array of MIB_TCPROW InputBuffer looks as follows:

first call:
0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 

second call:
0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 
0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 


	2) To get an array of MIB_UDPROW:

first call:
0x01 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 

second call:
0x01 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 
0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 


	3) To get an array of MIB_TCPROW_EX:

first call:
0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 

second call:
0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 
0x02 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 


	4) To get an array of MIB_UDPROW_EX:

first call:
0x01 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 

second call:
0x01 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 
0x02 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 


	You can see the buffers are different in few bytes only. We can lucidly
recapitulate these:
	
	Calls we are interested in have InputBuffer[1] set to 0x04 and mainly 
InputBuffer[17] on 0x01. Only after these input data we get filled OutputBuffer
with desiderative tables. If we want to get info about TCP ports we set 
InputBuffer[0] on 0x00, or on 0x01 for information about UDP. If we want 
extended output tables (MIB_TCPROW_EX or MIB_UDPROW_EX) we use Inputbuffer[16]
in second call set to 0x02.

	If we find out the call with these parameters we can change the output 
buffer. To get number of rows in output buffer simply divide Information from 
IoStatusBlock by size of the row. Hiding of one row is easy then. Just rewrite 
it with following rows and delete last row. Don't forget to change 
OutputBufferLength and IoStatusBlock.


=====[ 10.2 OpPorts on Win2k and NT4, FPort on Win2k ]==========================

	We use NtDeviceIoControlFile with IoControlCode 0x00210012 to determine 
if the handle of File type and name \Device\Tcp or \Device\Udp is the handle of 
open port.

	So at first we compare IoControlCode and then a type and the name of 
the handle. If it is still interesting then we compare the length of input 
buffer which should be equal to the length of struct TDI_CONNECTION_IN. This 
length is 0x18. OutputBuffer is TDI_CONNETION_OUT.

	typedef struct _TDI_CONNETION_IN
	{
		ULONG UserDataLength,
		PVOID UserData,
		ULONG OptionsLength,
		PVOID Options,
		ULONG RemoteAddressLength,
		PVOID RemoteAddress
	} TDI_CONNETION_IN, *PTDI_CONNETION_IN;

	typedef struct _TDI_CONNETION_OUT
	{
		ULONG State,
		ULONG Event,
		ULONG TransmittedTsdus,
		ULONG ReceivedTsdus,
		ULONG TransmissionErrors,
		ULONG ReceiveErrors,
		LARGE_INTEGER Throughput
		LARGE_INTEGER Delay,
		ULONG SendBufferSize,
		ULONG ReceiveBufferSize,
		ULONG Unreliable,
		ULONG Unknown1[5],
		USHORT Unknown2
	} TDI_CONNETION_OUT, *PTDI_CONNETION_OUT;


	Concrete implementation of how to determine the handle is open port 
is available in source code of OpPorts on http://rootkit.host.sk. We are 
interested in hiding specific port now. We already compared InputBufferLength 
and IoControlCode. Now we have to compare RemoteAddressLength. This is always 
3 or 4 for open port. The last we have to do is to compare ReceivedTsdus from 
OutputBuffer which contains the port in network form and our list of ports we 
want to hide. Differentiate between TCP and UDP is done according to the name 
of the handle. By deleting OutputBuffer, changing IoStatusBlock and returning 
the value of STATUS_INVALID_ADDRESS we will hide this port.


       
=====[ 11. Ending ]=============================================================

	Concrete implementation of described techniques will be available with 
the source code of Hander defender rootkit in version 1.0.0 on its homepage 
http://rootkit.host.sk and on http://www.rootkit.com.
	It is possible I will add some more information about invisibility on 
Windows NT in the future. New versions of this document could also contain  
improvement of described methods or new comments. 
	Special thanks to Ratter who give me a lot of knowhow which was 
necessary to write this document and to code project Hacker defender. 
	Send all remarks to holy_father@phreaker.net or to the board on
http://rootkit.host.sk.

===================================[ End ]======================================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -