符号链接枚举
我又回来了……2个月没什么进步了,在修炼软件产品与市场……
N年前,注册邮箱ID,zzz被人用过,一怒之下,前面随便敲了3个字母,
于是自己现在什么ID都是dhbzzz了……
不多说了,代码贴上,利用微软未公开的一些API枚举符号链接。
-------------------------------------------------------------------------------
代码
//--------------------------------------------------------------------------
// Copyright (C), 2004-2010, Zhengzz, All Rights Reserved
//
// FileName: EnumSymbolink.cpp
//
// Author: zhengzz
//
// Date: 2009-07-20
//
// Description: 枚举符号链接
//
// History: <author>zhengzz<time>2009-07-20<version>1.0
//
//-------------------------------------------------------------------------
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
// 定义函数返回值
typedef ULONG NTSTATUS;
// 宽字节字符串结构定义
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
// 对象属性定义
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
UNICODE_STRING *ObjectName;
ULONG Attributes;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
} OBJECT_ATTRIBUTES,*POBJECT_ATTRIBUTES;
// 基本信息定义
typedef struct _DIRECTORY_BASIC_INFORMATION {
UNICODE_STRING ObjectName;
UNICODE_STRING ObjectTypeName;
} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION;
// 返回值或状态类型定义
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define DIRECTORY_QUERY (0x0001)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
#define STATUS_NO_MORE_ENTRIES ((NTSTATUS)0x8000001AL)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define SYMBOLIC_LINK_QUERY (0x0001)
#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
// 初始化对象属性宏定义
#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; \
}
// 字符串初始化
typedef VOID (CALLBACK* RTLINITUNICODESTRING)(PUNICODE_STRING,PCWSTR);
RTLINITUNICODESTRING RtlInitUnicodeString;
// 字符串比较
typedef
BOOLEAN
(WINAPI *RTLEQUALUNICODESTRING)(
const UNICODE_STRING *String1,
const UNICODE_STRING *String2,
BOOLEAN CaseInSensitive
);
RTLEQUALUNICODESTRING RtlEqualUnicodeString;
// 打开对象
typedef NTSTATUS (WINAPI *ZWOPENDIRECTORYOBJECT)(
OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
ZWOPENDIRECTORYOBJECT ZwOpenDirectoryObject;
// 查询对象
typedef
NTSTATUS
(WINAPI *ZWQUERYDIRECTORYOBJECT)(
IN HANDLE DirectoryHandle,
OUT PVOID Buffer,
IN ULONG BufferLength,
IN BOOLEAN ReturnSingleEntry,
IN BOOLEAN RestartScan,
IN OUT PULONG Context,
OUT PULONG ReturnLength OPTIONAL
);
ZWQUERYDIRECTORYOBJECT ZwQueryDirectoryObject;
// 打开符号链接对象
typedef
NTSTATUS
(WINAPI *ZWOPENSYMBOLICKLINKOBJECT)(
OUT PHANDLE SymbolicLinkHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
ZWOPENSYMBOLICKLINKOBJECT ZwOpenSymbolicLinkObject;
// 查询符号链接对象
typedef
NTSTATUS
(WINAPI *ZWQUERYSYMBOLICKLINKOBJECT)(
IN HANDLE SymbolicLinkHandle,
IN OUT PUNICODE_STRING TargetName,
OUT PULONG ReturnLength OPTIONAL
);
ZWQUERYSYMBOLICKLINKOBJECT ZwQuerySymbolicLinkObject;
// 关闭已经打开的对象
typedef
NTSTATUS
(WINAPI *ZWCLOSE)(
IN HANDLE Handle
);
ZWCLOSE ZwClose;
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hNtdll = NULL;
hNtdll = LoadLibrary(_T("ntdll.dll" ));
if ( NULL == hNtdll )
{
printf("[%s]--Load ntdll.dll failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
printf("[%s]--Load ntdll.dll sucess now get proc.\r\n", __FUNCTION__);
RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress( hNtdll, "RtlInitUnicodeString");
RtlEqualUnicodeString = (RTLEQUALUNICODESTRING)GetProcAddress( hNtdll, "RtlEqualUnicodeString");
ZwOpenDirectoryObject = (ZWOPENDIRECTORYOBJECT)GetProcAddress( hNtdll, "ZwOpenDirectoryObject");
ZwQueryDirectoryObject = (ZWQUERYDIRECTORYOBJECT)GetProcAddress( hNtdll, "ZwQueryDirectoryObject");
ZwOpenSymbolicLinkObject = (ZWOPENSYMBOLICKLINKOBJECT)GetProcAddress( hNtdll, "ZwOpenSymbolicLinkObject");
ZwQuerySymbolicLinkObject = (ZWQUERYSYMBOLICKLINKOBJECT)GetProcAddress( hNtdll, "ZwQuerySymbolicLinkObject");
ZwClose = (ZWCLOSE)GetProcAddress( hNtdll, "ZwClose");
UNICODE_STRING strDirName;
OBJECT_ATTRIBUTES oba;
NTSTATUS ntStatus;
HANDLE hDirectory;
RtlInitUnicodeString(&strDirName, _T("\\global??"));
InitializeObjectAttributes(&oba, &strDirName, OBJ_CASE_INSENSITIVE, NULL, NULL);
printf("[%s]--Open directory object now.\r\n", __FUNCTION__);
ntStatus = ZwOpenDirectoryObject(&hDirectory, DIRECTORY_QUERY, &oba);
if ( ntStatus != STATUS_SUCCESS )
{
printf("[%s]--Open directory object failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
printf("[%s]--Open directory object success.\r\n", __FUNCTION__);
UNICODE_STRING symbolicLink;
UNICODE_STRING targetName;
BYTE buffer[2048] = {0};
ULONG ulLength = 2048;
ULONG ulContext = 0;
ULONG ulRet = 0;
RtlInitUnicodeString(&symbolicLink, L"SymbolicLink");
targetName.Length = 0;
targetName.Buffer = (PWSTR)calloc(2, 1024);
if ( targetName.Buffer == NULL )
{
printf("[%s]--calloc failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
targetName.MaximumLength = 1024;
do
{
ntStatus = ZwQueryDirectoryObject(hDirectory, buffer, ulLength, TRUE, FALSE, &ulContext, &ulRet);
if ( (ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_NO_MORE_ENTRIES) )
{
printf("[%s]--ZwQueryDirectoryObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
else if ( STATUS_NO_MORE_ENTRIES == ntStatus )
{
printf("[%s]--No more object.\r\n", __FUNCTION__);
goto EXIT;
}
PDIRECTORY_BASIC_INFORMATION directoryInfo = (PDIRECTORY_BASIC_INFORMATION)buffer;
printf("ObjectName: [%S]---ObjectTypeName: [%S]\n",
directoryInfo->ObjectName.Buffer, directoryInfo->ObjectTypeName.Buffer);
if ( RtlEqualUnicodeString(&directoryInfo->ObjectTypeName, &symbolicLink, TRUE) )
{
OBJECT_ATTRIBUTES symbolicLinkAttributes;
HANDLE hSymbolicLink;
// 初始化符号链接对象属性
InitializeObjectAttributes(&symbolicLinkAttributes, &directoryInfo->ObjectName,
OBJ_CASE_INSENSITIVE, hDirectory, NULL);
// 打开符号链接对象
ntStatus = ZwOpenSymbolicLinkObject(&hSymbolicLink, SYMBOLIC_LINK_QUERY, &symbolicLinkAttributes);
if ( ntStatus != STATUS_SUCCESS )
{
printf("[%s]--ZwOpenSymbolicLinkObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
// 查询符号链接对象
ntStatus = ZwQuerySymbolicLinkObject(hSymbolicLink, &targetName, NULL);
if ( ntStatus != STATUS_SUCCESS )
{
printf("[%s]--ZwQuerySymbolicLinkObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
ZwClose(hSymbolicLink);
goto EXIT;
}
// TODO: 添加针对符号链接的处理代码
// 清空targetName
memset((LPVOID)targetName.Buffer, 0, targetName.Length*sizeof(WCHAR));
// 关闭符号链接句柄
ZwClose(hSymbolicLink);
}
}while(TRUE);
EXIT:
if ( hDirectory != NULL )
{
ZwClose(hDirectory);
}
getchar();
return 0;
}
// Copyright (C), 2004-2010, Zhengzz, All Rights Reserved
//
// FileName: EnumSymbolink.cpp
//
// Author: zhengzz
//
// Date: 2009-07-20
//
// Description: 枚举符号链接
//
// History: <author>zhengzz<time>2009-07-20<version>1.0
//
//-------------------------------------------------------------------------
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
// 定义函数返回值
typedef ULONG NTSTATUS;
// 宽字节字符串结构定义
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
// 对象属性定义
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
UNICODE_STRING *ObjectName;
ULONG Attributes;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
} OBJECT_ATTRIBUTES,*POBJECT_ATTRIBUTES;
// 基本信息定义
typedef struct _DIRECTORY_BASIC_INFORMATION {
UNICODE_STRING ObjectName;
UNICODE_STRING ObjectTypeName;
} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION;
// 返回值或状态类型定义
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define DIRECTORY_QUERY (0x0001)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
#define STATUS_NO_MORE_ENTRIES ((NTSTATUS)0x8000001AL)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define SYMBOLIC_LINK_QUERY (0x0001)
#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
// 初始化对象属性宏定义
#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; \
}
// 字符串初始化
typedef VOID (CALLBACK* RTLINITUNICODESTRING)(PUNICODE_STRING,PCWSTR);
RTLINITUNICODESTRING RtlInitUnicodeString;
// 字符串比较
typedef
BOOLEAN
(WINAPI *RTLEQUALUNICODESTRING)(
const UNICODE_STRING *String1,
const UNICODE_STRING *String2,
BOOLEAN CaseInSensitive
);
RTLEQUALUNICODESTRING RtlEqualUnicodeString;
// 打开对象
typedef NTSTATUS (WINAPI *ZWOPENDIRECTORYOBJECT)(
OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
ZWOPENDIRECTORYOBJECT ZwOpenDirectoryObject;
// 查询对象
typedef
NTSTATUS
(WINAPI *ZWQUERYDIRECTORYOBJECT)(
IN HANDLE DirectoryHandle,
OUT PVOID Buffer,
IN ULONG BufferLength,
IN BOOLEAN ReturnSingleEntry,
IN BOOLEAN RestartScan,
IN OUT PULONG Context,
OUT PULONG ReturnLength OPTIONAL
);
ZWQUERYDIRECTORYOBJECT ZwQueryDirectoryObject;
// 打开符号链接对象
typedef
NTSTATUS
(WINAPI *ZWOPENSYMBOLICKLINKOBJECT)(
OUT PHANDLE SymbolicLinkHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
ZWOPENSYMBOLICKLINKOBJECT ZwOpenSymbolicLinkObject;
// 查询符号链接对象
typedef
NTSTATUS
(WINAPI *ZWQUERYSYMBOLICKLINKOBJECT)(
IN HANDLE SymbolicLinkHandle,
IN OUT PUNICODE_STRING TargetName,
OUT PULONG ReturnLength OPTIONAL
);
ZWQUERYSYMBOLICKLINKOBJECT ZwQuerySymbolicLinkObject;
// 关闭已经打开的对象
typedef
NTSTATUS
(WINAPI *ZWCLOSE)(
IN HANDLE Handle
);
ZWCLOSE ZwClose;
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hNtdll = NULL;
hNtdll = LoadLibrary(_T("ntdll.dll" ));
if ( NULL == hNtdll )
{
printf("[%s]--Load ntdll.dll failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
printf("[%s]--Load ntdll.dll sucess now get proc.\r\n", __FUNCTION__);
RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress( hNtdll, "RtlInitUnicodeString");
RtlEqualUnicodeString = (RTLEQUALUNICODESTRING)GetProcAddress( hNtdll, "RtlEqualUnicodeString");
ZwOpenDirectoryObject = (ZWOPENDIRECTORYOBJECT)GetProcAddress( hNtdll, "ZwOpenDirectoryObject");
ZwQueryDirectoryObject = (ZWQUERYDIRECTORYOBJECT)GetProcAddress( hNtdll, "ZwQueryDirectoryObject");
ZwOpenSymbolicLinkObject = (ZWOPENSYMBOLICKLINKOBJECT)GetProcAddress( hNtdll, "ZwOpenSymbolicLinkObject");
ZwQuerySymbolicLinkObject = (ZWQUERYSYMBOLICKLINKOBJECT)GetProcAddress( hNtdll, "ZwQuerySymbolicLinkObject");
ZwClose = (ZWCLOSE)GetProcAddress( hNtdll, "ZwClose");
UNICODE_STRING strDirName;
OBJECT_ATTRIBUTES oba;
NTSTATUS ntStatus;
HANDLE hDirectory;
RtlInitUnicodeString(&strDirName, _T("\\global??"));
InitializeObjectAttributes(&oba, &strDirName, OBJ_CASE_INSENSITIVE, NULL, NULL);
printf("[%s]--Open directory object now.\r\n", __FUNCTION__);
ntStatus = ZwOpenDirectoryObject(&hDirectory, DIRECTORY_QUERY, &oba);
if ( ntStatus != STATUS_SUCCESS )
{
printf("[%s]--Open directory object failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
printf("[%s]--Open directory object success.\r\n", __FUNCTION__);
UNICODE_STRING symbolicLink;
UNICODE_STRING targetName;
BYTE buffer[2048] = {0};
ULONG ulLength = 2048;
ULONG ulContext = 0;
ULONG ulRet = 0;
RtlInitUnicodeString(&symbolicLink, L"SymbolicLink");
targetName.Length = 0;
targetName.Buffer = (PWSTR)calloc(2, 1024);
if ( targetName.Buffer == NULL )
{
printf("[%s]--calloc failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
targetName.MaximumLength = 1024;
do
{
ntStatus = ZwQueryDirectoryObject(hDirectory, buffer, ulLength, TRUE, FALSE, &ulContext, &ulRet);
if ( (ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_NO_MORE_ENTRIES) )
{
printf("[%s]--ZwQueryDirectoryObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
else if ( STATUS_NO_MORE_ENTRIES == ntStatus )
{
printf("[%s]--No more object.\r\n", __FUNCTION__);
goto EXIT;
}
PDIRECTORY_BASIC_INFORMATION directoryInfo = (PDIRECTORY_BASIC_INFORMATION)buffer;
printf("ObjectName: [%S]---ObjectTypeName: [%S]\n",
directoryInfo->ObjectName.Buffer, directoryInfo->ObjectTypeName.Buffer);
if ( RtlEqualUnicodeString(&directoryInfo->ObjectTypeName, &symbolicLink, TRUE) )
{
OBJECT_ATTRIBUTES symbolicLinkAttributes;
HANDLE hSymbolicLink;
// 初始化符号链接对象属性
InitializeObjectAttributes(&symbolicLinkAttributes, &directoryInfo->ObjectName,
OBJ_CASE_INSENSITIVE, hDirectory, NULL);
// 打开符号链接对象
ntStatus = ZwOpenSymbolicLinkObject(&hSymbolicLink, SYMBOLIC_LINK_QUERY, &symbolicLinkAttributes);
if ( ntStatus != STATUS_SUCCESS )
{
printf("[%s]--ZwOpenSymbolicLinkObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
goto EXIT;
}
// 查询符号链接对象
ntStatus = ZwQuerySymbolicLinkObject(hSymbolicLink, &targetName, NULL);
if ( ntStatus != STATUS_SUCCESS )
{
printf("[%s]--ZwQuerySymbolicLinkObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
ZwClose(hSymbolicLink);
goto EXIT;
}
// TODO: 添加针对符号链接的处理代码
// 清空targetName
memset((LPVOID)targetName.Buffer, 0, targetName.Length*sizeof(WCHAR));
// 关闭符号链接句柄
ZwClose(hSymbolicLink);
}
}while(TRUE);
EXIT:
if ( hDirectory != NULL )
{
ZwClose(hDirectory);
}
getchar();
return 0;
}