You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
7.4 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Apewer.Internals
{
internal static class AccessHelper
{
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
static extern void RtlMoveMemory(ref double des, int src, int count);
internal const string JetOleDB4 = "microsoft.jet.oledb.4.0";
internal const string AceOleDB12 = "microsoft.ace.oledb.12.0";
#region 获取密码
public static string[] GetPassword(string path)
{
var list = new List<string>();
if (File.Exists(path))
{
FileStream file = null;
try
{
file = File.OpenRead(path);
GetPassword(list, file, GetPassword_1);
GetPassword(list, file, GetPassword_2);
}
catch { }
if (file != null)
{
file.Close();
file.Dispose();
}
}
return list.ToArray();
}
static void GetPassword(List<string> list, FileStream file, Func<FileStream, string> func)
{
file.Position = 0L;
file.Seek(0L, SeekOrigin.Begin);
try
{
var password = func(file);
if (string.IsNullOrEmpty(password)) return;
if (list.Contains(password)) return;
list.Add(password);
}
catch { }
}
#region 方式 1
static unsafe string GetPassword_1(FileStream file)
{
var password = "";
// 检查格式版本标记,0 为 Access 97,1 为 Accessor 2000。
file.Seek(0x14, SeekOrigin.Begin);
var verFlag = (byte)file.ReadByte();
// 检查文件类型标记,不含有标记的文件无法识别。
file.Seek(0x4, SeekOrigin.Begin);
var bs = new byte[15];
file.Read(bs, 0, 15);
var FileFlag = Encoding.Default.GetString(bs);
if (FileFlag != "Standard Jet DB") return null;
// 读取加密区。
file.Seek(0x18, SeekOrigin.Begin);
var originBytes = new byte[128];
file.Read(originBytes, 0, 128);
var encryptedKey = new byte[258];
var dbl = 0D;
encryptedKey = GetEncryptedString();
originBytes = GetKey(encryptedKey, originBytes);
double* dblAdress = &dbl;
fixed (byte* bskeysAdress = &originBytes[0]) RtlMoveMemory(ref *dblAdress, (int)bskeysAdress + 90, 8);
var passData = new long[19];
for (int j = 0; j < 19; j++)
{
passData[j] = (long)originBytes[j * 2 + 42] + 256 * (long)(originBytes[j * 2 + 43]);
if (j % 2 == 0) passData[j] = passData[j] ^ (int)dbl; // dbl = 42416;
if (passData[j] != 0) password += (char)passData[j];
}
return password;
}
static byte[] GetEncryptedString()
{
long temp1 = 0;
long temp2 = 0;
long temp3 = 0;
long temp4 = 0;
long temp5 = 0;
byte[] encryptedRet = new byte[258];
byte[] encriptedKey = new byte[4];
long temp = 0x800000FF;
encriptedKey[0] = 0xC7;
encriptedKey[1] = 0xDA;
encriptedKey[2] = 0x39;
encriptedKey[3] = 0x6B;
for (int i = 0; i < 256; i++)
{
encryptedRet[i] = (byte)i;
}
for (int i = 0; i < 256; i++)
{
temp1 = temp2;
temp1 = encriptedKey[temp1];
temp4 = encryptedRet[i];
temp1 = temp1 + temp4;
temp4 = temp3;
temp1 = temp1 + temp4;
temp1 = (byte)((byte)temp1 & (byte)(temp));
temp3 = temp1;
temp1 = encryptedRet[i];
temp5 = temp1;
temp1 = temp3;
temp1 = encryptedRet[temp1];
encryptedRet[i] = (byte)temp1;
temp4 = temp3;
encryptedRet[temp4] = (byte)temp5;
temp1 = temp2;
temp1 = temp1 + 1;
temp4 = temp1 % 4;
temp2 = temp4;
}
return encryptedRet;
}
static byte[] GetKey(byte[] encryptedKey, byte[] originBytes)
{
long temp1 = 0;
long temp2 = 0;
long temp3 = 0;
long temp4 = 0;
long temp5 = 0;
long temp6 = 0;
long temp7 = 0;
long temp8 = 0;
temp4 = encryptedKey[0x100];
temp1 = encryptedKey[0x101];
long temp = 0x800000FF;
temp1 = 0;
for (int i = 1; i < 129; i++)
{
temp4 = temp4 + 1;
temp4 = (byte)((byte)temp4 & (byte)(temp));
temp3 = (byte)((byte)temp4 & (byte)(0xFF));
temp5 = encryptedKey[temp3];
temp1 = (byte)((byte)temp1 & (byte)(0xFF));
temp5 = temp5 + temp1;
temp1 = (byte)((byte)temp5 & (byte)(temp));
temp6 = encryptedKey[temp4];
temp5 = encryptedKey[temp1];
encryptedKey[temp3] = (byte)temp5;
temp2 = temp1;
encryptedKey[temp2] = (byte)temp6;
temp5 = encryptedKey[temp3];
temp3 = encryptedKey[(byte)((byte)temp1 & (byte)(0xFF))];
temp5 = temp5 + temp3;
temp5 = (byte)((byte)temp5 & (byte)(temp)); ;
temp7 = temp5;
temp3 = temp8;
temp5 = encryptedKey[temp5];
originBytes[temp3] = (byte)(originBytes[temp3] ^ (byte)temp5);
temp8 = temp8 + 1;
}
encryptedKey[0x100] = (byte)temp4;
encryptedKey[0x101] = (byte)temp1;
return originBytes;
}
#endregion
#region 方式 2
static string GetPassword_2(FileStream file)
{
var password = "";
// 未加密的文件 0x42 开始至 0x61 之前的每间隔一字节的数值。
var baseByte = new byte[] { 0xbe, 0xec, 0x65, 0x9c, 0xfe, 0x28, 0x2b, 0x8a, 0x6c, 0x7b, 0xcd, 0xdf, 0x4f, 0x13, 0xf7, 0xb1, };
// 标志 0x62 处的数值。
byte flagByte = 0x0c;
// 检查格式版本标记,0 为 Access 97,1 为 Accessor 2000。
file.Seek(0x14, SeekOrigin.Begin);
byte verFlag = (byte)file.ReadByte();
file.Seek(0x42, SeekOrigin.Begin);
byte[] bs = new byte[33];
if (file.Read(bs, 0, 33) != 33) return "";
byte flag = (byte)(bs[32] ^ flagByte);
for (int i = 0; i < 16; i++)
{
byte b = (byte)(baseByte[i] ^ (bs[i * 2]));
// Access 2000
if (i % 2 == 0 && verFlag == 1) b ^= flag;
if (b > 0)
{
var ch = (char)b;
password += ch;
}
}
return password;
}
#endregion
#endregion
}
}