对入侵者来说,获取Windows口令是整个攻击过程中至关重要的一环,拥有用户的口令将使内网渗透和守控更加容易。Windows系统中的Hash密码值主要由LM-hash值和NTLM-hash值两部分构成,一旦入侵者获取了系统的Hash值,通过LC5及彩虹表等破解工具就可以很快获取系统的密码。
本节主要探讨如何使用GetHashes工具获取系统的Hash值,并对Hash值的生成原理等知识进行讲解,最后介绍了一些有关Hash破解方面的技巧。
本节介绍与Hash相关的基础知识。
1.Hash的定义
Hash,一般翻译为“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射,Pre-Image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,故不可能从散列值来唯一确定输入值。简单地说,Hash就是一种将任意长度的消息压缩到某一固定长度的消息摘要函数。
2.Hash的应用
Hash主要用于信息安全领域的加密算法,它把一些不同长度的信息转化成杂乱的128位编码,这种编码叫做Hash值。可以说,Hash就是找到数据内容和数据存放地址之间的映射关系。
3.Hash算法在密码上的应用
MD5和SHA1可以说是目前应用最广泛的Hash算法,它们都是以MD4为基础设计的,下面简单介绍一下。
Hash算法在信息安全方面的应用主要体现在以下3个方面。
(1)文件校验
我们比较熟悉的校验算法有奇偶校验和CRC校验,这两种校验并没有抗数据篡改的能力,它们在一定程度上能检测并纠正数据传输中的信道误码,但不能防止对数据的恶意破坏。MD5 Hash算法的“数字指纹”特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少UNIX系统提供了计算MD5 Checksum的命令。
(2)数字签名
Hash算法也是现代密码体系的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。对Hash值(又称“数字摘要”)进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。
(3)鉴权协议
鉴权协议又称挑战-认证模式,在传输信道可被侦听但不可被篡改的情况下,这是一种简单而安全的方法。
下面我们讨论一下Windows的Hash密码值。
1.Windows系统的Hash密码格式
Windows系统的Hash密码格式如下。
用户名称:RID:LM-hash值:NT-hash值
Windows系统的Hash密码示例如下。
Administrator:500:C8825DB10F2590EAAAD3B435B51404EE:683020925C5D8569C23AA 724774CE6CC:::
2.Windows下LM-hash值的生成原理
假设明文口令是“Welcome”,首先全部转换成大写,即“WELCOME”,再将该大写字符串转换成二进制串“57454C434F4D4500000000000000”。
技巧
可以将明文口令复制到UltraEdit编辑器中,使用二进制方式查看即可获取口令的二进制串。
如果明文口令经过大写变换后的二进制字符串不足14字节,则需要在其后添加“0x00”来补足14字节。
将转换后的二进制串切割成2组7字节的数据,分别经str_to_key() 函数处理,得到2组8字节数据。
说明
str_to_key()函数的C语言描述如下。
#include <stdio.h> #include <stdlib.h> #include <string.h> /* * 读取形如“AABBCCDDEEFF”的16进制数字串,由主调者进行形参的边界检查 */ static void readhexstring ( const unsigned char *src, unsigned char *dst, unsigned int len ) { unsigned int i; unsigned char str[3]; str[2] = '\0'; for ( i = 0; i < len; i++ ) { str[0] = src[ i * 2 ]; str[1] = src[ i * 2 + 1 ]; dst[i] = ( unsigned char )strtoul( str, NULL, 16 ); } return; } /* end of readhexstring */ /* * from The Samba Team's source/libsmb/smbdes.c */ static void str_to_key ( const unsigned char *str, unsigned char *key ) { unsigned int i; key[0] = str[0] >> 1; key[1] = ( ( str[0] & 0x01 ) << 6 ) | ( str[1] >> 2 ); key[2] = ( ( str[1] & 0x03 ) << 5 ) | ( str[2] >> 3 ); key[3] = ( ( str[2] & 0x07 ) << 4 ) | ( str[3] >> 4 ); key[4] = ( ( str[3] & 0x0F ) << 3 ) | ( str[4] >> 5 ); key[5] = ( ( str[4] & 0x1F ) << 2 ) | ( str[5] >> 6 ); key[6] = ( ( str[5] & 0x3F ) << 1 ) | ( str[6] >> 7 ); key[7] = str[6] & 0x7F; for ( i = 0; i < 8; i++ ) { key[i] = ( key[i] << 1 ); } return; } /* end of str_to_key */ int main ( int argc, char * argv[] ) { unsigned int i; unsigned char buf_0[21]; unsigned char buf_1[24]; if ( argc != 2 ) { fprintf( stderr, "Usage: %s <hexadecimal string>\n", argv[0] ); return( EXIT_FAILURE ); } memset( buf_0, 0, sizeof( buf_0 ) ); memset( buf_1, 0, sizeof( buf_1 ) ); i = strlen( argv[1] ) / 2; readhexstring( argv[1], buf_0, i ); for ( i = 0; i < s { fprintf( stderr } fprintf( stderr, " str_to_key( buf_0, str_to_key( buf_0 str_to_key( buf_0 for ( i = 0; i < s { fprintf( stderr } fprintf( stderr, " return( EXIT_SUCCE } /* end of main */
将这2组8字节数据作为DESKey对魔术字符串“KGS!@#$%”进行标准DES加密。
3.Windows下NTLM-hash值的生成原理
IBM设计的LM-hash算法存在几个弱点,微软在保持向后兼容性的同时提出了自己的挑战响应机制,NTLM-hash应运而生。
假设明文口令是“123456”,首先将其转换成Unicode字符串,与LM-hash算法不同,NTLM-hash不需要添加“0x00”补足14字节。
从ASCII串转换成Unicode串时使用LITTLE-ENDIAN,微软在设计SMB协议时就没有考虑BIG-ENDIAN,ntoh*()、hton*() 函数不宜用在SMB报文解码中。0x80之前的标准ASCII码转换成Unicode码,就是简单地从“0x??”变成“0x00??”。此类标准ASCII串按LITTLE-ENDIAN转换成Unicode串,就是简单地在原有数据的每个字节之后添加“0x00”。对获取的Unicode串进行标准MD4单向Hash,无论数据源有多少字节,MD4固定产生128位的Hash值。
得到的NTLM-hash为32ED87BDB5FDC5E9CBA88547376818D4。
与LM-hash算法相比,明文口令对大小写敏感,无法根据NTLM-hash判断原始明文口令是否小于8字节,且摆脱了魔术字符串“KGS!@#$%”。MD4是真正的单向Hash函数,穷举作为数据源出现的明文时难度较大。
GetHashes是InsidePro公司早期的一款Hash密码获取软件,目前的最高版本是1.6。InsidePro公司的网址为http://www.InsidePro.com。此外,该公司还有SAMInside、PasswordsPro、Extreme GPU Bruteforcer这3款密码破解软件。现在,AMInside已经将GetHashes等软件整合在一个软件中了。
1.GetHashes命令格式
一般使用“GetHashes $Local”命令获取系统的Hash密码值,该命令仅在System权限下才能执行成功,示例如下。
GetHashes <SAM registry file> [System key file] Or GetHashes $Local
根据个人爱好,可以将GetHashes软件更名为其他名称,在后面的案例中就将其命名为“getpw”。
2.使用GetHashes获取系统Hash值实例
将“GetHashes”更名为“getpw”,将其复制到欲获取Hash密码值的系统盘中,然后执行“getpw $local”命令,如图1-1所示,顺利获取其Hash密码值。本例中使用的是Radmin的Telnet。依次单击“文本”→“保存为”选项,将结果保存为一个新文件,使用UltraEdit编辑器进行编辑,仅保存Hash密码值部分,然后使用LC5导入Hash密码值即可破解系统的密码。
图1-1 获取系统Hash值
注意
(1)使用GetHashes获取系统的Hash密码值时,必须要在System权限下,也就是在反弹Shell或者Telnet下。
(2)如果系统中安装了杀毒软件或者防火墙,有可能由于杀毒软件和防火墙的保护而导致密码获取失败。研究发现,由于GetHashes威力巨大,主要用在入侵过程中获取系统的Hash密码值,因此绝大多数杀毒软件已经将GetHashes加入病毒库。如图1-2所示是Castlecops网站提供的各大杀毒软件针对 GetHashes制作的病毒库版本及更新信息。
图1-2 许多杀毒软件已经将GetHashes作为病毒处理
(3)InsidePro公司在其网站上还提供了一个Hash产生器,通过输入一些参数值就能够生成经过某种加密算法处理的口令密码值,如图1-3所示,有兴趣的读者可以尝试。该功能在研究系统Hash密码值的生成时可以进行相互验证。
图1-3 Hash生成器
(4)Hash密码值在线查询。在http://hash.insidepro.com/网站还可以在线查询Hash密码值的原始明文口令,如图1-4所示。将经过MD5加密的Hash值输入后,单击“Search”按钮,如果数据库中存在该值的计算结果,就会在该页面给出。
图1-4 在线破解Hash密码值
使用GetHashes获取系统的Hash值,一般是在获得了系统的部分或者全部控制权限之后,通常是在新的漏洞利用工具发布之后。例如,当系统中存在MS08067漏洞时,可以使用MS08067漏洞利用工具获得存在此漏洞的计算机的一个反弹Shell,然后将GetHashes软件上传到系统中,执行“GetHashes $Local”命令。
下面总结一些GetHashes的使用经验和技巧。
01 在获得反弹Shell的情况下,首先查看系统中是否存在杀毒软件。如果存在,则尝试将其关闭。如果不能关闭,则放弃使用GetHashes获取Hash密码值,转向下一步。
02 查看系统版本,以及系统是否开启了3389远程终端。如果未开启3389终端,判断可否直接开启3389终端。如果可以利用3389终端,则直接添加一个具有管理员权限的用户,然后以该用户的身份登录系统。
03 关闭杀毒软件,再次通过Shell或其他控制软件的Telnet执行“GetHashes $Local”命令来获取Hash密码值,最后删除新添加的用户。