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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace Apewer.Internals
  7. {
  8. internal static class AccessHelper
  9. {
  10. [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
  11. static extern void RtlMoveMemory(ref double des, int src, int count);
  12. internal const string JetOleDB4 = "microsoft.jet.oledb.4.0";
  13. internal const string AceOleDB12 = "microsoft.ace.oledb.12.0";
  14. #region 获取密码
  15. public static string[] GetPassword(string path)
  16. {
  17. var list = new List<string>();
  18. if (File.Exists(path))
  19. {
  20. FileStream file = null;
  21. try
  22. {
  23. file = File.OpenRead(path);
  24. GetPassword(list, file, GetPassword_1);
  25. GetPassword(list, file, GetPassword_2);
  26. }
  27. catch { }
  28. if (file != null)
  29. {
  30. file.Close();
  31. file.Dispose();
  32. }
  33. }
  34. return list.ToArray();
  35. }
  36. static void GetPassword(List<string> list, FileStream file, Func<FileStream, string> func)
  37. {
  38. file.Position = 0L;
  39. file.Seek(0L, SeekOrigin.Begin);
  40. try
  41. {
  42. var password = func(file);
  43. if (string.IsNullOrEmpty(password)) return;
  44. if (list.Contains(password)) return;
  45. list.Add(password);
  46. }
  47. catch { }
  48. }
  49. #region 方式 1
  50. static unsafe string GetPassword_1(FileStream file)
  51. {
  52. var password = "";
  53. // 检查格式版本标记,0 为 Access 97,1 为 Accessor 2000。
  54. file.Seek(0x14, SeekOrigin.Begin);
  55. var verFlag = (byte)file.ReadByte();
  56. // 检查文件类型标记,不含有标记的文件无法识别。
  57. file.Seek(0x4, SeekOrigin.Begin);
  58. var bs = new byte[15];
  59. file.Read(bs, 0, 15);
  60. var FileFlag = Encoding.Default.GetString(bs);
  61. if (FileFlag != "Standard Jet DB") return null;
  62. // 读取加密区。
  63. file.Seek(0x18, SeekOrigin.Begin);
  64. var originBytes = new byte[128];
  65. file.Read(originBytes, 0, 128);
  66. var encryptedKey = new byte[258];
  67. var dbl = 0D;
  68. encryptedKey = GetEncryptedString();
  69. originBytes = GetKey(encryptedKey, originBytes);
  70. double* dblAdress = &dbl;
  71. fixed (byte* bskeysAdress = &originBytes[0]) RtlMoveMemory(ref *dblAdress, (int)bskeysAdress + 90, 8);
  72. var passData = new long[19];
  73. for (int j = 0; j < 19; j++)
  74. {
  75. passData[j] = (long)originBytes[j * 2 + 42] + 256 * (long)(originBytes[j * 2 + 43]);
  76. if (j % 2 == 0) passData[j] = passData[j] ^ (int)dbl; // dbl = 42416;
  77. if (passData[j] != 0) password += (char)passData[j];
  78. }
  79. return password;
  80. }
  81. static byte[] GetEncryptedString()
  82. {
  83. long temp1 = 0;
  84. long temp2 = 0;
  85. long temp3 = 0;
  86. long temp4 = 0;
  87. long temp5 = 0;
  88. byte[] encryptedRet = new byte[258];
  89. byte[] encriptedKey = new byte[4];
  90. long temp = 0x800000FF;
  91. encriptedKey[0] = 0xC7;
  92. encriptedKey[1] = 0xDA;
  93. encriptedKey[2] = 0x39;
  94. encriptedKey[3] = 0x6B;
  95. for (int i = 0; i < 256; i++)
  96. {
  97. encryptedRet[i] = (byte)i;
  98. }
  99. for (int i = 0; i < 256; i++)
  100. {
  101. temp1 = temp2;
  102. temp1 = encriptedKey[temp1];
  103. temp4 = encryptedRet[i];
  104. temp1 = temp1 + temp4;
  105. temp4 = temp3;
  106. temp1 = temp1 + temp4;
  107. temp1 = (byte)((byte)temp1 & (byte)(temp));
  108. temp3 = temp1;
  109. temp1 = encryptedRet[i];
  110. temp5 = temp1;
  111. temp1 = temp3;
  112. temp1 = encryptedRet[temp1];
  113. encryptedRet[i] = (byte)temp1;
  114. temp4 = temp3;
  115. encryptedRet[temp4] = (byte)temp5;
  116. temp1 = temp2;
  117. temp1 = temp1 + 1;
  118. temp4 = temp1 % 4;
  119. temp2 = temp4;
  120. }
  121. return encryptedRet;
  122. }
  123. static byte[] GetKey(byte[] encryptedKey, byte[] originBytes)
  124. {
  125. long temp1 = 0;
  126. long temp2 = 0;
  127. long temp3 = 0;
  128. long temp4 = 0;
  129. long temp5 = 0;
  130. long temp6 = 0;
  131. long temp7 = 0;
  132. long temp8 = 0;
  133. temp4 = encryptedKey[0x100];
  134. temp1 = encryptedKey[0x101];
  135. long temp = 0x800000FF;
  136. temp1 = 0;
  137. for (int i = 1; i < 129; i++)
  138. {
  139. temp4 = temp4 + 1;
  140. temp4 = (byte)((byte)temp4 & (byte)(temp));
  141. temp3 = (byte)((byte)temp4 & (byte)(0xFF));
  142. temp5 = encryptedKey[temp3];
  143. temp1 = (byte)((byte)temp1 & (byte)(0xFF));
  144. temp5 = temp5 + temp1;
  145. temp1 = (byte)((byte)temp5 & (byte)(temp));
  146. temp6 = encryptedKey[temp4];
  147. temp5 = encryptedKey[temp1];
  148. encryptedKey[temp3] = (byte)temp5;
  149. temp2 = temp1;
  150. encryptedKey[temp2] = (byte)temp6;
  151. temp5 = encryptedKey[temp3];
  152. temp3 = encryptedKey[(byte)((byte)temp1 & (byte)(0xFF))];
  153. temp5 = temp5 + temp3;
  154. temp5 = (byte)((byte)temp5 & (byte)(temp)); ;
  155. temp7 = temp5;
  156. temp3 = temp8;
  157. temp5 = encryptedKey[temp5];
  158. originBytes[temp3] = (byte)(originBytes[temp3] ^ (byte)temp5);
  159. temp8 = temp8 + 1;
  160. }
  161. encryptedKey[0x100] = (byte)temp4;
  162. encryptedKey[0x101] = (byte)temp1;
  163. return originBytes;
  164. }
  165. #endregion
  166. #region 方式 2
  167. static string GetPassword_2(FileStream file)
  168. {
  169. var password = "";
  170. // 未加密的文件 0x42 开始至 0x61 之前的每间隔一字节的数值。
  171. var baseByte = new byte[] { 0xbe, 0xec, 0x65, 0x9c, 0xfe, 0x28, 0x2b, 0x8a, 0x6c, 0x7b, 0xcd, 0xdf, 0x4f, 0x13, 0xf7, 0xb1, };
  172. // 标志 0x62 处的数值。
  173. byte flagByte = 0x0c;
  174. // 检查格式版本标记,0 为 Access 97,1 为 Accessor 2000。
  175. file.Seek(0x14, SeekOrigin.Begin);
  176. byte verFlag = (byte)file.ReadByte();
  177. file.Seek(0x42, SeekOrigin.Begin);
  178. byte[] bs = new byte[33];
  179. if (file.Read(bs, 0, 33) != 33) return "";
  180. byte flag = (byte)(bs[32] ^ flagByte);
  181. for (int i = 0; i < 16; i++)
  182. {
  183. byte b = (byte)(baseByte[i] ^ (bs[i * 2]));
  184. // Access 2000
  185. if (i % 2 == 0 && verFlag == 1) b ^= flag;
  186. if (b > 0)
  187. {
  188. var ch = (char)b;
  189. password += ch;
  190. }
  191. }
  192. return password;
  193. }
  194. #endregion
  195. #endregion
  196. }
  197. }