关于进程与端口映射的文章已经有很多了 我把我对fport的分析也写出来 让大家知道fport是如何工作的 fport exe是由foundstone team出品的免费软件 可以列出系统中所有开放的端口都是由那些进程打开的 而下面所描述的方法是基于fport v 的 如果和你机器上的fport有出入 请检查fport版本
首先 它检测当前用户是否拥有管理员权限(通过读取当前进程的令牌可知当前用户是否具有管理权限 请参考相关历程) 如果没有 打印一句提示后退出 然后设置当前进程的令牌 接着 用ZwOpenSection函数打开内核对象DevicePhysicalMemory 这个对象用于对系统物理内存的访问 ZwOpenSection函数的原型如下:
NTSYSAPI
NTSTSTUS
NTAPI
ZwOpenSection(
Out PHANDLE sectionHandle
IN ACCESS_MASK DesiredAccess
IN POBJECT_ATTRIBUTES ObjectAttributes
}
(见ntddk h)
第一个参数得到函数执行成功后的句柄
第二个参数DesiredAccess为一个常数 可以是下列值:
#define SECTION_QUERY x
#define SECTION_MAP_WRITE x
#define SECTION_MAP_READ x
#define SECTION_MAP_EXECUTE x
#define SECTION_EXTEND_SIZE x
#define SECTION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY| SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE)
(见ntddk h)
第三个参数是一个结构 包含要打开的对象类型等信息 结构定义如下:
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length
HANDLE RootDirectory
PUNICODE_STRING ObjectName
ULONG Attributes
PVOID SecurityDescriptor // Points to type SECURITY_DESCRIPTOR
PVOID SecurityQualityOfService // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES
(见ntdef h)
对于这个结构的初始化用一个宏完成:
#define InitializeObjectAttributes( p n a r s ) { (p) >Length = sizeof( OBJECT_ATTRIBUTES ) (p) >RootDirectory = r (p) >Attributes = a (p) >ObjectName = n (p) >SecurityDescriptor = s (p) >SecurityQualityOfService = NULL }
(见ntdef h)
那么 打开内核对象DevicePhysicalMemory的语句如下:
WCHAR PhysmemName[] = L \Device\PhysicalMemory
void * pMapPhysicalMemory
HANDLE pHandle
bool OpenPhysicalMemory()
{
NTSTATUS status
UNICODE_STRING physmemString
OBJECT_ATTRIBUTES attributes
RtlInitUnicodeString( &physmemString PhysmemName ) //初始化Unicode字符串 函数原型见ntddk h
InitializeObjectAttributes( &attributes &physmemString
OBJ_CASE_INSENSITIVE NULL NULL ) //初始化OBJECT_ATTRIBUTES结构
status = ZwOpenSection(pHandle SECTION_MAP_READ &attributes ) //打开内核对象DevicePhysicalMemory 获得句柄
if( !NT_SUCCESS( status ))
return false
pMapPhysicalMemory=MapViewOfFile(pHandle FILE_MAP_READ
x x )
//从内存地址 x 开始映射 x 个字节
if( GetLastError()!= )
return false
return true
}
为什么要从 x 开始映射呢 是这样 我们知道 在Windows NT/ 下 系统分为内核模式和用户模式 也就是我们所说的Ring 和Ring 在Windows NT/ 下 我们所能够看到的进程都运行在Ring 下 一般情况下 系统进程(也就是System进程)的页目录(PDE)所在物理地址地址为 x 或者说 系统中最小的页目录所在的物理地址为 x 而页目录(PDE)由 项组成 每项均指向一页表(PTE) 每一页表也由 个页组成 而每页的大小为 K * = ( x ) 所以 上面从物理地址 x 开始映射了 x 个字节 (具体描述见WebCrazy的文章< 的分页机制>>)
程序打开打开内核对象DevicePhysicalMemory后 继续用函数ZwOpenFile打开内核对象DeviceTcp和DeviceUdp ZwOpenFile
函数的原型如下:
NTSYSAPI
NTSTATUS
NTAPI
ZwOpenFile(
OUT PHANDLE FileHandle
IN ACCESS_MASK DesiredAccess
IN POBJECT_ATTRIBUTES ObjectAttributes
OUT PIO_STATUS_BLOCK IoStatusBlock
IN ULONG ShareAccess
IN ULONG OpenOptions
)
(见ntddk h)
第一个参数返回打开对象的句柄
第二个参数DesiredAccess为一个常数 可以是下列值:
#define FILE_READ_DATA( x ) // file & pipe
#define FILE_LIST_DIRECTORY ( x ) // directory
#define FILE_WRITE_DATA ( x ) // file & pipe
#define FILE_ADD_FILE ( x ) // directory
#define FILE_APPEND_DATA ( x ) // file
#define FILE_ADD_SUBDIRECTORY ( x ) // directory
#define FILE_CREATE_PIPE_INSTANCE ( x ) // named pipe
#define FILE_READ_EA ( x ) // file & directory
#define FILE_WRITE_EA ( x ) // file & directory
#define FILE_EXECUTE ( x ) // file
#define FILE_TRAVERSE ( x ) // directory
#define FILE_DELETE_CHILD( x ) // directory
#define FILE_READ_ATTRIBUTES( x ) // all
#define FILE_WRITE_ATTRIBUTES ( x ) // all
#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | x FF)
#define FILE_GENERIC_READ(STANDARD_RIGHTS_READ |FILE_READ_DATA |FILE_READ_ATTRIBUTES |FILE_READ_EA |SYNCHRONIZE)
#define FILE_GENERIC_WRITE (STANDARD_RIGHTS_WRITE |FILE_WRITE_DATA |FILE_WRITE_ATTRIBUTES |FILE_WRITE_EA|FILE_APPEND_DATA|SYNCHRONIZE)
#define FILE_GENERIC_EXECUTE(STANDARD_RIGHTS_EXECUTE |FILE_READ_ATTRIBUTES |FILE_EXECUTE |SYNCHRONIZE)
(见ntdef h)
第三个参数是一个结构 包含要打开的对象类型等信息 结构定义见上面所述
第四个参数返回打开对象的属性 是一个结构 定义如下:
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status
PVOID Pointer
}
ULONG_PTR Information
} IO_STATUS_BLOCK *PIO_STATUS_BLOCK
#if defined(_WIN )
typedef struct _IO_STATUS_BLOCK {
NTSTATUS Status
ULONG Information
} IO_STATUS_BLOCK *PIO_STATUS_BLOCK
#endif
(见ntddk h)
第五个参数ShareAccess是一个常数 可以是下列值:
#define FILE_SHARE_READ x // winnt
#define FILE_SHARE_WRITE x // winnt
#define FILE_SHARE_DELETE x // winnt
(见ntddk h)
第六个参数OpenOptions也是一个常数 可以是下列的值:
#define FILE_DIRECTORY_FILE x
#define FILE_WRITE_THROUGH x
#define FILE_SEQUENTIAL_ONLY x
#define FILE_NO_INTERMEDIATE_BUFFERING x
#define FILE_SYNCHRONOUS_IO_ALERT x
#define FILE_SYNCHRONOUS_IO_NONALERT x
#define FILE_NON_DIRECTORY_FILE x
#define FILE_CREATE_TREE_CONNECTION x
#define FILE_COMPLETE_IF_OPLOCKED x
#define FILE_NO_EA_KNOWLEDGE x
#define FILE_OPEN_FOR_RECOVERY x
#define FILE_RANDOM_ACCESS x
#define FILE_DELETE_ON_CLOSE x
#define FILE_OPEN_BY_FILE_ID x
#define FILE_OPEN_FOR_BACKUP_INTENT x
#define FILE_NO_COMPRESSION x
#define FILE_RESERVE_OPFILTER x
#define FILE_OPEN_REPARSE_POINT x
#define FILE_OPEN_NO_RECALL x
#define FILE_OPEN_FOR_FREE_SPACE_QUERY x
#define FILE_COPY_STRUCTURED_STORAGE x
#define FILE_STRUCTURED_STORAGE x
#define FILE_VALID_OPTION_FLAGS x ffffff
#define FILE_VALID_PIPE_OPTION_FLAGS x
#define FILE_VALID_MAILSLOT_OPTION_FLAGS x
#define FILE_VALID_SET_FLAGS x
(见ntddk h)
那么 打开内核对象DeviceTcp和DeviceUdp的语句如下:
WCHAR physmemNameTcp[]=L \Device\TCP
WCHAR physmemNameUdp[]=L \Device\UDP
HANDLE pTcpHandle
HANDLE pUdpHandle