📄 pass.c
字号:
#include <stdio.h>
#include <pwd.h>
#include <ctype.h>
#define MAX_WORDS 64000 //字典中最多的单词数
#define BUFSIZE 1024;
/* 命令行选项:
* -w file: 字典文件,文件中每个口令占一行
* -p: pfile 指定口令文件,缺省使用/etc/shadow
*/
char PASSWD_FILE[256]; //存放系统口令文件名
char WORD_FILE[256]; //存放口令字典文件名
char line[BUFSIZ+1];
int getpwd(FILE *pwf, struct passwd *pwd);
int chkpw();
int uandltry (struct passwd *pwd,char *guess);
int trymatch(struct passwd *pwd,char *guess); //将guess使用crypt加密看是否等于pwd口令
int reverse(char *str1,char *str2);
int main(int argc, char **argv)
{
int i;
char *arg;
strcpy(PASSWD_FILE, "/etc/shadow"); //缺省的口令文件
strcpy(WORD_FILE,"./pass.words"); //缺省的口令字典
for (i = 1; i < argc; i++) //分析命令行参数
if ((arg = argv[i]) && *arg == '-')
while (*++arg) {
switch (*arg) {
case 'p'://指定要破解的口令文件
if (argv[i+1] == NULL) {
printf( "%s: No file supplied with -P option\n",argv[0]);
exit (1);
}
strcpy(PASSWD_FILE, argv[i+1]);
argv[i+1] = NULL;
break;
case 'w': //consult word list of likely passwords
strcpy(WORD_FILE,argv[i+1]);
if (!strlen(WORD_FILE)) {
printf( "%s: No file supplied with -w option\n",argv[0]);
exit (1);
}
argv[i+1] = NULL;
break;
default:
printf( "%s: unknown option '%c'. Options are:\n",argv[0], *arg);
exit(1);
}
argv[i] = NULL;
}
chkpw();
exit(0);
}
//这是核心函数,检查
int chkpw()
{
register char *cp, *cp2;
struct passwd *pwd; //用于保存一个用户的口令信息
char guess[100];
char *wordarray[MAX_WORDS];
int done = 0;//破解标志
int wordnum=0;
FILE *wlf = NULL,*pwf = NULL;//文件指针,分别用于系统口令文件 和口令字典文件。
if(!strlen(WORD_FILE))
{
printf("No wordlist file!\n");
exit(1);
}
if ((wlf = fopen(WORD_FILE,"r")) == NULL) {
printf("error in opening the wordlist file\n");
exit(1);
}
//将字典文件中的候选口令读入到字符串数组中
while (fscanf(wlf,"%[^\n]\n",guess) != EOF) {
//将口令文件中的口令读入字符串数组wordarray
if ((wordarray[wordnum] =(char *)malloc(1+strlen(guess))) == NULL)
{
//为口令分配空间
printf("malloc: no more memory for wordlist\n");
exit (1);
}
strcpy(wordarray[wordnum],guess);
wordnum++;
if (feof(wlf)) break;
if(wordnum>=MAX_WORDS) //留最后一个位置置为NULL,作为结束标志
{
printf("wordlist space is too small");
break;
}
}//end of while
fclose(wlf);
//打开系统的口令文件
if ((pwf = fopen(PASSWD_FILE,"r")) == NULL)
{
printf("open password file error! ");
return(0);
}
pwd=(struct passwd * )malloc(sizeof(struct passwd));
while ((getpwd(pwf, pwd)) != 0 )
{ //读取一个用户的口令信息到变量pwd
done = 0;
if (strlen(pwd->pw_passwd)<12) { //空口令
printf("Warning! Password Problem: null passwd:\t%s\n",pwd->pw_name);
continue;
}
// 试试用户名
if (uandltry(pwd,pwd->pw_name)) continue;
//试试用户名重写
strcpy(guess,pwd->pw_name);
strcat(guess,pwd->pw_name);
if (uandltry(pwd,guess)) continue;
if (wordnum) //逐一检查字典中的词
{
int i=0;
while (i < wordnum)
{
if (wordarray[i] == NULL)
break;
if (uandltry(pwd,wordarray[i]))
{
done++;
break;
}
i++;
}
}
if (!done ) { //检查单字母口令single letters and digits too
guess[1] = '\0';
for (guess[0]='a'; guess[0] <= 'z'; guess[0]++)
if (trymatch(pwd,guess))
break;
for (guess[0]='A'; guess[0] <= 'Z'; guess[0]++)
if (trymatch(pwd,guess))
break;
for (guess[0]='0'; guess[0] <= '9'; guess[0]++)
if (trymatch(pwd,guess))
break;
}
}//endof while
fclose(pwf);
}//end of chpwd
/* 代表"upper(大写) and lower(小写)" try. */
//试试guess、guess的反序以及guess全部变为大写字母和全部变为小写字母后的字符串
//match则返回1,否则返回0
int uandltry (struct passwd *pwd,char *guess)
{
register char *cp;
char buf[100],revbuf[100];
int alllower, allupper;
alllower = allupper = 1;
if (trymatch(pwd,guess)) return 1;//检查guess是否口令
if(reverse(guess,revbuf))
{//检查guess的反序
if(trymatch(pwd,revbuf)) return 1;
}
strcpy (buf, guess);
cp = buf-1;
while (*++cp) {
if (isupper(*cp)) //有大写
alllower = 0;
if (islower(*cp)) //有小写
allupper = 0;
}
if (!allupper) { //如果有小写字母,则全部改为大写,再试试
for ( cp=buf; *cp != '\0'; cp++)
if (islower (*cp)) *cp += 'A' - 'a';
if (trymatch(pwd,buf) ) return 1;
reverse(buf,revbuf); //尝试反序
if(trymatch(pwd,revbuf)) return 1;
}
if (!alllower) { //如果有大写字母,全部改为小写,再试试
for ( cp = buf; *cp != '\0'; cp++)
if (isupper (*cp)) *cp += 'a' - 'A';
if (trymatch(pwd,buf))return 1;
reverse(buf,revbuf); //尝试反序
if(trymatch(pwd,revbuf)) return 1;
}
return (0);
}
//将guess使用crypt加密看是否等于pwd口令
//破解返回1
//否则返回0
int trymatch(register struct passwd *pwd,char *guess)
{
register char *cp;
char *crypt ();
char saltstr[13];
saltstr[13]='\0';
if (! guess || ! *guess) return(0);
strncpy(saltstr,pwd->pw_passwd,12);//前12个字符是salt
cp = crypt (guess, saltstr); //对候选口令和种子调用加密函数crypt
if (strncmp (cp, pwd -> pw_passwd, 34))//比较加密结果,不匹配
return (0);
//匹配,打印信息
printf ("Warning! Password Problem: Guessed:\tuser:%s\tpasswd: %s\n",pwd -> pw_name, guess);
return (1);
}
#define MAXUID 0x7fff
char *pwskip(char *p) //找到下一个域
{
while(*p && *p != ':' && *p != '\n')
++p;
if(*p == '\n')
*p = '\0'; //去掉换行符
else if(*p)
*p++ = '\0'; //去掉:号,并指向下一个域
return(p);
}
int getpwd(FILE *pwf, struct passwd *pwd) //获取文件pwf的当前行的用户口令结构
{
char *p;
long x;
p = fgets(line, BUFSIZ, pwf);//读取一行
if(p == NULL) return(0);
pwd->pw_name = p;
p = pwskip(p);
pwd->pw_passwd = p;
p = pwskip(p);
x = atol(p);
pwd->pw_uid = (x < 0 || x > MAXUID)? (MAXUID+1): x;//检查用户的id
p = pwskip(p);
x = atol(p);
pwd->pw_gid = (x < 0 || x > MAXUID)? (MAXUID+1): x;//检查组id
p = pwskip(p);
pwd->pw_gecos = p;
p = pwskip(p);
pwd->pw_dir = p;
p = pwskip(p);
pwd->pw_shell = p;
(void) pwskip(p);
p = pwd->pw_passwd;
return(1);
}
//将一个字符串反序
int reverse(char *str1,char *str2)
{
char *ptr;
if(strlen(str1)>=100) return 0;
ptr = str2 + strlen(str1);
*ptr = '\0';
while (*str1 && (*--ptr = *str1++));
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -