密码攻击之基于字典和彩虹表的密码攻击

一、撞库攻击

最近经常听到撞库攻击的有关新闻,撞库就是黑客通过收集互联网已泄露的用户和密码信息,生成对应的字典表,尝试批量登陆其他网站后,得到一系列可以登录的用户。作为一个小白,我先从破解口令散列值的尝试入手。

二、Hash函数的特点

哈希函数:把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。数学表述为:h = H(M) ,其中H( )--单向散列函数,M--任意长度明文,h--固定长度散列值。

程序实现如下:(来自百度百科)

// 说明:Hash函数(即散列函数)在程序设计中的应用目标 ------ 把一个对象通过某种转换机制对应到一个
//size_t类型(即unsigned long)的整型值。
// 而应用Hash函数的领域主要是 hash表(应用非常广)、密码等领域。
// 实现说明:
// ⑴、这里使用了函数对象以及泛型技术,使得对所有类型的对象(关键字)都适用。
// ⑵、常用类型有对应的偏特化,比如string、char*、各种整形等。
// ⑶、版本可扩展,如果你对某种类型有特殊的需要,可以在后面实现专门化。
// ⑷、以下实现一般放在头文件中,任何包含它的都可使用hash函数对象。
//------------------------------------实现------------------------------------------------
#include <string>
using std::string;
inlinesize_thash_str(const char* s)
{
unsigned long res = 0;
for (; *s; ++s)
res = 5 * res + *s;
returnsize_t(res);
}
template <class Key>
struct hash
{
size_toperator () (const Key& k) const;
};
// 一般的对象,比如:vector< queue<string> >;的对象,需要强制转化
template < class Key >
size_thash<Key>::operator () (const Key& k) const
{
size_tres = 0;
size_tlen = sizeof(Key);
const char* p = reinterpret_cast<const char*>(&k);
while (len--)
{
res = (res<<1)^*p++;
}
return res;
}
// 偏特化
template<>
size_thash< string >::operator () (const string& str) const
{
return hash_str(str.c_str());
}
typedef char* PChar;
template<>
size_thash<PChar>::operator () (const PChar& s) const
{
return hash_str(s);
}
typedef const char* PCChar;
template<>
size_thash<PCChar>::operator () (const PCChar& s) const
{
return hash_str(s);
}
template<> size_t hash<char>::operator () (const char& x) const { return x; }
template<> size_t hash<unsigned char>::operator () (const unsigned char& x) const { return x; }
template<> size_t hash<signed char>::operator () (const signed char& x) const { return x; }
template<> size_t hash<short>::operator () (const short& x) const { return x; }
template<> size_t hash<unsigned short>::operator () (const unsigned short& x) const { return x; }
template<> size_t hash<int>::operator () (const int& x) const { return x; }
template<> size_t hash<unsigned int>::operator () (const unsigned int& x) const { return x; }
template<> size_t hash<long>::operator () (const long& x) const { return x; }
template<> size_t hash<unsigned long>::operator () (const unsigned long& x) const { return x; }
// 使用说明:
//
// ⑴、使用时首先由于是泛型,所以要加上关键字类型。
//
// ⑵、其次要有一个函数对象,可以临时、局部、全局的,只要在作用域就可以。
//
// ⑶、应用函数对象作用于对应类型的对象。
//----------------------- hash函数使用举例 -------------------------
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> vstr⑵;
vstr[0] = "sjw";
vstr[1] = "suninf";
hash<string> strhash; // 局部函数对象
cout << " Hash value: " << strhash(vstr[0]) << endl;
cout << " Hash value: " << strhash(vstr[1]) << endl;
cout << " Hash value: " << hash< vector<string> >() (vstr) << endl;
cout << " Hash value: " << hash<int>() (100) << endl; // hash<int>() 临时函数对象
return 0;
}

哈希函数最大的特点就是单向性(one-way),由明文计算散列值是极其容易的,但从散列值推得明文在计算上不可行。而hash函数的抵抗强碰撞性和抵抗弱碰撞性,是目前的两个突破点。

破解口令散列值即从这里进行尝试。

三、基于彩虹表的散列值破解攻击

1.首先来个题外话,根据口令设置中对字符的要求设定可用字符集和字符数量,假设目前只支持英文字母大小写和阿拉伯数字0123456789,先基于使用字符生成用户口令词典。

使用crunch工具,它的基本语法是 crunch [minimum length] [maximum length] [character set] [options] 

-o:这个选项允许你指定输出列表的文件名称和位置

-b:这个选项允许你指定每个文件的最大字节数。大小可以以 KB/MB/GB 来指定,并且必须和-o START触发器一起使用。

-t:这个选项允许你指定所使用的模式。

       -l:在使用-t选项时,这个选项允许你将一些字符标识为占位符(@,%,^)

现在要做的是:执行命令来在桌面上创建密码列表,它最少8 个字母,最大 10 个字符,并且使用字符集ABCDEFGabcdefg0123456789。

crunch 8 10 ABCDEFGabcdefg0123456789 –o /root/Desktop/ generatedCrunch.txt

使用如下指令:crunch 4 5 ABCDEFGabcdefg0123456789 –o /root/Desktop/ generatedCrunch.txt

可使用nano打开文件

也可直接打开。

就这样,我们使用了Crunch 来生成密码字典列表。

2.使用彩虹表 rainbowcrack

使用rtgen工具生成彩虹表,具体操作如下图所示:

指令和选项整理详细内容参照官方文档:http://project-rainbowcrack.com/documentation.htm

彩虹表生成完毕需要2-7个小时,最后生成.rt文件。

为简化实验数据量,仅用数字生成散列值,1-4位:

花费时间约2.5小时。文件大小为536.9MB。

为了方便使用彩虹表,可以进行排序:

再次尝试:

基于彩虹表进行散列值的破解:

可知该散列值破解结果为2342.

使用6666生成散列值:

e9510081ac30ffa83f10b68cde1cac07

运行之后:

Yes!!!

猜你喜欢

转载自blog.csdn.net/qq_37865996/article/details/83744958