使用一个比较古老的程序软件,发现使用的数据库是 mdb 格式,于是想看看数据库设计是什么样的。双击显示需要密码。这个 。。。 。。。 看看有没有公开密码吧。
很老的软件了,mdb 的版本也不确定是哪个版本了,发现了破解密码的文章,不过是要用到VB6的,VB相关的知识早就忘光光了。不过 JAVA倒是一直在开发。
把 VB 的代码 java 化就好了呀。自己写?太麻烦了,现在AI这么方便,当然是用 AI啦。
复制VB的代码给AI工具,几秒钟就有结果了。
结果如下:
public class MdbPasswordDecoder {
// Access 2000/2002的异或源码
private static final byte[] PASS_SOURCE_2K = {
(byte)0xa1, (byte)0xec, (byte)0x7a, (byte)0x9c,
(byte)0xe1, (byte)0x28, (byte)0x34, (byte)0x8a,
(byte)0x73, (byte)0x7b, (byte)0xd2, (byte)0xdf,
(byte)0x50
};
// Access 97的异或源码
private static final byte[] PASS_SOURCE_97 = {
(byte)0x86, (byte)0xfb, (byte)0xec, (byte)0x37,
(byte)0x5d, (byte)0x44, (byte)0x9c, (byte)0xfa,
(byte)0xc6, (byte)0x5e, (byte)0x28, (byte)0xe6,
(byte)0x13
};
public static void main(String[] args) {
createAndShowGUI();
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("MDB密码解码器");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 300);
frame.setLayout(null);
JTextField pathField = new JTextField();
pathField.setBounds(20, 20, 350, 25);
JButton selectButton = new JButton("选择文件");
selectButton.setBounds(380, 20, 90, 25);
JTextField versionField = new JTextField();
versionField.setBounds(20, 60, 450, 25);
versionField.setEditable(false);
JTextField passwordField = new JTextField();
passwordField.setBounds(20, 100, 450, 25);
passwordField.setEditable(false);
selectButton.addActionListener(e -> {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
public boolean accept(File f) {
return f.isDirectory() || f.getName().toLowerCase().endsWith(".mdb");
}
public String getDescription() {
return "Access Database (*.mdb)";
}
});
if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
pathField.setText(selectedFile.getAbsolutePath());
getMdbPass(selectedFile, versionField, passwordField);
}
});
frame.add(pathField);
frame.add(selectButton);
frame.add(versionField);
frame.add(passwordField);
frame.setVisible(true);
}
private static void getMdbPass(File file, JTextField versionField, JTextField passwordField) {
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
// 读取版本信息
raf.seek(0x14);
int ver = raf.read();
// 读取加密标志
raf.seek(0x62);
byte encrypFlag = raf.readByte();
// 读取加密后的密码
raf.seek(0x42);
byte[] passStrTemp = new byte[26];
raf.read(passStrTemp);
String mdbVersion;
StringBuilder mdbPassword = new StringBuilder();
if (ver < 1) {
// Access 97
mdbVersion = "Access 97";
if ((passStrTemp[0] ^ PASS_SOURCE_97[0]) == 0) {
mdbPassword.append("密码为空!");
} else {
for (int j = 0; j < 13; j++) {
mdbPassword.append((char)(passStrTemp[j] ^ PASS_SOURCE_97[j]));
}
}
} else {
// Access 2000 or 2002
mdbVersion = "Access 2000 or 2002";
for (int j = 0; j < 13; j++) {
byte t1;
if (j % 2 == 0) {
t1 = (byte)(0x13 ^ encrypFlag ^ passStrTemp[j * 2] ^ PASS_SOURCE_2K[j]);
} else {
t1 = (byte)(passStrTemp[j * 2] ^ PASS_SOURCE_2K[j]);
}
mdbPassword.append((char)(t1 & 0xFF));
}
}
// 检查密码是否有效
if (mdbPassword.length() > 0 &&
(mdbPassword.charAt(0) < 0x20 || mdbPassword.charAt(0) > 0x7e)) {
mdbPassword = new StringBuilder("密码为空!");
}
versionField.setText("版本: " + mdbVersion);
passwordField.setText("密码: " + mdbPassword.toString());
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "文件读取错误:" + ex.getMessage());
}
}
运行起来截图如下:
效果还不错。