📄 0504001.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title></title>
<link rel="stylesheet" type="text/css" href="../../vckbase.css">
</head>
<body>
<div align="justify">
<table border="0" width="100%" class="font" height="57">
<tr>
<td width="27%" height="6" class="bigfont" bgcolor="#B8CFE7" align="center" bordercolor="#800080">
<font color="#800080">VC知识库(五)</font>
</td>
<td width="73%" height="6" class="bigfont" bgcolor="#B8CFE7" align="center" bordercolor="#800080">
<font color="#800080">vckbase</font>
</td>
</tr>
<tr>
<td width="100%" height="4" class="header" valign="top" align="center" colspan="2">
<hr>
</td>
</tr>
<tr>
<td width="100%" height="17" class="header" valign="top" align="center" colspan="2">
<FONT color=#0000c0>
Win95/98下对软盘的直接读写</FONT>
<p><FONT color=#b00e>---利用32 Bits Windows 下“合法”的中断调用</FONT>
</td>
</tr>
<tr>
<td width="100%" height="17" class="info" align="center" colspan="2">
北京电信局运行维护部技术中心 <BR>邰 锋
</td>
</tr>
<tr>
<td width="100%" height="22" class="font" colspan="2">
<hr>
</td>
</tr>
<tr>
<td width="100%" height="5" class="font" colspan="2">
<CENTER><FONT color=#0000c0>
</FONT><FONT color=#b00e>
</FONT>
</CENTER>
<P><FONT color=#ffffff>----</FONT> 关于在 Win95/98
下对软盘(硬盘也可,读者可在读完后自行写出)的直接读写,笔者见过许多,但多数是利用 95/98 的虚拟8086
的方式。前些时期,笔者为了将即将完工的一软件加密,采用了软盘加密方式。利用的是Win95/98 的API ,感觉不错特向大家介绍:
<P><FONT color=#ffffff>----</FONT> Windows 95/98 屏蔽掉了大多数中断调用。但其中的一部分可以用
API : DeviceIoControl 来完成。该API 也将是Windows 2000 的合法函数。在Windows 95/98
下对软盘的直接读写并不象在NT下那么自然,它要通过调用一个VxD 来完成中断调用,这是因为MS—Windows 的“怪癖”,这是众所周知的。
<P><FONT color=#ffffff>----</FONT> 下面是加密软盘的制作思想和程式。
<P><FONT color=#ffffff>----</FONT> 制作思想:
由程序员定义一组绝对扇区号,最好不要连续,作为目标扇区。将你的密钥或序列号通过一定的加密算法,以某种方式写入这组绝对扇区。以实现加密。
<P><FONT color=#ffffff>----</FONT> 加密软盘的制作程式: <XMP>// staticSectorNo 即为绝对扇区号,这是需要保密的。
const UINT staticSectorNo[] = {
12, //0
3, //1
5, //2
7, //3
9, //4
11, //5
13, //6
17, //7
18, //8
23, //9
27, //10
31, //11
37, //12
41, //13
43, //14
47, //15
51, //16 //skip some number
71, //17
113, //18
118, //19 //last one is not a 素数
0,
};
///////////////////////////////////
//下面是可以进行的几种中断调用。
#define VWIN32_DIOC_DOS_IOCTL 1
#define VWIN32_DIOC_DOS_INT25 2
//Performs the Absolute Disk Read command
(Interrupt 25h)
#define VWIN32_DIOC_DOS_INT26 3
//Performs the Absolute Disk Write command
(Interrupt 26h)
#define VWIN32_DIOC_DOS_INT13 4
//Performs Interrupt 13h commands
#define VWIN32_DIOC_DOS_DRIVEINFO 6
//Performs Interrupt 21h Function 730X
//commands. This value is supported in Windows 95
// OEM Service Release 2 and later
////////////////////////////////////////////
//下面可以被看作是模拟的32位寄存器。
typedef struct _DEVIOCTL_REGISTERS
{
DWORD reg_EBX;
DWORD reg_EDX;
DWORD reg_ECX;
DWORD reg_EAX;
DWORD reg_EDI;
DWORD reg_ESI;
DWORD reg_Flags;
} DEVIOCTL_REGISTERS, *PDEVIOCTL_REGISTERS;
/////////////////////////////////////////////
//下面获得前述所说的VxD句柄。
HANDLE hDevice = CreateFile("\\\\.\\vwin32",
//该字符串是固定的,不可更改。
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
////////////////////////////////////////////
//下面是笔者定义的用户常量和数据结构:
#defineMAX_SECTEORWRITEBYTE 128
#defineMAX_SECTEORREADBYTE 1024
//max sector is 1024
enum
{
FIXED_KEYLEN = 20,
FIXED_USERIDLEN = 4,
};
structEncryptInfoData
{
BYTEbtKey[FIXED_KEYLEN];
BYTEbtUserID[FIXED_USERIDLEN];
EncryptInfoData()
{
memset(btKey,NULL,sizeof(btKey));
memset(btUserID,NULL,sizeof(btUserID));
}
};
//下面对用户的密钥通过笔者选定的加密算法,
写入绝对扇区:
BOOLSetFloppyEncryptData
(const EncryptInfoData* pEncDataBuf)
{
DWORD cb = 0;
BOOL bResult = TRUE;
DEVIOCTL_REGISTERS reg;
memset(®,NULL,sizeof(reg));
PDEVIOCTL_REGISTERS preg = ®
if(hDevice == NULL
||hDevice == (HANDLE) INVALID_HANDLE_VALUE)
return FALSE;
if(pEncDataBuf == NULL)
return FALSE;
for(int iSub = 0; iSub < FIXED_KEYLEN ; iSub ++)
{
///////////////////////////////////////////
//--下面做一个伪装数组,真数据只是其中的某一个,以下同:
CString strSSS;
char szWrite[MAX_SECTEORWRITEBYTE];
srand( (unsigned)time( NULL ) );
for(int i = 0; i < MAX_SECTEORWRITEBYTE ;i++ )
{
char szBuf[256];
sprintf(szBuf,"%d",rand());
strSSS+= szBuf;
if(strSSS.GetLength() >= MAX_SECTEORWRITEBYTE)
break;
}
strncpy(szWrite,strSSS,MAX_SECTEORWRITEBYTE);
if(staticSectorNo[iSub] == 0 )
break;
//--将真字符放入正确位置。
szWrite[iSub] = pEncDataBuf->btKey[iSub];
//--following use the int 26 to write the
//string to absoluted sector.
// (except partitions > 32M)
//--添充模拟寄存器,这需要程序员熟悉中断入口参数,以下同:
preg->reg_EDI = 0;
preg->reg_ESI = 0;
preg->reg_EAX= 0x0000;
//AL = drive number (00h = A:, 01h = B:, etc)
preg->reg_EBX = (DWORD)szWrite;
//DS:BX -> data to write
preg->reg_ECX = 1;
//CX = number of sectors to write (not FFFFh)
preg->reg_EDX = staticSectorNo[iSub];
//DX = starting logical sector number (0000h
- highest sector on drive)
preg->reg_Flags = 0x8000;
// assume error (carry flag set)
//调用DeviceIoControl ,
其实相当于模拟DOS下的中断调用,以下同:
bResult &= DeviceIoControl(m_hDevice,
VWIN32_DIOC_DOS_INT26,
preg,
sizeof(*preg),
preg,
sizeof(*preg),
&cb,
0);
if(!bResult)
break;
bResult = JudgeInt2526RetCode(preg->reg_EAX);
if(!bResult)
break;
}
for(iSub = 0; iSub < FIXED_USERIDLEN&&bResult ; iSub ++)
{
CString strSSS;
char szWrite[MAX_SECTEORWRITEBYTE];
srand( (unsigned)time( NULL ) );
for(int i = 0; i < MAX_SECTEORWRITEBYTE ;i++ )
{
char szBuf[256];
sprintf(szBuf,"%d",rand());
strSSS+= szBuf;
if(strSSS.GetLength() >= MAX_SECTEORWRITEBYTE)
break;
}
strncpy(szWrite,strSSS,MAX_SECTEORWRITEBYTE);
if(staticUserIDSectorNo[iSub] == 0 )
break;
//--Set the real user ID into the corrected position
szWrite[iSub] =(char) pEncDataBuf->btUserID[iSub];
//--following use the int 26 to write the
//string to absolute sector.
// (except partitions > 32M)
preg->reg_EDI = 0;
preg->reg_ESI = 0;
preg->reg_EAX= 0x0000;
//AL = drive number (00h = A:, 01h = B:, etc)
preg->reg_EBX = (DWORD)szWrite;//DS:BX -> data to write
preg->reg_ECX = 1;
//CX = number of sectors to write (not FFFFh)
preg->reg_EDX = staticUserIDSectorNo[iSub];
//DX = starting logical sector number
(0000h - highest sector on drive)
preg->reg_Flags = 0x8000;
// assume error (carry flag set)
bResult &= DeviceIoControl(m_hDevice,
VWIN32_DIOC_DOS_INT26,
preg,
sizeof(*preg),
preg,
sizeof(*preg),
&cb,
0);
if(!bResult) //
break;
bResult = JudgeInt2526RetCode(preg->reg_EAX);
if(!bResult) //
break;
}
return bResult;
}
///////////////////////////////////////////
//下面是读出数据:
BOOL GetFloppyEncryptData(EncryptInfoData* pEncDataBuf)
{
略。。。。。。
}
///////////////////////////////////////////
BOOL JudgeInt2526RetCode(DWORD dwEAX )
{
略。。。。。。
}
////////////////////////////////////////////
</XMP><FONT color=#ffffff>----</FONT> 读者可以看出,DeviceIoControl
其实是起了一个传递参数的作用,真正的中断调用是由处于Ring0级的VxD程序调用的。关于VxD在此不再赘述。
<P><FONT color=#ffffff>----</FONT> 为了更具加密性,可以对软盘再做一些处理,具体细节和省略的部分请与笔者联系。
</P>
</td>
</tr>
<tr>
<td width="100%" height="12" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="6" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="8" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="17" class="font" colspan="2"></td>
</tr>
</table>
</div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -