NTLM
?
NTLM HTTP認證
過程如下:
??? 1: C? --> S?? GET ...
??? 2: C <--? S?? 401 Unauthorized
?????????????? ??WW-Authenticate: NTLM
??? 3: C? --> S?? GET ...
???????????????? Authorization: NTLM <base64-encoded type-1-message>
??? 4: C <--? S?? 401 Unauthorized
???????????????? WWW-Authenticate: NTLM <base64-encoded type-2-message>
??? 5: C? --> S?? GET ...
???????????????? Authorization: NTLM <base64-encoded type-3-message>
??? 6: C <--? S?? 200 Ok
從交互過程可以發現,client會發送type-1消息和type-3消息給server,而server會發送type-2消息給client。
Type-1消息包括機器名、Domain等
Type-2消息包括server發出的NTLM challenge
Type-3消息包括用戶名、機器名、Domain、以及兩個根據server發出的challenge計算出的response,這里response是基于challenge和當前用戶的登錄密碼計算而得
?
SMB協議可以說是WIN系統的核心協議,這里大致給大家講解一下SMB認證登陸的過程:
????????? 1。協議解析棧
????????? CLIENT:APP----->NET/MRP/RPC
????? API------>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是NETBIOS OVER
????? TCP/IP的驅動,一般都是作為MRXSMB的下級驅動,不過MRXSMB也可以有其他的下級驅動,最后通過一個網絡驅
????? 動實現通訊,這里假設是使用TCP/IP。
?????????? SRV.SYS是服務器端的SMB協議驅動程序,實現完成真正的SMB的協議功能,然后將結果按原路返回給客戶端。
????????? 2。SMB的認證協議。
????????? 通過SMB進行認證客戶端一般都要先使用SMB的協商命令(0X72)發送客戶端支持的認證協議給服務器,服務器則選擇其中的一個,然后返回
????? 給客戶端,客戶端然后再使用SMB的會話設置和X命令(0X73)進行認證和登陸。
????????? MS的SMB已經使用的SMB認證協議有:
??????????? 協議??????????????????????? 備注
????????? PC NETWORK PROGRAM 1.0??????????????? W2K支持????????????????
????????? PCLAN1.0??????????????????????? W2K支持
????????? MICROSOFT NETWORKS 1.03??????????????? W2K支持
????????? MICROSOFT NETWORKS 3.0??????????????? W2K支持
????????? LANMAN1.0??????????????????????? W2K支持
????????? DOS LM1.2X002??????????????????? W2K支持
????????? Windows for Workgroups 3.1a???????????? W2K不支持,老的Windows for
????? Workgroups 3.1使用此協議方式。
????????? LM1.2X002??????????????????????? W2K支持??
????????? DOS LANMAN2.1??????????????????? W2K支持
????????? LANMAN2.1??????????????????????? W2K支持
????????? NT LM 0.12??????????????????????? W2K支持
????????? Cairo 0.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負責進行認證:
????? 模擬過程函數如下:
????? BYTE buf1[0x404c];
????? TOKEN_STATISTICS ts;
????? CredHandle phs;
????? CredHandle phc;
????? CtxtHandle cthc;
????? CtxtHandle cths;
????? SECURITY_STATUS?? ss;
????? wchar_t TargetName[]=L"HOST/192.168.0.34";
????? int len;
????? typedef struct _Credentials
????? {
????????? char * pusername;
????????? DWORD usernamelen;
????????? char * pdomainname;
????????? DWORD domainnamelen;
????????? char * ppassword;
????????? DWORD passwordlen;
????????? DWORD credtype;
????????? BYTE info[0x200];
????? }Credentials,* PCredentials;
????? void client1()
????? {
????????? Credentials crt;
????????? LUID LogonID;
????????? HANDLE tk;
????????? TimeStamp Lifetime;
????????? DWORD ContextAttributes;
????????? DWORD rlen;
????????? char
????? crtinfo[]={'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返回給客戶端,模擬程序如下:
????? void server2()
????? {
????????? TimeStamp???????? Lifetime;
????????? SecBufferDesc???? OutBuffDesc;
????????? SecBuffer???????? OutSecBuff;
????????? SecBufferDesc???? InBuffDesc;
????????? SecBuffer???????? InSecBuff;
????????? DWORD ContextAttributes;
????????? BYTE pOut[0X40DD];
????????? BYTE pIn[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進行加密。模擬的程序如下:
????? void client3()
????? {
????????? TimeStamp Lifetime;
????????? DWORD ContextAttributes;
????????? 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,每次生成的認證內容都不一樣,但是每次都是可以被認證的,那么我們可以得出一個結論,在這個認證的
????????? 信息里還包含有時間戳或其他隨機生成數據,加密和解密的算法還使用到了這個數據,這個數據也在認證內容中一起被發送到服務器。
????? 服務器端進行認證的代碼
????? void server4()
????? {
????????? TimeStamp???????? Lifetime;
????????? SecBufferDesc???? OutBuffDesc;
????????? SecBuffer???????? OutSecBuff;
????????? SecBufferDesc???? InBuffDesc;
????????? SecBuffer???????? InSecBuff;
????????? DWORD ContextAttributes;
?????????
???????? 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 <windows.h>
????? typedef struct _SMBNBT
????? {
????????? unsigned char nbtsmb;
????????? unsigned char flag;
????????? short smbpacketlen;
????? }SMBNBT,* PSMBNBT;
????? typedef struct _SMBINFO
????? {
????????? unsigned char magic[4];
????????? BYTE smbtoken;
????????? BYTE errcodeclass;
????????? BYTE dosaherrcode;
????????? unsigned char errcode[2];
????????? BYTE flagsummary;
????????? short flagsummary2;
????????? short unuse[6];
????????? short treeid;
????????? short callprocessid;
????????? short userid;
????????? short multiplexid;
????????? unsigned char info[2048];
????? }SMBINFO,* PSMBINFO;
????? typedef struct _SMBP
????? {
????????? SMBNBT smbnbt;
????????? SMBINFO smbinfo;
????? }SMBP,* PSMBP;
????? typedef struct _Credentials
????? {
????????? char * pusername;
????????? DWORD usernamelen;
????????? char * pdomainname;
????????? DWORD domainnamelen;
????????? char * ppassword;
????????? DWORD passwordlen;
????????? DWORD credtype;
????????? BYTE info[0x200];
????? }Credentials,* PCredentials;
?????????
????? 客戶端程序:
????? #include <stdio.h>
????? #include <winsock2.h>
????? #include <windows.h>
????? #include <wincrypt.h>
????? #include <process.h>
????? #include <string.h>
????? #include <winbase.h>
????? # include <wincrypt.h>
????? #define SECURITY_WIN32
????? # include <Security.h>
????? #include "SMB.H"
????? void SmbNegotiate(SMBP * psmbp);
????? void SmbSessionSetupAndX1(SMBP * psmbp,wchar_t * username,wchar_t *
????? domainname,wchar_t * password);
????? void SmbSessionSetupAndX2(SMBP * psmbp,unsigned char * ntlmrcv,short
????? ntlmlen);
????? TOKEN_STATISTICS ts;
????? CredHandle phs;
????? CredHandle phc;
????? CtxtHandle cthc;
????? CtxtHandle cths;
????? SECURITY_STATUS?? ss;
????? wchar_t
????? TargetName[]=L"HOST/192.168.13.34";//后面的192.168.0.34是SMB服務器的名字,如果是用的IP就使用IP,用的NETBIOS名字就使用NETBIOS名字)
????? wchar_t navos[]=L"windows 2000 2195";
????? wchar_t lanman[]=L"windows 2000 5.0";
????? void main(int argc,char ** argv)
????? {
????????? WSADATA WSAData;
????????? int i;
????????? SOCKET sock;
????????? SOCKADDR_IN addr_in;
????????? int len;
????????? char serverip[]="192.168.13.34";
????????? short port=445;
????????? WORD olen,nlen;
????????? unsigned char buf1[0x1000];
????????? SMBP smbp;
????????? if (WSAStartup(MAKEWORD(2,0),&WSAData)!=0)
????????? {
????????????? printf("WSAStartup error.Error:%d\n",WSAGetLastError());
????????????? return;
????????? }
????????? addr_in.sin_family=AF_INET;
????????? addr_in.sin_port=htons(port);
????????? addr_in.sin_addr.S_un.S_addr=inet_addr(serverip);
?????????
????????? if ((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
????????? {
????????????? printf("Socket failed.Error:%d\n",WSAGetLastError());
????????????? return;
????????? }
????????? if(WSAConnect(sock,(struct sockaddr
????? *)&addr_in,sizeof(addr_in),NULL,NULL,NULL,NULL)==SOCKET_ERROR)
????????? {
????????????? printf("Connect failed.Error:%d",WSAGetLastError());
????????????? return;
????????? }
????????? SmbNegotiate(&smbp);
????????? if (send(sock,(unsigned char
????? *)&smbp,ntohs(smbp.smbnbt.smbpacketlen)+4,0)==SOCKET_ERROR)
????????? {
????????????????? printf("Send failed.Error:%d\n",WSAGetLastError());
????????????????? return;
????????? }
????????? len=recv(sock,buf1,1024,NULL);
????????? SmbSessionSetupAndX1(&smbp,L"administrator",L"",L"1972");
????????? if (send(sock,(unsigned char
????? *)&smbp,ntohs(smbp.smbnbt.smbpacketlen)+4,0)==SOCKET_ERROR)
????????? {
????????????????? printf("Send failed.Error:%d\n",WSAGetLastError());
????????????????? return;
????????? }
????????? len=recv(sock,buf1,1024,NULL);
????????? if((buf1[0]==0xff)&&(buf1[1]=='S')&&(buf1[2]=='M')&&(buf1[3]=='B'))
????????????? olen=0x20;
????????? else
????? if((buf1[4]==0xff)&&(buf1[5]=='S')&&(buf1[6]=='M')&&(buf1[7]=='B'))
????????????? olen=0x24;
????????? else
????????????? return;
????????? smbp.smbinfo.userid =? *(WORD *)(buf1+olen-0x4);
????????? nlen=*(WORD *)(buf1+olen+1+2*3);//BLOB的長度
????????? olen=olen+1+2*buf1[olen]+2;
????????? SmbSessionSetupAndX2(&smbp,buf1+olen,nlen);
????????? if (send(sock,(unsigned char
????? *)&smbp,ntohs(smbp.smbnbt.smbpacketlen)+4,0)==SOCKET_ERROR)
????????? {
????????????????? printf("Send failed.Error:%d\n",WSAGetLastError());
????????????????? return;
????????? }
????????? len=recv(sock,buf1,1024,NULL);
????????? if((buf1[0]==0xff)&&(buf1[1]=='S')&&(buf1[2]=='M')&&(buf1[3]=='B'))
????????????? olen=0x20;
????????? else
????? if((buf1[4]==0xff)&&(buf1[5]=='S')&&(buf1[6]=='M')&&(buf1[7]=='B'))
????????????? olen=0x24;
????????? else
????????????? return;
????????? if(buf1[olen]==0)
????????????? printf("error username and password\n");
????????? else
????????????? printf("login ok\n");
????????? WSACleanup();
????????? return;
????? }
????? void SmbSessionSetupAndX1(SMBP * psmbp,wchar_t * username,wchar_t *
????? domainname,wchar_t * password)
????? {
????????? LUID LogonID;
????????? unsigned char buf1[0x404c];
????????? HANDLE tk;
????????? TimeStamp Lifetime;
????????? DWORD ContextAttributes;
????????? DWORD rlen;
????????? DWORD r1,r2,r3;
????????? int i;
????????? Credentials crt;
????????? SecBufferDesc???? OutBuffDesc;
????????? SecBufferDesc???? InBuffDesc;
????????? SecBuffer???????? InSecBuff;
????????? SecBuffer???????? OutSecBuff;
????????? LogonID.HighPart =0;
????????? LogonID.LowPart = 0x7d80;
????????? psmbp->smbinfo.smbtoken =0x73;
????????? memset(psmbp->smbinfo.info,0,0x200);
????????? psmbp->smbinfo.flagsummary2 = 0xc807;
????????? *(DWORD *)(psmbp->smbinfo.info+21) = 0x800000D4;
????????? //指定使用加密的FLAG
????????? psmbp->smbinfo.info[0]=0xc;//WORD 參數個數
????????? *(WORD *)(psmbp->smbinfo.info+1)=0Xff;//無下一個命令
????????? *(WORD *)(psmbp->smbinfo.info+3)=0Xb0;//下一命令偏移
????????? *(WORD *)(psmbp->smbinfo.info+5)=0X4104;//最大緩沖
????????? *(WORD *)(psmbp->smbinfo.info+7)=0X32;//最大的MPX
????????? *(WORD *)(psmbp->smbinfo.info+9)=0X0;//虛擬通道
????????? *(DWORD *)(psmbp->smbinfo.info+11)=0X0;//虛擬通道
????????? *(DWORD *)(psmbp->smbinfo.info+17)=0X0;//保留
????????? //輸入的口令在此需要CRT
????????? //自動的則不需要
????????? OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tk);
????????? GetTokenInformation(tk,TokenStatistics,&ts,sizeof(ts),&rlen);
????????? r1=0;
????????? for(i=0;i<0x30;i++)
????????? {
????????????? if(username[i]==0)
????????????????? break;
????????????? r1=r1+2;
????????? }
????????? r2=0;
????????? for(i=0;i<0x30;i++)
????????? {
????????????? if(domainname[i]==0)
????????????????? break;
????????????? r2=r2+2;
????????? }
????????? r3=0;
????????? for(i=0;i<0x30;i++)
????????? {
????????????? if(password[i]==0)
????????????????? break;
????????????? r3=r3+2;
????????? }
????????? crt.pusername = crt.info;
????????? crt.usernamelen = r1/2;
????????? if(r2>0)
????????? {
????????????? crt.pdomainname =crt.info+r1+2;
????????????? crt.domainnamelen = r2/2;
????????????? crt.ppassword = crt.pdomainname+r2+2;
????????????? crt.passwordlen =r3/2;
????????? }
????????? else
????????? {
????????????? crt.pdomainname =0;
????????????? crt.domainnamelen = 0;
????????????? crt.ppassword = crt.info+r1+2;
????????????? crt.passwordlen =r3/2;
????????? }
????????? crt.credtype = 6;
????????? memcpy(crt.pusername,username,r1);
????????? if(r2>0)
????????????? memcpy(crt.pdomainname,domainname,r2);
????????? memcpy(crt.ppassword,password,r3);
????????? ss=AcquireCredentialsHandleW
?????????????
????? (NULL,L"Negotiate",SECPKG_CRED_OUTBOUND,&ts.AuthenticationId,&crt,NULL,NULL,&phc,&Lifetime);
????????? //LOGIN會影響生成
????????? 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
????????????????? );
????????? *(WORD *)(psmbp->smbinfo.info+15)=OutSecBuff.cbBuffer;? //BLOB的長度
????????? memcpy(psmbp->smbinfo.info+27,buf1,OutSecBuff.cbBuffer);//放入BLOB
????????? memcpy(psmbp->smbinfo.info+28+OutSecBuff.cbBuffer,navos,36);//
????????? memcpy(psmbp->smbinfo.info+66+OutSecBuff.cbBuffer,lanman,32);//
????????? *(WORD *)(psmbp->smbinfo.info+25)=73+OutSecBuff.cbBuffer;
????????? psmbp->smbnbt.smbpacketlen = htons(132+ OutSecBuff.cbBuffer);
????? }
????? void SmbSessionSetupAndX2(SMBP * psmbp,unsigned char * ntlmrcv,short
????? ntlmlen)
????? {
????????? TimeStamp Lifetime;
????????? DWORD ContextAttributes;
????????? SecBufferDesc???? OutBuffDesc;
????????? SecBufferDesc???? InBuffDesc;
????????? SecBuffer???????? InSecBuff;
????????? SecBuffer???????? OutSecBuff;
????????? unsigned char buf1[0x404c];
????????? psmbp->smbinfo.smbtoken =0x73;
????????? memset(psmbp->smbinfo.info,0,0x200);
????????? psmbp->smbinfo.flagsummary2 = 0xc807;
????????? *(DWORD *)(psmbp->smbinfo.info+21) = 0x800000D4;
????????? //指定使用加密的FLAG
????????? psmbp->smbinfo.info[0]=0xc;//WORD 參數個數
????????? *(WORD *)(psmbp->smbinfo.info+1)=0Xff;//無下一個命令
????????? *(WORD *)(psmbp->smbinfo.info+3)=0X12e;//下一命令偏移
????????? *(WORD *)(psmbp->smbinfo.info+5)=0X4104;//最大緩沖
????????? *(WORD *)(psmbp->smbinfo.info+7)=0X32;//最大的MPX
????????? *(WORD *)(psmbp->smbinfo.info+9)=0X0;//虛擬通道
????????? *(DWORD *)(psmbp->smbinfo.info+11)=0X0;//虛擬通道
????????? *(DWORD *)(psmbp->smbinfo.info+17)=0X0;//保留
????????? //輸入的口令在此需要CRT
????????? //自動的則不需要
????????? InBuffDesc.ulVersion = 0;
????????? InBuffDesc.cBuffers = 1;
????????? InBuffDesc.pBuffers = &InSecBuff;
????????? InSecBuff.BufferType =SECBUFFER_TOKEN;
????????? InSecBuff.cbBuffer =ntlmlen;
????????? InSecBuff.pvBuffer = ntlmrcv;
????????? OutBuffDesc.ulVersion = 0;
????????? OutBuffDesc.cBuffers = 1;
????????? OutBuffDesc.pBuffers = &OutSecBuff;
????????? OutSecBuff.BufferType = SECBUFFER_TOKEN;
????????? OutSecBuff.cbBuffer =0x404c;
????????? OutSecBuff.pvBuffer = buf1;
????????? ss=InitializeSecurityContextW(
????????????????? &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
????????????????? );
????????? *(WORD *)(psmbp->smbinfo.info+15)=OutSecBuff.cbBuffer;? //BLOB的長度
????????? memcpy(psmbp->smbinfo.info+27,buf1,OutSecBuff.cbBuffer);//放入BLOB
????????? memcpy(psmbp->smbinfo.info+28+OutSecBuff.cbBuffer,navos,36);//
????????? memcpy(psmbp->smbinfo.info+66+OutSecBuff.cbBuffer,lanman,32);//
????????? *(WORD *)(psmbp->smbinfo.info+25)=73+OutSecBuff.cbBuffer;
????????? psmbp->smbnbt.smbpacketlen = htons(132+ OutSecBuff.cbBuffer);
????? }
????? void SmbNegotiate(SMBP * psmbp)
????? {
????????? unsigned char magic[4]={0xff,'S','M','B'};
????????? short len;
????????? char langitem1[]="PC NETWORK PROGRAM 1.0";
????????? char langitem2[]="LANMAN1.0";
????????? char langitem3[]="Windows for Workgroups 3.1a";
????????? char langitem4[]="LM1.2X002";
????????? char langitem5[]="LANMAN2.1";
????????? char langitem6[]="NT LM 0.12";
????????? char langitem7[]="PCLAN1.0";
????????? char langitem8[]="MICROSOFT NETWORKS 1.03";
????????? char langitem9[]="MICROSOFT NETWORKS 3.0";
????????? char langitem10[]="DOS LM1.2X002";
????????? char langitem11[]="DOS LANMAN2.1";
????????? char langitem12[]="Cairo 0.xa";
????????? memset(psmbp,0,sizeof(SMBP));
????????? psmbp->smbnbt.nbtsmb = 0;
????????? psmbp->smbnbt.flag = 0;
????????? memcpy(psmbp->smbinfo.magic, magic,4);
????????? psmbp->smbinfo.smbtoken = 0x72;
????????? psmbp->smbinfo.errcodeclass = 0x0;
????????? psmbp->smbinfo.dosaherrcode = 0x0;
????????? psmbp->smbinfo.errcode[0] = 0x0;
????????? psmbp->smbinfo.errcode[1] = 0x0;
????????? psmbp->smbinfo.flagsummary = 0x18;
????????? psmbp->smbinfo.flagsummary2 = 0xc853;
????????? //指定了帶挑戰方式支持的FLAG
????????? psmbp->smbinfo.callprocessid = 0xfeff;
????????? psmbp->smbinfo.multiplexid = 0;
????????? psmbp->smbinfo.info[0]=0x0;
????????? len=3+2*(psmbp->smbinfo.info[0]);
????????? /*
????????? psmbp->smbinfo.info[len]=0x2;
????????? memcpy(psmbp->smbinfo.info+len+1,langitem3,sizeof(langitem3));
????????? len = len+1+sizeof(langitem3);
?????????
????????? psmbp->smbinfo.info[len]=0x2;
????????? memcpy(psmbp->smbinfo.info+len+1,langitem1,sizeof(langitem1));
????????? len = len+1+sizeof(langitem1);
????????? psmbp->smbinfo.info[len]=0x2;
????????? memcpy(psmbp->smbinfo.info+len+1,langitem2,sizeof(langitem2));
????????? len = len+1+sizeof(langitem2);
?????????
????????? psmbp->smbinfo.info[len]=0x2;
????????? memcpy(psmbp->smbinfo.info+len+1,langitem4,sizeof(langitem4));
????????? len = len+1+sizeof(langitem4);
?????????
????????? psmbp->smbinfo.info[len]=0x2;
????????? memcpy(psmbp->smbinfo.info+len+1,langitem5,sizeof(langitem5));
????????? len = len+1+sizeof(langitem5);
?????????????
????????? psmbp->smbinfo.info[len]=0x2;
????????? memcpy(psmbp->smbinfo.info+len+1,langitem6,sizeof(langitem6));
????????? len = len+1+sizeof(langitem6);
????????? */
????????? psmbp->smbinfo.info[len]=0x2;
????????? memcpy(psmbp->smbinfo.info+len+1,langitem6,sizeof(langitem6));
????????? len = len+1+sizeof(langitem6);
????????? *(WORD *)(psmbp->smbinfo.info+1) =len-3-2*(psmbp->smbinfo.info[0]);
????????? psmbp->smbnbt.smbpacketlen = htons(len+0x20);
????? }
轉載于:https://www.cnblogs.com/ahuo/archive/2008/09/03/1282745.html
總結
- 上一篇: [转载] 湖北:星空团队——海燕计划
- 下一篇: 莫烦---Tensorflow学习