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
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
|
|
|
|
}
|
|
|
|
}
|
|
|