shadow文件的MD5密码破解
root:$1$abcde$LULigrJwcdszq2ReOX7bG/:15933:0:99999:7:::
hint:密码长度不超过6
root:$1$abcde$LULigrJwcdszq2ReOX7bG/:15933:0:99999:7:::
这是在linux下的shadow文件中,用来存放用户的账户和密码,在/etc/shadow目录下。
其内容用“:”号隔开,分别表示不同的内容:
1)“登录名”(root):是与/etc/passwd文件中的登录名相一致的用户账号。
2)“口令”($1$abcde$LULigrJwcdszq2ReOX7bG/
):字段存放的是加密后的用户口令字,如果为空,则对应用户没有口令,登录时不需要口令;星号代表帐号被锁定;双叹号表示这个密码已经过期了。
$6开头的,表明是用SHA-512加密的,$1表明是用MD5加密的,$2是用Blowfish加密的,$5是用 SHA-256加密的;
$abcde表示加密算法所加的盐值为abcde;
$LULigrJwcdszq2ReOX7bG/表示加密算法得到的密文为LULigrJwcdszq2ReOX7bG/。
3)“最后一次修改时间”(15933):表示的是从某个时刻起,到用户最后一次修改口令时的天数,时间起点对不同的系统可能不一样,例如在SCOLinux中,这个时间起点是1970年1月1日。
4)“最小时间间隔”(0):指的是两次修改口令之间所需的最小天数。
5)“最大时间间隔”(99999):指的是口令保持有效的最大天数。
6)“警告时间”(7):字段表示的是从系统开始警告用户到用户密码正式失效之间的天数。
7)“不活动时间”():表示的是用户没有登录活动但账号仍能保持有效的最大天数。
8)“失效时间”():字段给出的是一个绝对的天数,如果使用了这个字段,那么就给出相应账号的生存期。期满后,该账号就不再是一个合法的账号,也就不能再用来登录了。
9)保留字段()
所以题目是要我们破解Linux下shadow文件的密码,其中的关键是$1$abcde$LULigrJwcdszq2ReOX7bG/
,表示盐值为abcde的MD5加密的密文LULigrJwcdszq2ReOX7bG/,我们需要解出明文密码。
一、直接代码暴力破解
descarck.c
//编译选项:gcc -O3 descrack.c -lcrypt -o descrack
#define _XOPEN_SOURCE /* See feature_test_macros(7) */
#include <unistd.h>
#include <stdio.h>
#include <crypt.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
char data[37] = "0123456789abcdefghijklmnopqrstuvwxyz";
//待解密的密文
char * goalPass = "$1$abcde$LULigrJwcdszq2ReOX7bG/";
//存储遍历的明文
char mypwd[10];
//最短的密码长度
int minlen = 1;
//最长的密码长度
int maxlen = 6;
//当前时间
time_t global_start;
void subgenerate(int index, int pwdlen)
{
if (index == pwdlen)
return;
int i;
for (i = 0; i < 36; i++)
{
mypwd[index] = data[i];
memset(mypwd + index + 1, data[0], pwdlen- index -1);
if (i != 0)
{
//printf("%s ",mypwd);
//strcmp:相等则返回0,!0让程序输出退出
if (!strcmp(goalPass, crypt(mypwd, "$1$abcde$")))
{
printf("当前程序花费的时间: %ld (秒)\n",
(time(NULL) - global_start));
printf("解密后的明文密码是:%s\n", mypwd);
exit(0);
}
}
subgenerate(index + 1, pwdlen);
}
}
void generate(int pwdlen, int start, int end)
{
int i;
// 多线程可分段
for (i = start; i < end; i++)
{
mypwd[0] = data[i];
//填充长度
memset(mypwd + 1, data[0], pwdlen-1);
//printf("%s ",mypwd);
if (!strcmp(goalPass, crypt(mypwd, "$1$abcde$")))
{
printf("当前程序花费的时间: %ld (秒)\n",
(time(NULL) - global_start));
printf("解密后的明文密码是:%s\n", mypwd);
exit(0);
}
subgenerate(1, pwdlen);
}
}
int main()
{
//赋值为当前时间
global_start = time(NULL);
char mypwd[10];
int i,threadnum = 10;
for (i = minlen; i <= maxlen; i++)
{
printf("当前破解密码的长度:%d\n", i);
//password length
memset(mypwd, 0, 10);
//留作多线程
generate(i,0,36);
printf("当前程序花费的时间: %ld (秒)\n",
(time(NULL) - global_start));
}
puts("在指定的范围内没有找到正确的密码");
return 0;
}
运行结果:
得到解密后的明文密码123qwe,大概需要32005秒也就是8个小时53分25秒。
二、工具破解(John the Ripper)
John the Ripper的安装过程可以参考我的另一篇文章:Bugku-加密-Crack it(shadow文件解密)
根据提示下载 John 并拷贝到虚拟机
进 入 src 目 录 , 使 用 make 指 令 查 看 可 安 装 的 系 统
选择第七个 linux-x86-mmx,安装完成后,退出 src 并进入 run 目录,在 run 目录下新建文件,把我们要破解的内容放进去,这里我将它命名为 root:
文件创建完成后就可以使用 John 破解了,先进入root权限(不然会提示权限不够),输入./john root 指令
1秒钟就得到了结果,破解结果也是123qwe,的确是不超过 6 位的密码,验证了我们的结果。