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(); 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 list, FileStream file, Func 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 } }