前言:本文仅供学习交流,禁止用于非法用途
Access_JDBC30.jar为国人参与制作的jdbc的access驱动,但是免费版存在三个限制
1.查询50次限制
2.查询结果1000条限制
3.插入500次限制
下载地址:http://www.hxtt.com/access.zip
本文用到的工具:IDEA,Eclipse,JBE
一、使用超过限制代码查看异常栈
超过50行查询的代码如下:
package com.jdbc.test1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class hxtt50thselectlimit {
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName("com.hxtt.sql.access.AccessDriver");
conn = (Connection) DriverManager.getConnection("jdbc:Access:///D:/Database1.mdb", "", ""); // 连接数据库
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void select() {
Connection conn = getConnection();
String sql = "select *from usertable";
try {
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql); // 执行SQL语句
while (rs.next()) {
System.out.print(rs.getString("id") + " ");
System.out.print(rs.getString("username") + " ");
System.out.println(rs.getInt("age") + " ");
}
rs.close();
st.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
for(int i=0;i<=60;i++) {
System.out.println("第"+i+"次查询");
select();
}
}
/*
上限1:50次查询上限
若有限制,报错如下
第51次查询
java.sql.SQLException: HXTT Access Version 6.0 For Evaluation Purpose allows executing not more than 50 queries once. You can order commercial version from http://www.hxtt.com .
at com.hxtt.b.am.a(Unknown Source)
at com.hxtt.b.am.if(Unknown Source)
at com.hxtt.sql.b0.a(Unknown Source)
at com.hxtt.sql.b0.if(Unknown Source)
at com.hxtt.sql.b0.a(Unknown Source)
at com.hxtt.sql.an.a(Unknown Source)
at com.hxtt.sql.an.a(Unknown Source)
at com.hxtt.sql.an.if(Unknown Source)
at com.hxtt.sql.an.executeQuery(Unknown Source)
at com.jdbc.test.hxtt50limit.select(hxtt50limit.java:26)
at com.jdbc.test.hxtt50limit.main(hxtt50limit.java:43)*/
}
原版jar在执行到第50次查询时会报异常
这时,我们需要根据其中的异常栈推出其中的报错信息。
二、反编译找调用栈
在Eclipse下可以搜索下载Eclipse Decompiler 插件,里面集成了好几个插件,但是由于这个jar经过了混淆,部分类反编译失败,但是IDEA果然是神器,Procyon反编译不出来的IDEA自带的却能反编译出来。以下教程的行数均以IDEA反编译的行数为准
首先,根据调用栈建立空表如下,每分析一个调用,填充完一行内容
方法
|
调用行
|
实际方法定义
|
参数个数
|
at com.hxtt.b.am.a(Unknown Source)
|
|
|
|
at com.hxtt.b.am.if(Unknown Source)
|
|
|
|
at com.hxtt.sql.b0.a(Unknown Source)
|
|
|
|
at com.hxtt.sql.b0.if(Unknown Source)
|
|
|
|
at com.hxtt.sql.b0.a(Unknown Source)
|
|
|
|
at com.hxtt.sql.an.a(Unknown Source)
|
|
|
|
at com.hxtt.sql.an.a(Unknown Source)
|
|
|
|
at com.hxtt.sql.an.if(Unknown Source)
|
|
|
|
at com.hxtt.sql.an.executeQuery(Unknown Source)
|
|
|
|
首先,不管调用栈的方法,先根据提示文字not more than 50 queries once,搜索内容,这里使用反编译后的java文件,使用notepad++文件搜索
这里找到两处,两处的结果都在at com.hxtt.b.am这个类下
代码如下
private static final String dM = "allows executing not more than 50 queries once. You can order commercial version from http://www.hxtt.com .";
public static final SQLException if(
final String s)
{
return a(s + " "
+ "allows executing not more than 50 queries once. You can order commercial version from http://www.hxtt.com .",
40960);
}
复制与if相关的方法,新建测试文件调用throw if("HXTT Access Version 6.0 For Evaluation Purpose");可得到与报错一致的结果
接下来分析调用方法,打开IDEA,新建工程,引用这个jar
展开引用的jar,找到com.hxtt.b.am这个类
第一个要寻找的方法为com.hxtt.b.am.a(Unknown Source),实际上,通过前面的文件搜索已经找到第二个方法,这里我们点击里面的a方法,结合Ctrl键可以跳转到改方法
前两个方法找完,填一下调用栈的表
方法
|
调用行
|
实际方法定义
|
参数个数
|
at com.hxtt.b.am.a(Unknown Source)
|
503
|
public static final SQLException a(String var0, int var1) {
return new SQLException(var0, if(var1), var1);
}
|
2
|
at com.hxtt.b.am.if(Unknown Source)
|
550
|
public static final SQLException if(String var0) {
return a((String)(var0 + " " + "allows executing not more than 50 queries once. You can order commercial version from http://www.hxtt.com ."), 40960);
}
|
1
|
接下来找com.hxtt.sql.b0这个类
由于b0这个类调用了am类的if方法,并且参数为1个,根据这个线索,搜索关键字am.if(
搜索结果中有3处调用了这个方法
向上找方法名
这里正好对应上调用栈第三行的at com.hxtt.sql.b0.a(Unknown Source),填上一行
at com.hxtt.sql.b0.a(Unknown Source)
|
1248
|
private Object a(an var1, int var2, de var3, cd var4, bm var5, ba var6, a3 var7) throws SQLException {
|
7
|
继续找调用,搜索this.a( 并且参数是7个的
找到两处
不过对应的方法不是同一个,但方法名都是if,一并记录下来
at com.hxtt.sql.b0.a(Unknown Source)
|
1043
1080
|
protected synchronized void a(ay var1, an var2, int var3, de var4, ba var5) throws SQLException {
protected synchronized Object a(an var1, int var2, de var3, ba var4) throws SQLException {
|
5
4
|
到这里b0类的也就找完了,后面找com.hxtt.sql.an类的方法
搜索b0.a没有结果,但是搜索b0会发现
搞了个变量表示别找不着哦,不要搜b0.a了,搜goto.a有惊喜
前面的4个和5个参数都找着了
这俩都在一个方法里
at com.hxtt.sql.an.a(Unknown Source)
|
265
|
protected Object a(int var1, de var2, ba var3) throws SQLException {
|
3
|
后面的调用栈找的方法都一样,搜参数,看个数,如果个数一样看参数的对应类型,后面找到的如下
at com.hxtt.sql.an.a(Unknown Source)
|
261
|
protected Object a(int var1, de var2, Object var3) throws SQLException {
|
3
|
at com.hxtt.sql.an.if(Unknown Source)
|
228
|
private Object if(int var1, String var2, Object var3) throws SQLException {
|
3
|
at com.hxtt.sql.an.executeQuery(Unknown Source)
|
126
|
public ResultSet executeQuery(String var1) throws SQLException {
|
1
|
调用栈全表
方法
|
调用行
|
实际方法定义
|
参数个数
|
at com.hxtt.b.am.a(Unknown Source)
|
503
|
public static final SQLException a(String var0, int var1) {
return new SQLException(var0, if(var1), var1);
}
|
2
|
at com.hxtt.b.am.if(Unknown Source)
|
550
|
public static final SQLException if(String var0) {
return a((String)(var0 + " " + "allows executing not more than 50 queries once. You can order commercial version from http://www.hxtt.com ."), 40960);
}
|
1
|
at com.hxtt.sql.b0.a(Unknown Source)
|
1248
|
private Object a(an var1, int var2, de var3, cd var4, bm var5, ba var6, a3 var7) throws SQLException {
|
7
|
at com.hxtt.sql.b0.if(Unknown Source)
|
1152
|
private Object if(an var1, int var2, de var3, cd var4, bm var5, ba var6, a3 var7) throws SQLException {
|
|
at com.hxtt.sql.b0.a(Unknown Source)
|
1043
1080
|
protected synchronized void a(ay var1, an var2, int var3, de var4, ba var5) throws SQLException {
protected synchronized Object a(an var1, int var2, de var3, ba var4) throws SQLException {
|
5
4
|
at com.hxtt.sql.an.a(Unknown Source)
|
265
|
protected Object a(int var1, de var2, ba var3) throws SQLException {
|
3
|
at com.hxtt.sql.an.a(Unknown Source)
|
261
|
protected Object a(int var1, de var2, Object var3) throws SQLException {
|
3
|
at com.hxtt.sql.an.if(Unknown Source)
|
228
|
private Object if(int var1, String var2, Object var3) throws SQLException {
|
3
|
at com.hxtt.sql.an.executeQuery(Unknown Source)
|
126
|
public ResultSet executeQuery(String var1) throws SQLException {
|
1
|
其实调用栈不用分析这么多,分析到b0已经足够,往后分析的只是理一理思路。
由于超过限制是抛出异常,我们不让它抛出异常就可以了
之前找到am.if之前有个throw,那么这一句就是抛出异常的了
理论上来说,如果有源代码,只要去掉throw这句就好了。或者把前面的判断的值改为false。case 75和case 76的同样也是这个道理
三、使用JBE修改字节码
之前使用Javassist该过一些字节码,虽然Javassist有直接操作字节码的API,但是都很少有人用,逆向的时候多用来改方法的返回值或者直接重写方法体。由于这个是改方法体里面的东西,还是使用专用的工具比较好。
这里可以看到case的字节码呈现
这里是case 73 里面的字节码内容分,看到sipush 503的意思是把503这个数压入栈顶,后面用来做比较,看到这里就很简单了吧,把MAX_INT放入栈顶比较完不就一直是false了,在常量池建立一个整形常量,值为2147483647,后面ldc #常量编号(JBE编辑的时候直接用 ldc 2147483647)就行了,后面两个case同理