SMB的NTLM认证过程与NTLM挑战的编程实现.docx

上传人:b****6 文档编号:7749119 上传时间:2023-01-26 格式:DOCX 页数:23 大小:22.22KB
下载 相关 举报
SMB的NTLM认证过程与NTLM挑战的编程实现.docx_第1页
第1页 / 共23页
SMB的NTLM认证过程与NTLM挑战的编程实现.docx_第2页
第2页 / 共23页
SMB的NTLM认证过程与NTLM挑战的编程实现.docx_第3页
第3页 / 共23页
SMB的NTLM认证过程与NTLM挑战的编程实现.docx_第4页
第4页 / 共23页
SMB的NTLM认证过程与NTLM挑战的编程实现.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

SMB的NTLM认证过程与NTLM挑战的编程实现.docx

《SMB的NTLM认证过程与NTLM挑战的编程实现.docx》由会员分享,可在线阅读,更多相关《SMB的NTLM认证过程与NTLM挑战的编程实现.docx(23页珍藏版)》请在冰豆网上搜索。

SMB的NTLM认证过程与NTLM挑战的编程实现.docx

SMB的NTLM认证过程与NTLM挑战的编程实现

SMB的NTLM认证过程与NTLM挑战的编程实现

 //注:

本文不涉及到NTLM具体的认证算法,但是给出通过SSPI的API实现的过程。

    SMB协议可以说是WIN系统的核心协议,这里大致给大家讲解一下SMB认证登陆的过程:

    1。

协议解析栈

    CLIENT:

APP----->NET/MRP/RPCAPI------>MRXSMB.SYS------>NETBT.SYS---->TCP/IP

                                                           

    SERVER:

SRV.SYS<-----------MRXSMB.SYS<----------NETBT.SYS<--------TCP/IP

   

    应用程序调用NET/MPR/RPC等API将信息写入WKSSVC管道,这个管道是一个特殊的管道,对应的其实是一个LPC端口。

    MRXSMB.SYS是一个SMB的小端口驱动,负责完成客户端的SMB的封装和实现,如发起协商,认证的加密/解密过程等。

对于服务器端则主要

完成会话状态的一些管理,然后将SMB包发送给下级驱动处理。

    NETBT.SYS是NETBIOSOVERTCP/IP的驱动,一般都是作为MRXSMB的下级驱动,不过MRXSMB也可以有其他的下级驱动,最后通过一个网络驱

动实现通讯,这里假设是使用TCP/IP。

    SRV.SYS是服务器端的SMB协议驱动程序,实现完成真正的SMB的协议功能,然后将结果按原路返回给客户端。

    2。

SMB的认证协议。

    通过SMB进行认证客户端一般都要先使用SMB的协商命令(0X72)发送客户端支持的认证协议给服务器,服务器则选择其中的一个,然后返回

给客户端,客户端然后再使用SMB的会话设置和X命令(0X73)进行认证和登陆。

    MS的SMB已经使用的SMB认证协议有:

      协议                        备注

    PCNETWORKPROGRAM1.0                W2K支持                 

    PCLAN1.0                        W2K支持

    MICROSOFTNETWORKS1.03                W2K支持

    MICROSOFTNETWORKS3.0                W2K支持

    LANMAN1.0                        W2K支持

    DOSLM1.2X002                    W2K支持

    WindowsforWorkgroups3.1a            W2K不支持,老的WindowsforWorkgroups3.1使用此协议方式。

    LM1.2X002                        W2K支持   

    DOSLANMAN2.1                    W2K支持

    LANMAN2.1                        W2K支持

    NTLM0.12                        W2K支持

    Cairo0.xa                        W2K支持,这是NT后MS自己开发的一个认证协议

    

    这里我们首先讲讲大家用的最多和最熟悉的NTLM认证方式:

    3。

NTLM认证过程

    NTLM在发展的过程中也存在这兼容的一些问题,现在的NTLM是支持挑战方式的,但原始的W9X的NTLM则不支持挑战会话方式的,所以

从协议过程来看存在2种方式,一种是支持挑战加密的方式(NT,2K等),一种是不支持加密挑战的方式(W9X)。

    i.    认证过程1

?

    (客户端发起:

会话协商协议)包含支持NTLM认证的选项且支持挑战选项。

?

    (服务器:

会话协商协议)选择了NTLM认证协议,且包含服务器的GUID

?

    (客户端发起:

会话设置和X协议)申请挑战会话的安全BLOB

?

    (服务器:

会话设置和X协议)返回带有挑战KEY的安全BLOB

?

    (客户端发起:

会话设置和X协议)带会话KEY加密的口令散列的安全BLOB

?

        认证成功:

会话设置和X协议返回成功信息

        认证失败:

会话设置和X协议返回失败信息,发起注销协议包

    ii.    认证过程2

?

    (客户端发起:

会话协商协议)包含支持NTLM认证的选项且不支持挑战选项。

?

    (服务器:

会话协商协议)选择了NTLM认证协议,且包含会话KEY

?

    (客户端发起:

会话设置和X协议)使用会话KEY加密的密码散列

//注意可以指定是非加密方式的密码明文来进行登陆

?

    认证成功:

会话设置和X协议返回成功信息

    认证失败:

会话设置和X协议返回失败信息,发起注销协议包

    我们这里主要讲认证过程1,其实过程2一般为很多工具使用,因为可以通过特定的FLAG字段指定不使用挑战和加密方式进行登陆,

那么就可以方便的使用明文口令,如SMBCRACK主要使用这种方法进行口令暴力破解,但是需要注意的一点是,这种属于老的方式,是可以在

服务器端禁止的。

    客户端APP通过写入WKSSVC管道(LPC端口发起)相关命令和数据

        客户端MRXSMB.SYS的SmbCeNegotiate函数负责进行协商包的封装并交下级驱动封装

        服务器SRV.SYS的SrvSmbNegotiate函数负责选取一个认证协议并返回给客户端,并返回服务器的GUID

    客户端的MRXSMB.SYS的SmbCeReferenceSession负责进行认证:

模拟过程函数如下:

BYTEbuf1[0x404c];

TOKEN_STATISTICSts;

CredHandlephs;

CredHandlephc;

CtxtHandlecthc;

CtxtHandlecths;

SECURITY_STATUS  ss;

wchar_tTargetName[]=L"HOST/192.168.0.34";

intlen;

typedefstruct_Credentials

{

    char*pusername;

    DWORDusernamelen;

    char*pdomainname;

    DWORDdomainnamelen;

    char*ppassword;

    DWORDpasswordlen;

    DWORDcredtype;

    BYTEinfo[0x200];

}Credentials,*PCredentials;

voidclient1()

{

    Credentialscrt;

    LUIDLogonID;

    HANDLEtk;

    TimeStampLifetime;

    DWORDContextAttributes;

    DWORDrlen;

    charcrtinfo[]={'a',0,'d',0,'m',0,'i',0,'n',0,'i',0,'s',0,'t',0,'r',0,'a',0,'t',0,'o',0,'r',0,0,0,'p',0,'s',0,'w',0,'d',0,0,0};

    

    SecBufferDesc    OutBuffDesc;

    SecBufferDesc    InBuffDesc;

    SecBuffer        InSecBuff;

    SecBuffer        OutSecBuff;

    LogonID.HighPart=0;

    LogonID.LowPart=0x7d80;

    //输入的口令在此需要CRT

    //自动的则不需要

    OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&tk);

    GetTokenInformation(tk,TokenStatistics,&ts,sizeof(ts),&rlen);

    crt.pusername=crt.info;

    crt.usernamelen=0xd;

    crt.pdomainname=0;

    crt.domainnamelen=0;

    crt.ppassword=crt.info+0x1c;

    crt.passwordlen=4;

    crt.credtype=6;

    memcpy(crt.info,crtinfo,0x22); 

    ss=AcquireCredentialsHandleW

        (NULL,L"Negotiate",SECPKG_CRED_OUTBOUND,&ts.AuthenticationId,&crt,NULL,NULL,&phc,&Lifetime);

    InBuffDesc.ulVersion=0;

    InBuffDesc.cBuffers=1;

    InBuffDesc.pBuffers=&InSecBuff;

    InSecBuff.BufferType=SECBUFFER_TOKEN;

    InSecBuff.cbBuffer=0;

    InSecBuff.pvBuffer=buf1;

    OutBuffDesc.ulVersion=0;

    OutBuffDesc.cBuffers=1;

    OutBuffDesc.pBuffers=&OutSecBuff;

    OutSecBuff.BufferType=SECBUFFER_TOKEN;

    OutSecBuff.cbBuffer=0x404c;

    OutSecBuff.pvBuffer=buf1;

    ss=InitializeSecurityContextW(

            &phc,

            NULL,

            TargetName,

            ASC_REQ_MUTUAL_AUTH|ASC_REQ_DELEGATE|ASC_REQ_STREAM|ASC_REQ_ALLOW_NON_USER_LOGONS,//0x210003

            0,

            SECURITY_NATIVE_DREP,

        &InBuffDesc,

            0,

            &cthc,

            &OutBuffDesc,

            &ContextAttributes,

            &Lifetime

            );

    len=OutSecBuff.cbBuffer;

    

}

    解释:

    TargetName后面的192.168.0.34是SMB服务器的名字,如果是用的IP就使用IP,用的NETBIOS名字就使用NETBIOS名字

    InitializeSecurityContextW之后的buf1里面就是BLOB数据。

然后将此数据放于SMB包中的安全BLOB处进行传送。

    AcquireCredentialsHandle中的crt是当使用输入用户与口令的时候使用的,格式是明文和UNICODE的(参考Credentials结构)。

系统使用SAM数据进行登陆的时候,此处可以是NULL;NULL的时候和非NULL的时候生成的安全BLOB的头内容是不同的。

    ts.AuthenticationId是认证的LUID,其实MRXSMB使用的是WIN32K.sys的不对外的GetProcessLuid函数来获取的,这里使用

GetTokenInformation来进行模拟。

当系统使用系统的SAM登陆时,必须获得此值,才知道使用的认证ID,当然如果你知道且能获得其他用户进

程的认证LUID,也可以使用,不仅仅非要是自己进程的认证LUID;

    服务器的SRV.SYS获得此安全BLOB之后,调用SrvSmbSessionSetupAndX函数来进行处理,实际的处理函数是BlockingSessionSetupAndX函数。

调用SrvValidateSecurityBuffer,主要工作是根据客户端的初始BLOB生成带会话KEY的安全BLOB返回给客户端,模拟程序如下:

voidserver2()

{

    TimeStamp        Lifetime;

    SecBufferDesc    OutBuffDesc;

    SecBuffer        OutSecBuff;

    SecBufferDesc    InBuffDesc;

    SecBuffer        InSecBuff;

    DWORDContextAttributes;

    BYTEpOut[0X40DD];

    BYTEpIn[0X50];

    

    ss=AcquireCredentialsHandleW

        (NULL,L"Negotiate",SECPKG_CRED_INBOUND,NULL,NULL,NULL,NULL,&phs,&Lifetime);

  OutBuffDesc.ulVersion=0;

  OutBuffDesc.cBuffers=1;

  OutBuffDesc.pBuffers=&OutSecBuff;

  OutSecBuff.cbBuffer=0x40dd;

  OutSecBuff.BufferType=SECBUFFER_TOKEN;

  OutSecBuff.pvBuffer=pOut;

  InBuffDesc.ulVersion=0;

  InBuffDesc.cBuffers=1;

  InBuffDesc.pBuffers=&InSecBuff;

  InSecBuff.cbBuffer=len;

  InSecBuff.BufferType=SECBUFFER_TOKEN;

  InSecBuff.pvBuffer=pIn;

  memset(pIn,0,0x40dd);

  memset(pOut,0,0x40dd);

  memcpy(pIn,buf1,0x10);

  ss=AcceptSecurityContext(

            &phs,

            NULL,

            &InBuffDesc,

            ASC_REQ_DELEGATE|ASC_REQ_EXTENDED_ERROR|ASC_REQ_FRAGMENT_TO_FIT,//ASC_REQ_ALLOW_NULL_SESSION

            0x10,//SECURITY_NATIVE_DREP,

            &cths,

            &OutBuffDesc,

            &ContextAttributes,

            &Lifetime

            );

    len=OutSecBuff.cbBuffer;

}

    解释:

    ASC_REQ_ALLOW_NULL_SESSION选项在用户模式下不可用,在SRV.SYS则可以使用

    实际上客户端生成的初始BLOB只有前0X10字节(BLOB头)是有意义的,AcceptSecurityContext执行后的pOut缓冲里就是需要返回的

带会话KEY的安全BLOB

    客户端的MRXSMB.SYS获得这个安全BLOB后就会使用此KEY进行加密。

模拟的程序如下:

voidclient3()

{

    TimeStampLifetime;

    DWORDContextAttributes;

    SecBufferDesc    OutBuffDesc;

    SecBufferDesc    InBuffDesc;

    SecBuffer        InSecBuff;

    SecBuffer        OutSecBuff;

    InBuffDesc.ulVersion=0;

    InBuffDesc.cBuffers=1;

    InBuffDesc.pBuffers=&InSecBuff;

    InSecBuff.BufferType=SECBUFFER_TOKEN;

    InSecBuff.cbBuffer=len;

    InSecBuff.pvBuffer=buf1;

    OutBuffDesc.ulVersion=0;

    OutBuffDesc.cBuffers=1;

    OutBuffDesc.pBuffers=&OutSecBuff;

    OutSecBuff.BufferType=SECBUFFER_TOKEN;

    OutSecBuff.cbBuffer=0x404c;

    OutSecBuff.pvBuffer=buf1;

    ss=

            &phc,

            &cthc,

            TargetName,

            ASC_REQ_MUTUAL_AUTH|ASC_REQ_DELEGATE|ASC_REQ_STREAM|ASC_REQ_ALLOW_NON_USER_LOGONS,//0x210003

            0,

            SECURITY_NATIVE_DREP,

            &InBuffDesc,

            0,

            &cthc,

            &OutBuffDesc,

            &ContextAttributes,

            &Lifetime

            );

}

    

    在这个生成的过程中一些特性:

    我们使用同一返回的KEY,每次生成的认证内容都不一样,但是每次都是可以被认证的,那么我们可以得出一个结论,在这个认证的

    信息里还包含有时间戳或其他随机生成数据,加密和解密的算法还使用到了这个数据,这个数据也在认证内容中一起被发送到服务器。

服务器端进行认证的代码

voidserver4()

{

    TimeStamp        Lifetime;

    SecBufferDesc    OutBuffDesc;

    SecBuffer        OutSecBuff;

    SecBufferDesc    InBuffDesc;

    SecBuffer        InSecBuff;

    DWORDContextAttributes;

    

  OutBuffDesc.ulVersion=0;

  OutBuffDesc.cBuffers=1;

  OutBuffDesc.pBuffers=&OutSecBuff;

  OutSecBuff.cbBuffer=0x40dd;

  OutSecBuff.BufferType=SECBUFFER_TOKEN;

  OutSecBuff.pvBuffer=buf1;

  InBuffDesc.ulVersion=0;

  InBuffDesc.cBuffers=1;

  InBuffDesc.pBuffers=&InSecBuff;

  InSecBuff.cbBuffer=len;

  InSecBuff.BufferType=SECBUFFER_TOKEN;

  InSecBuff.pvBuffer=buf1;

 

  ss=AcceptSecurityContext(

            &phs,

            &cths,

            &InBuffDesc,

            ASC_REQ_DELEGATE|ASC_REQ_EXTENDED_ERROR|ASC_REQ_FRAGMENT_TO_FIT,//ASC_REQ_ALLOW_NULL_SESSION

            0x10,//SECURITY_NATIVE_DREP,

            &cths,

            &OutBuffDesc,

            &ContextAttributes,

            &Lifetime

            );

    if(ss==SEC_E_OK)

        printf("ok");

    else

        printf("error");

    

}

    

4.挑战NTLM的编程实现

        那么我们就可以实现一个纯TCP/IP的SMB使用NTLM的挑战方式进行登陆了,再这之前大家需要了解SMB协议,这里由于涉及到

公司的商业利益,我不能给予大家最详细的协议说明,但从程序代码和其中的注解大家应该大致知道。

这个程序大家修改一下就可以

得到类似SMBCRACK功能的口令破解的多线程支持NTLM挑战方式的(这样可以使用在标准的W2K认可的方式,关闭了非挑战和不许可明

文口令方式登陆的W2K服务器)的工具,但是由于口令计算的消耗,速度就会慢一些:

SMB.h文件:

#include

typedefstruct_SMBNBT

{

    unsignedcharnbtsmb;

    unsignedcharflag;

    shortsmbpacketlen;

}SMBNBT,*PSMBNBT;

typedefstruct_SMBINFO

{

    unsignedcharmagic[4];

    BYTEsmbtoken;

    BYTEerrcodeclass;

    BYTEdosaherrcode;

    unsignedcharerrcode[2];

    BYTEf

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 农林牧渔 > 水产渔业

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1