PersonalCorpus 版 (精华区)
发信人: lofe ()感激生活(), 信区: Hacker
标 题: 微机BIOS口令破译与设置
发信站: 哈工大紫丁香 (Tue Sep 5 19:20:32 2000), 转信
微机BIOS口令破译与设置
华中理工大学CAD中心
本文详细阐述了海洋主板、DECpc主板(Digital公司)和AMI主板的口令加密算法与解密算法,用到了计算CMOS校验和的算法,并给出了破译口令和修改口令的程序。
一、海洋主板
海洋主板口令最多由10个字符构成,加密后只生成一个16位的密码,存储在CMOS单元3AH和3BH。口令检查方式存储于3CH单元的最高二位,00表示disable, 01表示setup only, 10表示 Powerup&Setup,11表示Bootup&Setup。口令加密算法如下:
设
口令长度为 L L≤10
明文口令为 Y={y1, y2, ... , yL}
加密因子为 K={k0, k1, ... , kL} 其中k0=FFFFH
密文口令为 M
则 ki= f(ki-1, yi) 1≤i≤L
M= kL
加密函数 ki= f(ki-1, yi) 定义为:
设 yi={Bit0, Bit1 , ... , Bit14 ,Bit15 },
明文yi由ASCII码加扫描码构成 ,故有16位。
则 S0= ki-1
Sj+1 = ( Sj * 2 + Bitj ) XOR 1021H 如果Sj AND 8000H >0
Sj+1 = ( Sj * 2 + Bitj ) 如果Sj AND 8000H =0
(0≤j≤15)
ki= S16
通过对加密过程分析可知,加密函数是多对一函数,即多个明文对应一个密文。这说明海洋微机可能有多个口令。因此,加密过程不可逆,解密算法只能是穷举法。
二、DECpc主板
DECpc主板口令最多由7个字符构成 ,经加密变换后存储于CMOS单元58H-5EH,5FH单元存储口令扫描码的字节累加和。加密算法比较简单,算法如下:
设
口令长度为 L L≤7
明文口令为 Y={y1, y2, ... , yL}
密文口令为 M={m1, m2, ... , mL}
则
mi = ROR( yi XOR AAH, 7- i ) 1≤i≤L
其中ROR为循环右移函数。
解密函数为:
yi = ROL( mi , 7- i ) XOR AAH 1≤i≤L
其中ROL为循环左移函数。
三、AMI主板
AMI主板口令可由6个字符构成 ,加密后存储于CMOS单元38H-3DH,37单元存储加密算法的加密因子,是随机生成的。故多次设置的同一口令的密文并不相同。
设
口令长度为 L L≤6
明文口令为 Y={y1, y2, ... , yL}
加密因子为 m0
密文口令为 M={m1, m2, ... , mL}
则 mi= f(mi-1, yi) 1≤i≤L
加密函数 mi=f(mi-1, yi) 定义为:
S0=mi-1
Sj+1 =Sj / 2 + 80H 如果 Sj AND C3H 的奇偶性为奇
Sj+1 =Sj / 2 如果 Sj AND C3H 的奇偶性为偶
(0≤j ≤yi )
mi= Syi+1
解密算法不再列出。
加密算法比较
主板类型 特征字符串 密文存储单元 口令长度 校验和1 校验和2 允许/禁止单元 多个口令
MR 'MR BIOS' 3A-3B 10 2E,2F 3F 3C bit6,bit7 是
DECpc 'DECpc' 58-5E 7 2E,2F 5F N/A 否
AMI 'AMMMMI' 38-3D 6 2E,2F 3E,3F 34 bit6 否
Phoenix 'Phoenix' 27-28, 29-2A 7 2E,2F 6E,6F,70 55 bit4 是
以上算法省略了与扫描码有关的细节。据此,笔者编写了针对三种主板的口令破译与修改程序PWD.CPP。程序首先自动识别主板类型,在BIOS段F000H中搜索能代表主板的特征字符串。DECpc主板也包含字符串'Phoenix',
但是优先寻找'DECpc'。然后根据主板类型调用不同的解密算法,显示机器BIOS口令。对海洋微机可求出多个口令,用户输入任一口令即可使用该机器。还能直接修改BIOS口令,对于海洋主板和AMI主板,修改口令后需重新计算CMOS校验和,算法详见程序。本程序在多台微机上测试通过。
// Filename PWD.CPP
// (C) Copyright SunJian CAD Center, HUST. All Rights Reserved
// Compile with SMALL model Tel:7543973
/************************************************************
function : Show your CMOS password
date : 1994 11 11
Modify : 1996 3 2
************************************************************/
#ifndef __SMALL__
#error complile with small model
#endif
#include <stdio.h>
#include <conio.h>
#include <bios.h>
#include <dos.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define INDEX 0x70
#define VALUE 0x71
#define BYTE unsigned char
#define WORD unsigned int
void help();
void display();
void wbyte(int port, unsigned value);
BYTE rbyte(int port);
void cal_checksum( int checklen);
int write_mrsum();
int write_amisum();
void change_bios();
int test_biostype(void);
void show_mrpassword();
void change_mrpassword(char*);
void show_dec_password();
void change_dec_password(char*);
void show_ami_password();
void change_ami_password(char*);
//void show_phoenix_password();
WORD scan_code[]={
0, 0x1e61,0x3062,0x2e63,0x2064,0x1265,
0x2166,0x2267,0x2368,0x1769,0x246a,
0x256b,0x266c,0x326d,0x316e,0x186f,
0x1970,0x1071,0x1372,0x1f73,0x1474,
0x1675,0x2f76,0x1177,0x2d78,0x1579,
0x2c7a,
0x0231,0x0332,0x0433,0x0534,0x0635,
0x0736,0x0837,0x0938,0x0a39,0x0b30,
0x0c2d,0x0d3d,0x0e08,0x0f09
//scan code of 'a-z 0-9'
} ;
char str[22]="";
int *pstr=(int*)str;
struct {
char *name;
int (*sum) () ;
void (*show)();
void (*change)(char *);
} biosdesc[]={
"AMMMMI", write_amisum,show_ami_password, change_ami_password,
"MR BIOS",write_mrsum,show_mrpassword,change_mrpassword,
"DECpc", NULL,show_dec_password,change_dec_password,
"Phoenix",NULL,NULL,NULL,
} ;
#define cprintf printf
void help(void)
{
cprintf("\nCMOS Password Utility (Version 1.00) Mar 1996 Tel:(027)7800172\r\n");
cprintf("(C) Copyright SunJian CAD Center, HUST. All Rights Reserved\r\n\n");
cprintf(" Password utility for AMI bios, MR bios & DECpc bios\r\n");
cprintf("Usage : PWD --display bios password directly\r\n");
cprintf(" PWD [new_password] --change bios password\n");
cprintf("\r\n");
return;
}
int biostype=0;
/*main function of cmos*/
void main(int argc, char *argv[])
{
clrscr();
help();
biostype=test_biostype();
if(biostype==0 )
{
printf("Unknow BIOS!\n");
return;
}
printf("BIOS type: %s\n",biosdesc[biostype-1].name );
if (argc==2)
{
if(biosdesc[biostype-1].change)
(*biosdesc[biostype-1].change)(argv[1]);
}
else if (argc==1)
{
if(biosdesc[biostype-1].show)
(*biosdesc[biostype-1].show)();
}
}
/* print CMOS element */
void display()
{
int i;
for (i=0x0 ;i<0x10 ;i++)
printf("%-5x",i);
for (i=0x10 ;i<0x80 ;i++)
printf("%-5x",rbyte(i));
printf("\n");
}
BYTE rbyte(int port)
{
outp(INDEX,port);
outp(0xed, port);
return inp(VALUE);
}
void wbyte(int port, unsigned value)
{
disable();
outp(INDEX,port);
outp(0xed, port);
outp(VALUE, value&0xff);
enable();
}
void outw(int port, unsigned value)
{
wbyte(port, value&0xff);
wbyte(port+1, value>>8);
}
WORD inw(int port)
{
WORD value;
outp(INDEX,port);
outp(0xed, port);
value=inp(VALUE);
outp(INDEX,port+1);
outp(0xed, port+1);
value= value+( inp(VALUE)<<8 );
return value;
}
/*cal checksum of ami bios, From addr 34 to 3d and 40 to ...,save to 3e*/
int write_amisum()
{
WORD i=0,num;
WORD sum=0;
BYTE movsi[]={
0xbe,0x40,0xe0,0
};
//code of MOV si, e040
BYTE far *pkey=(BYTE far*)movsi;
WORD far *p;
BYTE far *ROM=(BYTE far*)MK_FP(0xf000,0);
for(i=0;i<0xa;i++)
sum+=rbyte( 0x34+i);
for (i=0;i<0xfff0;i++)
if (_fstrncmp(ROM+i,pkey,3)==0)
break;
if (i<0xfff0)
{
ROM+=i;
p=(WORD far*)ROM+3;
p=(WORD far*)MK_FP(0xf000, *p);
num= *p;
p=(WORD far*)ROM+5;
num=num- *p;
for(i=0;i<num;i++)
sum+=rbyte(0x40+i);
}
wbyte(0x3f, sum&0xff);
wbyte(0x3e, sum>>8);
return sum;
}
//calculate checksum of mrbios, part addr of 10 to 3e, save to 3f
int write_mrsum()
{
BYTE mask[6]={
0x7f,0xf8,0x3f,0xff,0xf8,0x0a
} ;
BYTE v,cx;
register unsigned char sum=0x1f;
int i,addr;
addr=0x10;
for (i=5;i>=0;i--)
{
v=mask[i];
for (cx=0;cx<8;cx++)
{
if (v&1)
sum+= rbyte(addr);
addr++;
v >>=1;
}
}
sum= sum&0x1f;
wbyte(0x3f,sum);
return sum;
}
/*calculate checksum , from addr 10 ot 2d */
void cal_checksum( int checklen)
{
WORD value, sum =0,i;
for (i=0x10 ;i<checklen ;i++)
sum+= rbyte(i);
value=inw(0x3e);
printf("\nSUM (2e)=%-5x (3e)=%-5x\n", sum,value);
wbyte(checklen+1, sum&0xff);
wbyte(checklen, sum>>8);
}
/* Test your MotherBoard BIOS type */
int test_biostype(void)
{
char far *ROM;
WORD i,type;
for(type=0 ;type<sizeof(biosdesc) / sizeof(biosdesc[0]);type++)
for(i=0; i<0xfff0; i++)
{
ROM=(char far *) MK_FP(0xf000,i);
if(! _fstrncmp(ROM, biosdesc[type].name, 5))
return type+1;
}
return 0;
}
/* Calc Security Code of special Password*/
WORD mr_Encrypt(int len)
{
//reference write cmos f000:ea16
asm cld
asm lea si,str
asm mov cx,len
asm mov dx,0xffff
asm mov bx,0x1021
l7200:
asm lodsw
asm push cx
asm mov cl,0x10
l7220:
asm shl ax,1
asm rcl dx,1
asm jae next
asm xor dx,bx
next:
asm loop l7220
asm pop cx
asm loop l7200
return _DX;
//C version
/*
WORD *p=(WORD*)str,ax,cf,df;
BYTE cx;
WORD dx=0xffff,bx=0x1021;
while(*p)
{
ax= *p++;
for(cx=0;cx<0x10;cx++)
{
cf= ax>>15;
ax<<=1;
df=dx&0x8000;
dx=(dx<<1)+cf;
if (df)
dx^=bx;
}
}
return dx;
*/
}
/*Show Current MR BIOS Password String*/
void show_mrpassword()
{
WORD code;
register unsigned char i1,i2;
char i3,i4, tt ,i5=0;
int count=0;
int dest;
char *check[4]={
"Disable","Setup only",
"Powerup & Setup","Bootup & Setup"
};
// 3a 3b is security code
dest=inw(0x3a);
code=rbyte(0x3c)>>6;
printf("Security Code=0x%04X %s\n",dest, check[code]);
printf(" Press Esc to quit\n");
//if no password found , use followed line and run again
// for (i5=0 ;i5<=26,count==0 ;i5++)
{
*(pstr+4)=scan_code[i5];
for (i4=0 ;i4<=26 ;i4++)
{
*(pstr+3)=scan_code[i4];
if( i4==0 && i5)
continue;
for (i3=0 ;i3<=26 ;i3++)
{
*(pstr+2)=scan_code[i3];
if( i3==0 && i4) continue;
for (i2=0 ;i2<=26 ;i2++)
{
*(pstr+1)=scan_code[i2];
if( i2==0 && i3) continue;
for (i1=1 ;i1<=26 ;i1++)
{
*pstr=scan_code[i1];
tt=5;
if (i5==0) tt=4;
if (i4==0) tt=3;
if (i3==0) tt=2;
if (i2==0) tt=1;
code=mr_Encrypt(tt);
if(code==dest)
{
count++;
printf("Password=");
printf("%c%c%c%c%c\n",str[0],str[2],
str[4],str[6],str[8]);
}
if( bioskey(1) && (getch()==27)) return;
}
}
}
}
}
printf("Total %d password\n",count);
}
/* Extend the KEY's scan code */
void mr_ascii2scan_code()
{
int num, i;
num=strlen(str);
for (i=num-1; i>=0; i--)
str[i]=tolower( str[i]);
for (i=num-1; i>=0; i--)
if( str[i]<='9')
*(int*)(str+2*i)=scan_code[str[i]-'0'+26];
else
*(int*)(str+2*i)=scan_code[str[i]-'a'+1];
*(str+2*num)=0;
}
//change password for mr bios
void change_mrpassword(char *pass)
{
int code;
printf("NewPassword=%s\n",pass);
strcpy(str,pass);
mr_ascii2scan_code();
code=mr_Encrypt(strlen(str)/2);
printf("Security Code=0x%04X\n", code);
// 3a 3b save security code
outw(0x3a,code);
// calculate check sum 2e & 3f
write_mrsum();
return;
}
//get scancode of password for DECpc
//addr 58-5E save password
void dec_unEncrypt(char *pass)
{
int crc=0;
BYTE cx,c;
for ( cx=0;cx<7;cx++)
{
c=rbyte(0x58+cx);
_CL=7-cx;
_AL=c;
asm rol al,cl
c= _AL;
c ^=0xaa;
crc=crc+c;
pass[cx]=c;
if (c==0) break;
}
if (crc != rbyte(0x5f))
printf("password CRC error \n");
}
//change password for DECpc
void change_dec_password(char *pass)
{
int crc=0,cx;
BYTE c,i,*p;
printf("NewPassword=%s\n",pass);
p=(BYTE*)scan_code;
//translate form ascii to scancode
for ( cx=0;cx<7;cx++)
{
c=tolower(pass[cx]);
for (i=1;i<=36;i++)
if(c==p[i*2])
break;
if(i<=36)
pass[cx]=p[i*2+1];
else
pass[cx]=0;
}
for ( cx=0;cx<7;cx++)
{
c=pass[cx];
crc=crc+c;
c ^=0xaa;
_CL=7-cx;
_AL=c;
asm ror al,cl
c=_AL;
wbyte(0x58+cx,c);
if (pass[cx]==0)
break;
}
wbyte(0x5f, crc );
return;
}
/* Show Current DECpc Password String */
void show_dec_password()
{
BYTE ch,*p=(char*)scan_code;
BYTE *pstr=str;
int i, maxc= 36;
str[7]=0;
dec_unEncrypt( str);
//translate from scancode to ascii
while((ch= *pstr)!=0)
{
for (i=1;i<=maxc;i++)
if(ch==p[i*2+1])
break;
*pstr= p[i*2];
pstr++;
}
printf("Password=%s\n",str);
return ;
}
char AMI_unEncrypt( char c1,char c2)
{
//C version of AMI_unEncrypt
/*
BYTE num[]={
0,1,1,2
};
int di=0,c;
do{
c=num[key>>6]+num[key&3];
if (c&1)
key=0x80+(key>>1);
else
key>>=1;
di++;
}while(key!=c2);
return di; */
asm xor di,di
asm mov bl,c1
asm mov cl,c2
lab1:
asm test bl,0xc3
asm jpe lab2
asm stc
lab2:
asm rcr bl,1
asm inc di
asm cmp bl,cl
asm jne lab1:
return _DI;
}
unsigned char ami_Encrypt(BYTE t, BYTE key)
{
//C version of Encrypt
/*
BYTE num[]={
0,1,1,2
};
BYTE c;
while(t--){
c=num[key>>6]+num[key&3];
if (c&1)
key=0x80+(key>>1);
else
key>>=1;
}
return key;*/
asm mov al,t
asm mov bl,key
mark1:
asm test bl,0xc3
asm jpe mark2
asm stc
mark2:
asm rcr bl,1
asm dec al
asm jnz mark1
asm mov key,bl
return key;
}
/*change password for ami bios*/
//0x38-3d password code 0x37 initial value
void change_ami_password(char *pass)
{
BYTE code[8];
char *p=pass;
int i=0;
printf("NewPassword=%s\n",pass);
code[0]= 0x80;
while( *p && i++<6)
code[i]= ami_Encrypt( *p++,code[i-1]);
if (i<6)
code[++i]=0;
do
wbyte(0x37+i,code[i] );
while(i-->=0);
write_amisum();
}
/* Show AMI Password String */
void show_ami_password()
{
int i, length;
static BYTE secret[7];
for(length=0; length<7; length++)
secret[length] = rbyte(0x37+length);
secret[0] &= 0xf0;
for(i=0; i<7 ,secret[i+1]>0; i++)
str[i] = AMI_unEncrypt(secret[i], secret[i+1]);
str[i+1]=0;
if (secret[1]==0)
printf("No password\n");
else
printf("Password=%s\n",str);
}
--
jesse (捷思)
潇洒逛一回
※ 修改:.haojs 于 Sep 5 19:16:16 修改本文.[FROM: bbs.hit.edu.cn]
--
※ 转寄:.武汉白云黄鹤站 bbs.whnet.edu.cn.[FROM: bbs.hit.edu.cn]
--
☆ 来源:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: haojs.bbs@bbs.whnet.]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:209.557毫秒