創建時間:2003-05-16
文章屬性:原創
文章提交:
flashsky
(flashsky1_at_sina.com)
轉摘請注明作者和安全焦點
作者:FLASHSKY
SITE:
WWW.XFOCUS.NET
,
WWW.SHOPSKY.COM
src:
http://www.xfocus.net/articles/200305/533.html
郵件:flashsky@xfocus.org
????????????????????
????//注:本文不涉及到NTLM具體的認證算法,但是給出通過SSPI的API實現的過程。
????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);
}
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
