Skip to content

3) samsrv!SampUpdateEncryption()

用IDA Pro 4.6.0.785逆向英文版XP SP1的samsrv!SampUpdateEncryption:

下面是C风格的伪代码:


/ * samsrv.dll中定义的全局变量 / extern PSAM_DOMAIN SampDefinedDomains;

/ * 我猜不出var_9、var_10的意义所在,也没时间逆得更深,暂时先不管这两个变量 * 了,以后有时间再来修正。 * * status不是栈式局部变量,在汇编代码中不直接对应某个内存位置。 * * 标号SampUpdateEncryption_exit不直接对应汇编代码中的标号,毕竟逆向是试着 * 还原最初的C代码,要考虑编译器的工作。 / NTSTATUS __stdcall SampUpdateEncryption ( HANDLE samhandle // 第01形参,[EBP+0x008] ) { BOOL nomoredata; // 第01个局部变量,[EBP-0x001] // 由于对齐优化的缘故实际将占去4字节 HANDLE ContextHandle; // 第02个局部变量,[EBP-0x008] PSAM_DOMAIN_USER_ENUMERATION DomainUserEnumeration; // 第03个局部变量,[EBP-0x00C] HANDLE DomainHandle; // 第04个局部变量,[EBP-0x010] PSAM_PRIVATE_USER_DATA PrivateUserData; // 第05个局部变量,[EBP-0x014] HANDLE SamHandle; // 第06个局部变量,[EBP-0x018] DWORD UserCount; // 第07个局部变量,[EBP-0x01C] HANDLE EnumerationHandle; // 第08个局部变量,[EBP-0x020] var_9; // 第09个局部变量,[EBP-0x024] var_10; // 第10个局部变量,[EBP-0x028] NTSTATUS status; DWORD count;

DomainHandle            = ( HANDLE )NULL;
ContextHandle           = ( HANDLE )NULL;
SamHandle               = ( HANDLE )NULL;
EnumerationHandle       = ( HANDLE )NULL;
DomainUserEnumeration   = ( PSAM_DOMAIN_USER_ENUMERATION )NULL;
nomoredata              = FALSE;
PrivateUserData         = ( PSAM_PRIVATE_USER_DATA )NULL;
if ( NULL == samhandle )
{
    status      = SamIConnect
                  (
                      0,
                      &SamHandle,     // [out]参数
                      0x000F003F,     // Access Mask,参SamrConnect2()的Ethereal解码
                      1
                  );
    if ( !NT_SUCCESS( status ) )
    {
        goto SampUpdateEncryption_exit;
    }
    samhandle   = SamHandle;
}
status  = SamrOpenDomain
          (
              samhandle,
              0x00000301,                     // Access Mask,参Ethereal解码
              SampDefinedDomains->DomainSid,
              &DomainHandle                   // [out]参数
          );
if ( !NT_SUCCESS( status ) )
{
    goto SampUpdateEncryption_exit;
}
var_9   = DomainHandle->Unkown_0E0;
/*
 * 下面这段我实在没法逆成C风格的伪代码,SAM_DOMAIN结构未明。显然var_9
 * 是个Index,0x340是sizeof( struct xxx )。但结构数组的偏移未必是0x19E,
 * 注意到+0x344处是DomainSid。DomainSid很可能并不直接是SAM_DOMAIN结构
 * 的成员,而是第一个xxx结构的成员。SAM_DOMAIN结构中包含xxx结构数组。
 * 此处无关本次意图,放弃之,下面的汇编代码不是直接反汇编的结果。
 */
status  = 0;
__asm
{
    test    byte ptr [var_9 * 0x340 + SampDefinedDomains + 19Eh],1
    jz      offset SampUpdateEncryption_exit
}
do
{
    status                  = SamrEnumerateUsersInDomain
                              (
                                  DomainHandle,             // Context Handle
                                  &EnumerationHandle,       // [in/out]参数,Resume Handle
                                  0,                        // filter,Access Mask
                                  &DomainUserEnumeration,   // [out]参数
                                  0x0000FFFF,               // 意义未明,似乎对应Pref MaxSize
                                  &UserCount                // [out]参数
                              );
    if ( !NT_SUCCESS( status ) )
    {
        goto SampUpdateEncryption_exit;
    }
    /*
     * from ntstatus.h(\WINDDK\2600.1106\inc\ddk\wxp\)
     *
     * Returned by enumeration APIs to indicate more information is
     * available to successive calls.
     *
     * #define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
     */
    if ( STATUS_MORE_ENTRIES != status )
    {
        nomoredata = TRUE;
    }
    count                   = 0;
    while ( count < UserCount )
    {
        status          = SampAcquireWriteLock();
        if ( !NT_SUCCESS( status ) )
        {
            /*
             * 注意这是do-while循环里嵌套while循环
             */
            goto SampUpdateEncryption_exit;
        }
        SampSetTransactionDomain( var_9 );
        status          = SampCreateAccountContext
                          (
                              4,
                              DomainUserEnumeration->DomainUser[count],
                              1,
                              0,
                              1,
                              &ContextHandle  // [out]参数
                          );
        if ( !NT_SUCCESS( status ) )
        {
            /*
             * 与SampAcquireWriteLock()配对
             */
            SampReleaseWriteLock( FALSE );
            goto SampUpdateEncryption_exit;
        }
        status          = SampGetPrivateUserData
                          (
                              ContextHandle,
                              &var_10,
                              &PrivateUserData
                          );
        if ( !NT_SUCCESS( status ) )
        {
            SampReleaseWriteLock( FALSE );
            goto SampUpdateEncryption_exit;
        }
        status          = SampSetPrivateUserData
                          (
                              ContextHandle,
                              var_10,
                              PrivateUserData
                          );
        MIDL_user_free( PrivateUserData );
        PrivateUserData = NULL;
        if ( !NT_SUCCESS( status ) )
        {
            SampReleaseWriteLock( FALSE );
            goto SampUpdateEncryption_exit;
        }
        SampStoreObjectAttributes
        (
            ContextHandle,
            NULL
        );
        /*
         * 与SampCreateAccountContext()配对
         */
        status          = SampDeleteContext( ContextHandle );
        ContextHandle   = NULL;
        if ( !NT_SUCCESS( status ) )
        {
            SampReleaseWriteLock( FALSE );
            goto SampUpdateEncryption_exit;
        }
        SampSetTransactionWithinDomain( NULL );
        /*
         * 与SampAcquireWriteLock()配对
         */
        status          = SampReleaseWriteLock( TRUE );
        if ( !NT_SUCCESS( status ) )
        {
            goto SampUpdateEncryption_exit;
        }
        count++;
    }  /* end of while */
    SamIFree_SAMPR_ENUMERATION_BUFFER
    (
        ( PSAM_ENUMERATION_BUFFER )DomainUserEnumeration
    );
    DomainUserEnumeration   = NULL;
}
while ( FALSE == nomoredata );

SampUpdateEncryption_exit:

if ( NULL != ContextHandle )
{
    /*
     * 与SampCreateAccountContext()配对
     */
    SampDeleteContext( ContextHandle );
}
if ( NULL != DomainHandle )
{
    /*
     * 与SamrOpenDomain()配对
     */
    SamrCloseHandle( &DomainHandle );
}
if ( NULL != SamHandle )
{
    /*
     * 与SamIConnect()配对
     */
    SamrCloseHandle( &SamHandle );
}
if ( NULL != DomainUserEnumeration )
{
    SamIFree_SAMPR_ENUMERATION_BUFFER
    (
        ( PSAM_ENUMERATION_BUFFER )DomainUserEnumeration
    );
}
return( status );

} / end of SampUpdateEncryption /

对比pwdump2/samdump.c,不再神密了吧,尤其是貌似突兀的STATUS_MORE_ENTRIES, 这可是正经的NTSTATUS值!

SamIFree_SAMPR_ENUMERATION_BUFFER()不只用于DomainUserEnumeration,因此其形 参类型不是PSAM_DOMAIN_USER_ENUMERATION,调用时可能需要对指针做强制类型转换。