峯言凬语 My life is brilliant~
常用标签
/etc/shadow

root:$1$BTkC8R/1$ZtNrYbhknXmNKGHDJCmJc1:0:0:99999:7:::
密码是 123456

其格式为:
{用户名}:{加密后的口令密码}:{口令最后修改时间距原点(1970-1-1)的天数}:{口令最小修改间隔(防止修改口令,如果时限未到,将恢复至旧口令):{口令最大修改间隔}:{口令失效前的警告天数}:{账户不活动天数}:{账号失效天数}:{保留}

shadow文件为可读文件,普通用户没有读写权限,超级用户拥有读写权限。如果密码字符串为*,则表示系统用户不能被登入;如果字符串为!,则表示用户名被禁用;如果字符串为空,则表示没有密码。
可以使用passwd –d 用户名 来清空一个用户的口令密码。

参考linux标准源文件passwd.c,其中的pw_encrypt函数为加密方法,加密算法就是用明文密码和salt通过函数crypt()完成加密,salt参数是某个固定长度的随机字符串,密码域密文由三部分组成:$id$salt$encrypted
id为1时,采用md5进行加密;
id为5时,采用SHA256进行加密;
id为6时,采用SHA512进行加密。

数据加密函数crypt()

  1. 头文件:#define _XOPEN_SOURCE

include <unistd.h>

  1. 函数原型:char crypt(const char key, const char *salt);
  2. 函数说明:crypt()将使用DES演算法将参数key所指的字符串加以编码,key字符串长度仅取前8个字符,超过此长度的字符没有意义。参数salt为两个字符组成的字符串,由a-z、A-Z、0-9,’.’和’/’所组成,用来决定使用4096种不同内建表格的哪一种。函数执行成功后会返回指向编码过的字符串指针,参数key所指向的字符串不会有所改动。编码过的字符串长度为13个字符,前两个字符为参数salt代表的字符串。
  3. 返回值:返回一个指向以NULL结尾的密码字符串
  4. 使用GCC编译时需要加上 –lcrypt

方式:
在每次改写密码时,会随机生成一个salt。登录时输入的明文密码经过演化后与shadow里的密码域进行字符串比较,以此来判断是否允许用户登录。

破解linux下的口令示例代码(源自CSDN):

    #include <pwd.h>
#include <stddef.h>
#include <string.h>
#include <shadow.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])

{

if(argc < 2)

{

printf("no usrname input");

return 1;

}

if (geteuid() != 0)

{

fprintf(stderr, "must be setuid root");

return -1;

} 

struct spwd *shd= getspnam(argv[1]);

if(shd != NULL)

{

static char crypt_char[80];

strcpy(crypt_char, shd->sp_pwdp);

char salt[13];

int i=0,j=0;

while(shd->sp_pwdp[i]!='\0')

{

salt[i]=shd->sp_pwdp[i];

if(salt[i]=='$')

{

j++;

if(j==3)

{

salt[i+1]='\0';

break;

}

}

i++;

}

if(j<3)

perror("file error or user cannot use.");

if(argc==3)

{

printf("salt: %s, crypt: %s\n", salt, crypt(argv[2], salt));

printf("shadowd passwd: %s\n", shd->sp_pwdp);

}

}

return 0;

}

编译:

gcc passwd.c -lcrypt -o passwd

运行:

./passwd root 123456

结果:

salt: $1$BTkC8R/1$, crypt: $1$BTkC8R/1$ZtNrYbhknXmNKGHDJCmJc1
            shadowd passwd: $1$BTkC8R/1$ZtNrYbhknXmNKGHDJCmJc1
暂无评论

添加新评论