www.pudn.com > 密码探针1.0源程序 > _CMOS.CPP


//             _____________________________________ 
//            |                                     | 
//            |               文件描述              | 
// ___________|_____________________________________|___________ 
// 
// 文件名:_CMOS.CPP 
// 作者:阿卓 
// 内容:清除和解码CMOS密码的C++程序代码段。 
// 声明:本文件及其相关文档内容可以自由使用、修改和传播,并可用 
//       于任何商业和非商业目的。对于使用本文件及其相关文档内容 
//       而产生的任何后果,作者概不负责。 
// 
// 技术要点之一: 
//     使用了在WINDOWS 9X和NT环境下直接读写端口的方法。由于 
//     WINDOWS(特别是WINDOWS NT)对硬件直接访问设置了限制,使得端 
//     口的读写难以实现。于是就寻寻觅觅,终于在互联网上觅得一共 
//     享软件名曰:NTPort Library。此软件提供WINDOWS 9X/NT环境下 
//     的直接端口读写而不需要写DDK程序。使用本程序时,需要将 
//     ntport.dll拷到system(NT:system32)目录下,如果是NT,还要将 
//     zntport.sys拷贝到system32目录下。 
// 
// 技术要点之二: 
//     CMOS密码解码算法。 
//     CMOS密码的生成算法是:将用户输入的密码字符串中的字符c按先 
//     后顺序重复这样的操作(sum是最终存储到CMOS中的一个16位值, 
//     初值为0): 
//         sum = sum + c; 
//         sum 按位循环左移2位(最后一个字符不左移) 
//     我的解密算法是: 
//         找到一个合适的c(c的低2位与sum的低2位相同) 
//         sum减去c 
//         sum右移2位 
//         重复上述过程,递归求解,遇到无解时回溯,直至sum的值 
//         落到一个合适的范围之内(可显示的字符范围之内) 
// 
// 当前版本:v1.4 
// 最后更新日期:11/7/2001 
// 
// 版本历史: 
// v1.0 
//     算法初步成型,探测结果为纯数字,没有优化到可键入字符集 
//     中,未采用NTPort Library,运行于MS-DOS方式下。 
// v1.1 
//     将探测结果优化到可键入的字符集中,并移植到WINDOWS 9X环境 
//     下。 
// v1.2 
//     增加直接清除功能。 
// v1.3 
//     采用NTPort Library,使得程序能在NT架构环境中能操作端口。 
// v1.4 
//     当前版本,优化探测结果,得到的密码更容易键入。增加详细注 
//     释。 
// 
// _______________________文件描述结束__________________________ 
 
 
// 这是MFC程序需要的头文件,以支持预编译头文件 
#include "stdafx.h" 
 
// 这是NTPort Library的头文件 
// 要使用这个库,需要在Project/Settings.../Link中添加ntport\ntport.lib 
#include "ntport\\ntport.h" 
 
//      ___________ 
// ____|  Clear()  |____________________________________________ 
// 功能:向CMOS的一些端口输出一些无意义数据,使得CMOS的校验和出 
//       错,导致CMOS自动载入缺省设置,恢复到无密码状态。 
// 参数详解:无参数 
// 返回值:无 
// _____________________________________________________________ 
void Clear(void) 
{ 
	// 还记得使用DEBUG来破CMOS密码的日子吗?这个原理是一样的 
	Outport(0x70, 0x21); 
	Outport(0x71, 0x20); 
 
	// 这是个额外方案,以确保清除成功 
	Outport(0x70, 0x2e); 
	Outport(0x71, 0x00); 
	Outport(0x70, 0x2f); 
	Outport(0x71, 0x00); 
} 
// ____End of Clear()___________________________________________ 
 
//      _________________ 
// ____|  GetPortData()  |______________________________________ 
// 功能:从CMOS的0x1c和0x1d端口读入一个16位的加密状态的密码数据。 
//       可能不同的BIOS有不同的端口,这两个端口适用于普通的AWARD 
//       BIOS,这是本软件为普通AWARD BIOS版的原因,也是导致解密不 
//       成功或者探测的密码无效之类问题的原因,可以在将来版本制作 
//       多种解决方案。 
// 参数详解:无参数 
// 返回值:一个16位的加密状态的CMOS密码数据 
// _____________________________________________________________ 
unsigned int GetPortData(void) 
{ 
	unsigned int	Data; 
	unsigned char	Data1, Data2; 
 
	Outport(0x70, 0x1c); 
	Data1 = (unsigned char)Inport(0x71); 
 
	Outport(0x70, 0x1d); 
	Data2 = (unsigned char)Inport(0x71); 
 
	Data = (Data2 << 8) | Data1; 
 
	return Data; 
} 
// ____End of GetPortData()_____________________________________ 
 
// 这是一个字符表,排在前面的字符比较容易键入,所以先试探此类字符 
// 这是易键入性优化的关键所在。 
static char CharSet[] = { 
	'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',  
	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',  
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',  
	'`', '-', '=', '[', ']', '\\', ';', '\'', ',', '.', '/',  
	'~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '{', '}', '|', ':', '"', '<', '>', '?' 
}; 
 
//      _____________ 
// ____|  MinChar()  |__________________________________________ 
// 功能:内部使用函数,它返回在字符集中最小的字符。 
// 参数详解:无参数 
// 返回值:在字符集中最小的字符 
// _____________________________________________________________ 
static char MinChar(void) 
{ 
	int		i; 
	char	Min = 127; 
	 
	for(i = 0; i < sizeof(CharSet); i ++) 
		if(CharSet[i] < Min) 
			Min = CharSet[i]; 
 
	return Min; 
} 
// ____End of MinChar()_________________________________________ 
 
//      _____________ 
// ____|  MaxChar()  |__________________________________________ 
// 功能:内部使用函数,它返回在字符集中最大的字符。 
// 参数详解:无参数 
// 返回值:在字符集中最大的字符 
// _____________________________________________________________ 
static char MaxChar(void) 
{ 
	int		i; 
	char	Max = 0; 
	 
	for(i = 0; i < sizeof(CharSet); i ++) 
		if(CharSet[i] > Max) 
			Max = CharSet[i]; 
 
	return Max; 
} 
// ____End of MaxChar()_________________________________________ 
 
//      _________________ 
// ____|  IsInCharSet()  |______________________________________ 
// 功能:内部使用函数,它判断某个字符是否在字符集内。 
// 参数详解: 
// char c 
//     待判断的字符 
// 返回值: 
//     0 - 不在字符集内 
//     1 - 在字符集内 
// _____________________________________________________________ 
static int IsInCharSet(char c) 
{ 
	int		i; 
 
	for(i = 0; i < sizeof(CharSet); i ++) 
		if(CharSet[i] == c) 
			return 1; 
 
	return 0; 
} 
// ____End of IsInCharSet()_____________________________________ 
 
//      ____________ 
// ____|  Decode()  |___________________________________________ 
// 功能:核心解码函数,递归,回溯。 
// 参数详解: 
// unsigned int SourceCode 
//     16位的加密状态的CMOS密码数据 
// unsigned char *Password 
//     存储解码结果的缓冲区,注意:结果是倒序存储的 
// 返回值: 
//     -1 - 解码失败 
//     0 - 解码成功 
// _____________________________________________________________ 
int Decode(unsigned int SourceCode, unsigned char *Password) 
{ 
	unsigned int	i, TempCode, Mask = 0x03; 
	unsigned char	LastTwoBits; 
 
	if(SourceCode < (unsigned int)MinChar()) 
		// 所剩SourceCode不合法,回溯 
		return -1; 
 
	if(SourceCode < (unsigned int)MaxChar()) 
		if(IsInCharSet(SourceCode)) 
		{ 
			// 所剩SourceCode合法,探密完成! 
			*Password = SourceCode; 
			return 0; 
		} 
 
	// 取出SourceCode的低2位 
	LastTwoBits = SourceCode & Mask; 
	for(i = 0; i < sizeof(CharSet); i ++) 
	{ 
		// 若低2位相同才继续探测 
		if(((CharSet[i] ^ LastTwoBits) & Mask) == 0) 
		{ 
			*Password = CharSet[i]; 
			TempCode = (SourceCode - CharSet[i]) >> 2; 
			if(Decode(TempCode, Password + 1) == 0) 
				return 0; 
		} 
	} 
 
	//向前探索失败,回溯 
	return -1; 
} 
// ____End of Decode()__________________________________________