mirror of
https://github.com/sairson/Yasso.git
synced 2026-02-09 05:23:41 +08:00
Yasso更新大改动,更新扫描方式,去除不常用功能,增加指纹和协议识别,修补bug等
This commit is contained in:
593
example/tcp_smb_test.go
Normal file
593
example/tcp_smb_test.go
Normal file
@@ -0,0 +1,593 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
crand "crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
res, _, err := smb2("192.168.248.224", 445, 1*time.Second)
|
||||
if err != nil || res["ntlmssp.Version"] == "" {
|
||||
return
|
||||
} else {
|
||||
banner := fmt.Sprintf("Version:%s||DNSComputer:%s||TargetName:%s||NetbiosComputer:%s",
|
||||
res["ntlmssp.Version"],
|
||||
res["ntlmssp.DNSComputer"],
|
||||
res["ntlmssp.TargetName"],
|
||||
res["ntlmssp.NetbiosComputer"],
|
||||
)
|
||||
fmt.Println(banner)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// smb2 from https://github.com/RumbleDiscovery/rumble-tools/blob/main/cmd/rumble-smb2-sessions/main.go
|
||||
func smb2(host string, port int, timeout time.Duration) (map[string]string, []byte, error) {
|
||||
// SMB1NegotiateProtocolRequest is a SMB1 request that advertises support for SMB2
|
||||
var smb1NegotiateProtocolRequest = []byte{
|
||||
0x00, 0x00, 0x00, 0xd4, 0xff, 0x53, 0x4d, 0x42,
|
||||
0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x43, 0xc8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x02,
|
||||
0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
|
||||
0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
|
||||
0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
|
||||
0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x4f, 0x46,
|
||||
0x54, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52,
|
||||
0x4b, 0x53, 0x20, 0x31, 0x2e, 0x30, 0x33, 0x00,
|
||||
0x02, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x4f,
|
||||
0x46, 0x54, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
|
||||
0x52, 0x4b, 0x53, 0x20, 0x33, 0x2e, 0x30, 0x00,
|
||||
0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31,
|
||||
0x2e, 0x30, 0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e,
|
||||
0x32, 0x58, 0x30, 0x30, 0x32, 0x00, 0x02, 0x44,
|
||||
0x4f, 0x53, 0x20, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
|
||||
0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4c, 0x41,
|
||||
0x4e, 0x4d, 0x41, 0x4e, 0x32, 0x2e, 0x31, 0x00,
|
||||
0x02, 0x53, 0x61, 0x6d, 0x62, 0x61, 0x00, 0x02,
|
||||
0x4e, 0x54, 0x20, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
|
||||
0x4e, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02, 0x4e,
|
||||
0x54, 0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31,
|
||||
0x32, 0x00, 0x02, 0x53, 0x4d, 0x42, 0x20, 0x32,
|
||||
0x2e, 0x30, 0x30, 0x32, 0x00, 0x02, 0x53, 0x4d,
|
||||
0x42, 0x20, 0x32, 0x2e, 0x3f, 0x3f, 0x3f, 0x00,
|
||||
}
|
||||
fmt.Println(string(smb1NegotiateProtocolRequest))
|
||||
info := make(map[string]string)
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", host, port), timeout)
|
||||
if err != nil {
|
||||
return info, []byte{}, err
|
||||
}
|
||||
err = SMBSendData(conn, smb1NegotiateProtocolRequest, timeout)
|
||||
if err != nil {
|
||||
return info, []byte{}, err
|
||||
}
|
||||
|
||||
data, err := SMBReadFrame(conn, timeout)
|
||||
if err != nil {
|
||||
return info, []byte{}, err
|
||||
}
|
||||
|
||||
err = SMBSendData(conn, SMB2NegotiateProtocolRequest(host), timeout)
|
||||
if err != nil {
|
||||
return info, []byte{}, err
|
||||
}
|
||||
|
||||
data, _ = SMBReadFrame(conn, timeout)
|
||||
SMB2ExtractFieldsFromNegotiateReply(data, info)
|
||||
|
||||
// SMB2SessionSetupNTLMSSP is a SMB2 SessionSetup NTLMSSP request
|
||||
var smb2SessionSetupNTLMSSP = []byte{
|
||||
0x00, 0x00, 0x00, 0xa2, 0xfe, 0x53, 0x4d, 0x42,
|
||||
0x40, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x01,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x58, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x60, 0x48, 0x06, 0x06,
|
||||
0x2b, 0x06, 0x01, 0x05, 0x05, 0x02, 0xa0, 0x3e,
|
||||
0x30, 0x3c, 0xa0, 0x0e, 0x30, 0x0c, 0x06, 0x0a,
|
||||
0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02,
|
||||
0x02, 0x0a, 0xa2, 0x2a, 0x04, 0x28, 0x4e, 0x54,
|
||||
0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x97, 0x82, 0x08, 0xe2, 0x00, 0x00,
|
||||
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0a, 0x00,
|
||||
0xba, 0x47, 0x00, 0x00, 0x00, 0x0f,
|
||||
}
|
||||
|
||||
setup := make([]byte, len(smb2SessionSetupNTLMSSP))
|
||||
copy(setup, smb2SessionSetupNTLMSSP)
|
||||
|
||||
// Set the ProcessID
|
||||
binary.LittleEndian.PutUint16(setup[4+32:], 0xfeff)
|
||||
|
||||
err = SMBSendData(conn, setup, timeout)
|
||||
if err != nil {
|
||||
return info, []byte{}, err
|
||||
}
|
||||
|
||||
data, err = SMBReadFrame(conn, timeout)
|
||||
SMB2ExtractSIDFromSessionSetupReply(data, info)
|
||||
SMBExtractFieldsFromSecurityBlob(data, info)
|
||||
|
||||
return info, data, err
|
||||
}
|
||||
|
||||
// RandomBytes generates a random byte sequence of the requested length
|
||||
func RandomBytes(numBytes int) []byte {
|
||||
randBytes := make([]byte, numBytes)
|
||||
err := binary.Read(crand.Reader, binary.BigEndian, &randBytes)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return randBytes
|
||||
}
|
||||
|
||||
// SMBReadFrame reads the netBios header then the full response
|
||||
func SMBReadFrame(conn net.Conn, t time.Duration) ([]byte, error) {
|
||||
timeout := time.Now().Add(time.Duration(t) * time.Second)
|
||||
res := []byte{}
|
||||
nbh := make([]byte, 4)
|
||||
|
||||
err := conn.SetReadDeadline(timeout)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Read the NetBIOS header
|
||||
n, err := conn.Read(nbh[:])
|
||||
if err != nil {
|
||||
// Return if EOF is reached
|
||||
if err == io.EOF {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Return if timeout is reached
|
||||
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// If we have data and received an error, it was probably a reset
|
||||
if len(res) > 0 {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
if n != 4 {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
res = append(res[:], nbh[:n]...)
|
||||
dlen := binary.BigEndian.Uint32(nbh[:]) & 0x00ffffff
|
||||
buf := make([]byte, dlen)
|
||||
n, err = conn.Read(buf[:])
|
||||
if err != nil {
|
||||
// Return if EOF is reached
|
||||
if err == io.EOF {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Return if timeout is reached
|
||||
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// If we have data and received an error, it was probably a reset
|
||||
if len(res) > 0 {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
res = append(res[:], buf[:n]...)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// SMB2ExtractFieldsFromNegotiateReply extracts useful fields from the SMB2 negotiate response
|
||||
func SMB2ExtractFieldsFromNegotiateReply(blob []byte, info map[string]string) {
|
||||
|
||||
smbOffset := bytes.Index(blob, []byte{0xfe, 'S', 'M', 'B'})
|
||||
if smbOffset < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
data := blob[smbOffset:]
|
||||
|
||||
// Basic sanity check
|
||||
if len(data) < (64 + 8 + 16 + 36) {
|
||||
return
|
||||
}
|
||||
|
||||
switch binary.LittleEndian.Uint16(data[64+2:]) {
|
||||
case 0:
|
||||
info["smb.Signing"] = "disabled"
|
||||
case 1:
|
||||
info["smb.Signing"] = "enabled"
|
||||
case 2, 3:
|
||||
info["smb.Signing"] = "required"
|
||||
}
|
||||
|
||||
info["smb.Dialect"] = fmt.Sprintf("0x%.4x", binary.LittleEndian.Uint16(data[64+4:]))
|
||||
//info["smb.GUID"] = uuid.FromBytesOrNil(data[64+8 : 64+8+16]).String()
|
||||
info["smb.Capabilities"] = fmt.Sprintf("0x%.8x", binary.LittleEndian.Uint32(data[64+8+16:]))
|
||||
|
||||
negCtxCount := int(binary.LittleEndian.Uint16(data[64+6:]))
|
||||
negCtxOffset := int(binary.LittleEndian.Uint32(data[64+8+16+36:]))
|
||||
if negCtxCount == 0 || negCtxOffset == 0 || negCtxOffset+(negCtxCount*8) > len(data) {
|
||||
return
|
||||
}
|
||||
|
||||
negCtxData := data[negCtxOffset:]
|
||||
idx := 0
|
||||
for {
|
||||
if idx+8 > len(negCtxData) {
|
||||
break
|
||||
}
|
||||
negType := int(binary.LittleEndian.Uint16(negCtxData[idx:]))
|
||||
negLen := int(binary.LittleEndian.Uint16(negCtxData[idx+2:]))
|
||||
idx += 8
|
||||
|
||||
if idx+negLen > len(negCtxData) {
|
||||
break
|
||||
}
|
||||
negData := negCtxData[idx : idx+negLen]
|
||||
|
||||
SMB2ParseNegotiateContext(negType, negData, info)
|
||||
|
||||
// Move the index to the next context
|
||||
idx += negLen
|
||||
// Negotiate Contexts are aligned on 64-bit boundaries
|
||||
for idx%8 != 0 {
|
||||
idx++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SMB2ParseNegotiateContext decodes fields from the SMB2 Negotiate Context values
|
||||
func SMB2ParseNegotiateContext(t int, data []byte, info map[string]string) {
|
||||
switch t {
|
||||
case 1:
|
||||
// SMB2_PREAUTH_INTEGRITY_CAPABILITIES
|
||||
if len(data) < 6 {
|
||||
return
|
||||
}
|
||||
hashCount := int(binary.LittleEndian.Uint16(data[:]))
|
||||
// MUST only be one in responses
|
||||
if hashCount != 1 {
|
||||
return
|
||||
}
|
||||
hashSaltLen := int(binary.LittleEndian.Uint16(data[2:]))
|
||||
hashType := int(binary.LittleEndian.Uint16(data[4:]))
|
||||
hashName := "sha512"
|
||||
if hashType != 1 {
|
||||
hashName = fmt.Sprintf("unknown-%d", hashType)
|
||||
}
|
||||
info["smb.HashAlg"] = hashName
|
||||
info["smb.HashSaltLen"] = fmt.Sprintf("%d", hashSaltLen)
|
||||
|
||||
case 2:
|
||||
// SMB2_ENCRYPTION_CAPABILITIES
|
||||
if len(data) < 4 {
|
||||
return
|
||||
}
|
||||
cipherCount := int(binary.LittleEndian.Uint16(data[:]))
|
||||
if len(data) < 2+(2*cipherCount) {
|
||||
return
|
||||
}
|
||||
// MUST only be one in responses
|
||||
if cipherCount != 1 {
|
||||
return
|
||||
}
|
||||
cipherList := []string{}
|
||||
for i := 0; i < cipherCount; i++ {
|
||||
cipherID := int(binary.LittleEndian.Uint16(data[2+(i*2):]))
|
||||
cipherName := ""
|
||||
switch cipherID {
|
||||
case 1:
|
||||
cipherName = "aes-128-ccm"
|
||||
case 2:
|
||||
cipherName = "aes-128-gcm"
|
||||
default:
|
||||
cipherName = fmt.Sprintf("unknown-%d", cipherID)
|
||||
}
|
||||
cipherList = append(cipherList, cipherName)
|
||||
}
|
||||
|
||||
info["smb.CipherAlg"] = strings.Join(cipherList, "\t")
|
||||
|
||||
case 3:
|
||||
// SMB2_COMPRESSION_CAPABILITIES
|
||||
if len(data) < 10 {
|
||||
return
|
||||
}
|
||||
compCount := int(binary.LittleEndian.Uint16(data[:]))
|
||||
if len(data) < 2+2+4+(2*compCount) {
|
||||
return
|
||||
}
|
||||
// MUST only be one in responses
|
||||
if compCount != 1 {
|
||||
return
|
||||
}
|
||||
compList := []string{}
|
||||
for i := 0; i < compCount; i++ {
|
||||
compID := int(binary.LittleEndian.Uint16(data[8+(i*2):]))
|
||||
compName := ""
|
||||
switch compID {
|
||||
case 0:
|
||||
compName = "none"
|
||||
case 1:
|
||||
compName = "lznt1"
|
||||
case 2:
|
||||
compName = "lz77"
|
||||
case 3:
|
||||
compName = "lz77+huff"
|
||||
case 4:
|
||||
compName = "patternv1"
|
||||
default:
|
||||
compName = fmt.Sprintf("unknown-%d", compID)
|
||||
}
|
||||
compList = append(compList, compName)
|
||||
}
|
||||
info["smb.CompressionFlags"] = fmt.Sprintf("0x%.4x", binary.LittleEndian.Uint32(data[4:]))
|
||||
info["smb.CompressionAlg"] = strings.Join(compList, "\t")
|
||||
}
|
||||
}
|
||||
|
||||
// SMBSendData writes a SMB request to a socket
|
||||
func SMBSendData(conn net.Conn, data []byte, timeout time.Duration) error {
|
||||
err := conn.SetWriteDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, err := conn.Write(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = n
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SMB2ExtractSIDFromSessionSetupReply tries to extract the SessionID and Signature from a SMB2 reply
|
||||
func SMB2ExtractSIDFromSessionSetupReply(blob []byte, info map[string]string) {
|
||||
smbOffset := bytes.Index(blob, []byte{0xfe, 'S', 'M', 'B'})
|
||||
if smbOffset < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
smbData := blob[smbOffset:]
|
||||
if len(smbData) < 48 {
|
||||
return
|
||||
}
|
||||
|
||||
status := binary.LittleEndian.Uint32(smbData[8:])
|
||||
info["smb.Status"] = fmt.Sprintf("0x%.8x", status)
|
||||
|
||||
sessID := binary.LittleEndian.Uint64(smbData[40:])
|
||||
info["smb.SessionID"] = fmt.Sprintf("0x%.16x", sessID)
|
||||
|
||||
if len(smbData) >= 64 {
|
||||
sigData := hex.EncodeToString(smbData[48:64])
|
||||
if sigData != "00000000000000000000000000000000" {
|
||||
info["smb.Signature"] = sigData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SMBExtractValueFromOffset peels a field out of a SMB buffer
|
||||
func SMBExtractValueFromOffset(blob []byte, idx int) ([]byte, int, error) {
|
||||
res := []byte{}
|
||||
|
||||
if len(blob) < (idx + 6) {
|
||||
return res, idx, fmt.Errorf("data truncated")
|
||||
}
|
||||
|
||||
len1 := binary.LittleEndian.Uint16(blob[idx:])
|
||||
idx += 2
|
||||
|
||||
// len2 := binary.LittleEndian.Uint16(blob[idx:])
|
||||
idx += 2
|
||||
|
||||
off := binary.LittleEndian.Uint32(blob[idx:])
|
||||
idx += 4
|
||||
|
||||
// Allow zero length values
|
||||
if len1 == 0 {
|
||||
return res, idx, nil
|
||||
}
|
||||
|
||||
if len(blob) < int(off+uint32(len1)) {
|
||||
return res, idx, fmt.Errorf("data value truncated")
|
||||
}
|
||||
|
||||
res = append(res, blob[off:off+uint32(len1)]...)
|
||||
return res, idx, nil
|
||||
}
|
||||
|
||||
// SMBExtractFieldsFromSecurityBlob extracts fields from the NTLMSSP response
|
||||
func SMBExtractFieldsFromSecurityBlob(blob []byte, info map[string]string) {
|
||||
var err error
|
||||
|
||||
ntlmsspOffset := bytes.Index(blob, []byte{'N', 'T', 'L', 'M', 'S', 'S', 'P', 0x00, 0x02, 0x00, 0x00, 0x00})
|
||||
if ntlmsspOffset < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
data := blob[ntlmsspOffset:]
|
||||
|
||||
// Basic sanity check
|
||||
if len(data) < (12 + 6 + 12 + 8 + 6 + 8) {
|
||||
return
|
||||
}
|
||||
|
||||
idx := 12
|
||||
|
||||
targetName, idx, err := SMBExtractValueFromOffset(data, idx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Negotiate Flags
|
||||
negotiateFlags := binary.LittleEndian.Uint32(data[idx:])
|
||||
info["ntlmssp.NegotiationFlags"] = fmt.Sprintf("0x%.8x", negotiateFlags)
|
||||
idx += 4
|
||||
|
||||
// NTLM Server Challenge
|
||||
idx += 8
|
||||
|
||||
// Reserved
|
||||
idx += 8
|
||||
|
||||
// Target Info
|
||||
targetInfo, idx, err := SMBExtractValueFromOffset(data, idx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Version
|
||||
versionMajor := uint8(data[idx])
|
||||
idx++
|
||||
|
||||
versionMinor := uint8(data[idx])
|
||||
idx++
|
||||
|
||||
versionBuild := binary.LittleEndian.Uint16(data[idx:])
|
||||
idx += 2
|
||||
|
||||
ntlmRevision := binary.BigEndian.Uint32(data[idx:])
|
||||
|
||||
// macOS reverses the endian order of this field for some reason
|
||||
if ntlmRevision == 251658240 {
|
||||
ntlmRevision = binary.LittleEndian.Uint32(data[idx:])
|
||||
}
|
||||
|
||||
info["ntlmssp.Version"] = fmt.Sprintf("%d.%d.%d", versionMajor, versionMinor, versionBuild)
|
||||
info["ntlmssp.NTLMRevision"] = fmt.Sprintf("%d", ntlmRevision)
|
||||
info["ntlmssp.TargetName"] = TrimName(string(targetName))
|
||||
|
||||
idx = 0
|
||||
for {
|
||||
if idx+4 > len(targetInfo) {
|
||||
break
|
||||
}
|
||||
|
||||
attrType := binary.LittleEndian.Uint16(targetInfo[idx:])
|
||||
idx += 2
|
||||
|
||||
// End of List
|
||||
if attrType == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
attrLen := binary.LittleEndian.Uint16(targetInfo[idx:])
|
||||
idx += 2
|
||||
|
||||
if idx+int(attrLen) > len(targetInfo) {
|
||||
// log.Printf("too short: %d/%d", idx+int(attrLen), len(targetInfo))
|
||||
break
|
||||
}
|
||||
|
||||
attrVal := targetInfo[idx : idx+int(attrLen)]
|
||||
idx += int(attrLen)
|
||||
|
||||
switch attrType {
|
||||
case 1:
|
||||
info["ntlmssp.NetbiosComputer"] = TrimName(string(attrVal))
|
||||
case 2:
|
||||
info["ntlmssp.NetbiosDomain"] = TrimName(string(attrVal))
|
||||
case 3:
|
||||
info["ntlmssp.DNSComputer"] = TrimName(string(attrVal))
|
||||
case 4:
|
||||
info["ntlmssp.DNSDomain"] = TrimName(string(attrVal))
|
||||
case 7:
|
||||
ts := binary.LittleEndian.Uint64(attrVal[:])
|
||||
info["ntlmssp.Timestamp"] = fmt.Sprintf("0x%.16x", ts)
|
||||
|
||||
}
|
||||
|
||||
// End of List
|
||||
if attrType == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TrimName removes null bytes and trims leading and trailing spaces from a string
|
||||
func TrimName(name string) string {
|
||||
return strings.TrimSpace(strings.Replace(name, "\x00", "", -1))
|
||||
}
|
||||
|
||||
// SMB2NegotiateProtocolRequest generates a new Negotiate request with the specified target name
|
||||
func SMB2NegotiateProtocolRequest(dst string) []byte {
|
||||
|
||||
base := []byte{
|
||||
0xfe, 0x53, 0x4d, 0x42,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x05, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Client GUID (16)
|
||||
base = append(base[:], RandomBytes(16)...)
|
||||
|
||||
base = append(base[:], []byte{
|
||||
0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x02, 0x02, 0x10, 0x02, 0x00, 0x03, 0x02, 0x03,
|
||||
0x11, 0x03, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00,
|
||||
0x01, 0x00,
|
||||
}...)
|
||||
|
||||
// SHA-512 Salt (32)
|
||||
base = append(base[:], RandomBytes(32)...)
|
||||
|
||||
base = append(base[:], []byte{
|
||||
0x00, 0x00, 0x02, 0x00, 0x06, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0e, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
}...)
|
||||
|
||||
encodedDst := make([]byte, len(dst)*2)
|
||||
for i, b := range []byte(dst) {
|
||||
encodedDst[i*2] = b
|
||||
}
|
||||
|
||||
netname := []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
binary.LittleEndian.PutUint16(netname[2:], uint16(len(encodedDst)))
|
||||
netname = append(netname, encodedDst...)
|
||||
|
||||
base = append(base, netname...)
|
||||
|
||||
nbhd := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(nbhd, uint32(len(base)))
|
||||
nbhd = append(nbhd, base...)
|
||||
fmt.Println(string(nbhd))
|
||||
return nbhd
|
||||
}
|
||||
76
example/tcp_ssh_test.go
Normal file
76
example/tcp_ssh_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TcpProtocol(host string, port int, timeout time.Duration) ([]byte, error) {
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", host, port), time.Duration(timeout))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second))
|
||||
reply := make([]byte, 256)
|
||||
_, err = conn.Read(reply)
|
||||
|
||||
var buffer [256]byte
|
||||
if err == nil && bytes.Equal(reply[:], buffer[:]) == false {
|
||||
if conn != nil {
|
||||
_ = conn.Close()
|
||||
}
|
||||
return reply, nil
|
||||
}
|
||||
conn, err = net.DialTimeout("tcp", fmt.Sprintf("%v:%v", host, port), time.Duration(timeout))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg := "GET /test HTTP/1.1\r\n\r\n"
|
||||
_, err = conn.Write([]byte(msg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second))
|
||||
reply = make([]byte, 256)
|
||||
_, _ = conn.Read(reply)
|
||||
if conn != nil {
|
||||
_ = conn.Close()
|
||||
}
|
||||
return reply, nil
|
||||
}
|
||||
func ByteToStringParse1(p []byte) string {
|
||||
var w []string
|
||||
var res string
|
||||
for i := 0; i < len(p); i++ {
|
||||
if p[i] > 32 && p[i] < 127 {
|
||||
w = append(w, string(p[i]))
|
||||
continue
|
||||
}
|
||||
asciiTo16 := fmt.Sprintf("\\x%s", hex.EncodeToString(p[i:i+1]))
|
||||
w = append(w, asciiTo16)
|
||||
}
|
||||
res = strings.Join(w, "")
|
||||
if strings.Contains(res, "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00") {
|
||||
s := strings.Split(res, "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00")
|
||||
return s[0]
|
||||
}
|
||||
return res
|
||||
}
|
||||
func Test1(test *testing.T) {
|
||||
buff, err := TcpProtocol("192.168.248.203", 22, 1*time.Second)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
ok, _ := regexp.Match(`^SSH.\d`, buff)
|
||||
str := ByteToStringParse1(buff)
|
||||
fmt.Println(ok, str)
|
||||
if ok {
|
||||
fmt.Println(strings.Split(str, "\\x0d\\x0a")[0])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user