Skip to content

Commit 747dacb

Browse files
committed
1.1
1 parent c97b8de commit 747dacb

22 files changed

+584
-513
lines changed

README.md

+28-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# DHook ![1.0 (shields.io)](https://img.shields.io/badge/1.1-brightgreen.svg)
2-
DHook是一个自定义动态hook的工具。通过`javaagent`+`ASM`技术对运行时的java应用进行字节码修改,并可以配置文件的方式来增加hook点,修改执行方法的返回值等
2+
DHook是一个自定义动态hook的工具。通过`javaagent`+`ASM`技术对运行时的java应用进行字节码修改,并可以配置文件的方式来增加hook点,修改执行方法的返回值以及参数等
33

44
## 兼容性
55
* java 8-11
@@ -42,17 +42,36 @@ public class Test {
4242
该类存在三个分别是string,boolean,int为参数和返回值的方法,通过配置`hookClass.csv`文件,更改对应的返回值。此文件内容如下:
4343

4444
```csv
45-
className,method,desc,return
46-
com/keven1z/Test,test1,(Ljava/lang/String;)Ljava/lang/String;,keven1z
47-
com/keven1z/Test,test2,(I)I,111
48-
com/keven1z/Test,test3,(Z)Z,true
45+
className,method,desc,return,parameter
46+
com/keven1z/Test,test1,(Ljava/lang/String;)Ljava/lang/String;,keven1z,
47+
com/keven1z/Test,test2,(I)I,111,
48+
com/keven1z/Test,test3,(Z)Z,true,
4949
```
50+
文件参数如下:
5051

51-
该配置文件由className,method,desc,return组成,分别为类名,方法名,方法的描述符,以及返回值组成,配置文件路径固定为运行应用的当前路径。
52+
| name | description |
53+
| :-------: | :----------------------------------------------------------: |
54+
| className | 类的全路径,以`/`分割,示例:`com/keven1z/Test`|
55+
| method | 方法名,示例:`test1` |
56+
| desc | 方法描述,示例:`(Ljava/lang/String;)Ljava/lang/String;` |
57+
| return | 待修改的返回值 |
58+
| parameter | 待修改的参数,以`;`分割多个参数,以`-`分割位置和值,前者为位置,后者为值,静态方法位置以0为起始值,非静态方法以1为起始值,示例:0-aa;1-bb |
5259

53-
运行`java -javaagent:agent -jar test.jar`.运行结果如下:
5460

55-
![image-20211123135028361](https://typora-1253484559.cos.ap-shanghai.myqcloud.com/img/image-20211123135028361.png)
61+
62+
运行`java -javaagent:dHook.jar -jar test.jar`.运行结果如下:
63+
64+
![image-20211129204730815](https://typora-1253484559.cos.ap-shanghai.myqcloud.com/img/image-20211129204730815.png)
65+
66+
### 辅助参数
67+
68+
#### 反编译源代码
69+
70+
需在`className`前添加`+`,会在运行目录下生成一个文件,若该类可以被反编译,则生成java文件,否则生成class文件。
71+
72+
#### 打印类的所有方法
73+
74+
可以通过将method设置为`*`,则`Dhook`会打印该类的所有方法。
5675

5776
## 更新
5877
### 1.0版本
@@ -63,5 +82,5 @@ com/keven1z/Test,test3,(Z)Z,true
6382
### 1.1版本
6483
* 增加通过`*`打印该类的所有方法
6584
* 支持打印返回值
66-
* 支持反编译代码,将hook代码生成文件写入当前目录
85+
* 支持反编译代码
6786
* 支持修改参数

hookClass.csv

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
className,method,desc,return,parameter,
2-
com/keven1z/Test,test1,(Ljava/lang/String;)Ljava/lang/String;,keven1z
3-
com/keven1z/Test,test2,(I)I,111
4-
com/keven1z/Test,test3,(Z)Z,true
5-
com/keven1z/Test,*,*
2+
com/keven1z/Test,test1,(Ljava/lang/String;)Ljava/lang/String;,keven1z,
3+
com/keven1z/Test,test2,(I)I,111,
4+
com/keven1z/Test,test3,(Z)Z,true,
5+
com/keven1z/Test,test4,(Ljava/lang/String;I)Ljava/lang/String;,,0-keven1z;1-777

pom.xml

+7-6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@
2525
<artifactId>commons-csv</artifactId>
2626
<version>1.9.0</version>
2727
</dependency>
28+
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
29+
<dependency>
30+
<groupId>commons-codec</groupId>
31+
<artifactId>commons-codec</artifactId>
32+
<version>1.9</version>
33+
</dependency>
34+
2835
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
2936
<dependency>
3037
<groupId>javax.xml.bind</groupId>
@@ -51,12 +58,6 @@
5158
<artifactId>procyon-compilertools</artifactId>
5259
<version>0.5.36</version>
5360
</dependency>
54-
<dependency>
55-
<groupId>org.jvnet.sorcerer</groupId>
56-
<artifactId>sorcerer-javac</artifactId>
57-
<version>0.8</version>
58-
</dependency>
59-
<!-- Thanks for using https://jar-download.com -->
6061

6162
</dependencies>
6263
<build>

src/main/java/cn/com/x1001/Agent.java

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cn.com.x1001;
22

33

4-
import cn.com.x1001.hook.BpCrack;
54
import cn.com.x1001.hook.HookTransformer;
65
import cn.com.x1001.watch.ClassFileWatch;
76
import cn.com.x1001.watch.HookWatch;
@@ -21,16 +20,15 @@ public static void premain(String args, Instrumentation inst){
2120
}
2221

2322
private static void start(Instrumentation inst) {
24-
out.println("********************************************************************");
25-
out.println("* Run Success *");
26-
out.println("********************************************************************");
27-
inst.addTransformer(new BpCrack());
28-
inst.addTransformer(new HookTransformer(), true);
2923
try {
3024
new ClassFileWatch().start();
3125
} catch (IOException e) {
3226
e.printStackTrace();
3327
}
28+
out.println("********************************************************************");
29+
out.println("* Run Success *");
30+
out.println("********************************************************************");
31+
inst.addTransformer(new HookTransformer(), true);
3432
new HookWatch(inst).start();
3533
}
3634
}

src/main/java/cn/com/x1001/InstrumentationContext.java

+117-52
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,37 @@
11
package cn.com.x1001;
22

3-
import cn.com.x1001.classmap.ClassInfo;
4-
import cn.com.x1001.classmap.Edge;
5-
import cn.com.x1001.classmap.GraphNode;
6-
import cn.com.x1001.classmap.HookGraph;
3+
import cn.com.x1001.classmap.*;
74
import cn.com.x1001.util.ClassUtil;
85

9-
import java.util.Collections;
106
import java.util.HashSet;
117
import java.util.Set;
128
import java.util.concurrent.CopyOnWriteArraySet;
139

1410
/**
15-
* @author keven1z
16-
* @Date 2021/6/17
11+
* @author keven1z
12+
* @Date 2021/6/17
1713
* @Description hook 的上下文信息
18-
*/
14+
*/
1915
public class InstrumentationContext {
2016

2117
/**
2218
* 类的图集合
2319
*/
2420
private HookGraph classMap = new HookGraph();
2521
/*
26-
* 存储hook的接口或类
27-
*/
28-
private Set<ClassInfo> hookClasses = new CopyOnWriteArraySet();
22+
* 存储hook的接口或类
23+
*/
24+
private CopyOnWriteArraySet<HookClass> hookClasses = new CopyOnWriteArraySet<>();
2925

3026

31-
public Set<ClassInfo> getClassHashSet() {
27+
public CopyOnWriteArraySet<HookClass> getClassHashSet() {
3228
return hookClasses;
3329
}
3430

35-
public void addHook(ClassInfo classInfo) {
36-
this.getClassHashSet().add(classInfo);
31+
public void addHook(HookClass hookClass) {
32+
this.getClassHashSet().add(hookClass);
3733
}
34+
3835
public HookGraph getClassMap() {
3936
return classMap;
4037
}
@@ -43,68 +40,136 @@ public HookGraph getClassMap() {
4340
* 是否为hook点
4441
*/
4542
public boolean isHookClass(String className) {
46-
for (ClassInfo hookClassInfo : getClassHashSet()) {
47-
String hookClassName = hookClassInfo.getClassName();
43+
for (HookClass hookHookClass : getClassHashSet()) {
44+
String hookClassName = hookHookClass.getClassName();
4845
if (hookClassName.equals(className)) {
4946
return true;
5047
}
5148
}
5249
return false;
5350
}
54-
public void setHooked(String className){
55-
GraphNode node = this.getClassMap().getNode(className);
56-
node.hooked();
51+
52+
public boolean isHookClass(String className, String method, String desc) {
53+
for (HookClass hookHookClass : getClassHashSet()) {
54+
String hookClassName = hookHookClass.getClassName();
55+
String m = hookHookClass.getMethod();
56+
String d = hookHookClass.getDesc();
57+
if (hookClassName.equals(className) && m.equals(method) && d.equals(desc)) {
58+
return true;
59+
}
60+
}
61+
return false;
5762
}
58-
public ClassInfo getHookClass(String className) {
59-
for (ClassInfo hookClassInfo : getClassHashSet()) {
60-
String hookClassName = hookClassInfo.getClassName();
61-
if (hookClassName.equals(className)) {
62-
return hookClassInfo;
63+
64+
public HookClass getHookClass(Set<HookClass> hookClasses, String method, String desc) {
65+
66+
for (HookClass hookClass : hookClasses) {
67+
String m = hookClass.getMethod();
68+
String d = hookClass.getDesc();
69+
if (m.equals(method) && d.equals(desc)) {
70+
return hookClass;
6371
}
6472
}
6573
return null;
6674
}
67-
public void addHooKClass(String className,ClassInfo hookClass){
68-
ClassInfo vertex = getClassMap().getVertex(className);
69-
vertex.setMethodDesc(hookClass.getMethodDesc());
70-
getClassHashSet().add(vertex);
75+
76+
public HookClass getHookClass(String className, String method, String desc) {
77+
Set<HookClass> hookClasses = getHookClasses(className);
78+
for (HookClass hookClass : hookClasses) {
79+
String m = hookClass.getMethod();
80+
String d = hookClass.getDesc();
81+
if (m.equals(method) && d.equals(desc)) {
82+
return hookClass;
83+
}
84+
}
85+
return null;
86+
}
87+
88+
/**
89+
* 設置已hook
90+
*/
91+
public void setHooked(String className) {
92+
Set<HookClass> hookClasses = getHookClasses(className);
93+
for (HookClass hookClass : hookClasses) {
94+
hookClass.setHooked(true);
95+
}
96+
}
97+
98+
public Set<HookClass> getHookClasses(String className) {
99+
HashSet<HookClass> hashSet = new HashSet<>();
100+
for (HookClass hookHookClass : getClassHashSet()) {
101+
String hookClassName = hookHookClass.getClassName();
102+
if (hookClassName.equals(className)) {
103+
hashSet.add(hookHookClass);
104+
}
105+
}
106+
return hashSet;
107+
}
108+
109+
public boolean containAction(String className, int action) {
110+
Set<HookClass> hookClasses = getHookClasses(className);
111+
for (HookClass hookClass : hookClasses) {
112+
Set<Integer> actions = hookClass.getActions();
113+
if (actions.contains(action)) return true;
114+
}
115+
return false;
116+
}
117+
118+
/**
119+
* 通过父类增加hook点
120+
*
121+
* @param className
122+
* @param superClassName
123+
*/
124+
public void addHooKClass(String className, String superClassName) {
125+
Set<HookClass> superHookClasses = getHookClasses(superClassName);
126+
for (HookClass hookClass : superHookClasses) {
127+
HookClass hc = new HookClass(className, hookClass.getMethod(), hookClass.getDesc(), hookClass.getReturnValue(), hookClass.getParameters(), hookClass.getActions());
128+
getClassHashSet().add(hc);
129+
}
71130
}
72-
public void addHooKClass(Set<ClassInfo> classInfoHashSet,ClassInfo hookClass){
73-
for (ClassInfo classInfo :classInfoHashSet){
74-
classInfo.setMethodDesc(hookClass.getMethodDesc());
131+
132+
public void addHooKClass(String className, Set<ClassVertex> childClasses) {
133+
Set<HookClass> hookClasses = getHookClasses(className);
134+
135+
for (HookClass hookClass : hookClasses) {
136+
for (ClassVertex classVertex : childClasses) {
137+
HookClass hc = new HookClass(classVertex.getClassName(), hookClass.getMethod(), hookClass.getDesc(), hookClass.getReturnValue(), hookClass.getParameters(), hookClass.getActions());
138+
getClassHashSet().add(hc);
139+
}
75140
}
76-
getClassHashSet().addAll(classInfoHashSet);
77141
}
142+
78143
/**
79144
* 判断该节点的父类是否在hook表中
145+
*
80146
* @param className 待hook的className
81147
*/
82-
public Set<ClassInfo> getChildHookClasses(String className){
83-
ClassInfo superClassInfo = getClassMap().getVertex(className);
84-
HashSet<Edge> toEdges = getClassMap().getToEdges(superClassInfo);
85-
HashSet<ClassInfo> classInfos = new HashSet<>();
86-
for(Edge edge:toEdges){
87-
ClassInfo from = edge.getFrom();
88-
if (!ClassUtil.isInterface(from.getAccess())){
89-
classInfos.add(from);
90-
}
91-
else classInfos.addAll(getChildHookClasses(from.getClassName()));
148+
public Set<ClassVertex> getChildClasses(String className) {
149+
ClassVertex vertex = classMap.getVertex(className);
150+
HashSet<Edge> toEdges = getClassMap().getToEdges(vertex);
151+
HashSet<ClassVertex> classVertices = new HashSet<>();
152+
for (Edge edge : toEdges) {
153+
ClassVertex from = edge.getFrom();
154+
if (!ClassUtil.isInterface(from.getAccess())) {
155+
classVertices.add(from);
156+
} else classVertices.addAll(getChildClasses(from.getClassName()));
92157
}
93-
return classInfos;
158+
return classVertices;
94159
}
95-
public ClassInfo getSuperHookClasses(String className){
96-
ClassInfo classInfo = getClassMap().getVertex(className);
160+
161+
public ClassVertex getSuperClasses(String className) {
162+
ClassVertex classVertex = getClassMap().getVertex(className);
97163
/*如果为接口则不加入hook点*/
98-
if (ClassUtil.isInterface(classInfo.getAccess())){
164+
if (ClassUtil.isInterface(classVertex.getAccess())) {
99165
return null;
100166
}
101-
HashSet<Edge> fromEdges = getClassMap().getFromEdges(classInfo);
102-
for(Edge edge:fromEdges){
103-
ClassInfo to = edge.getTo();
104-
if (isHookClass(to.getClassName())){
167+
HashSet<Edge> fromEdges = getClassMap().getFromEdges(classVertex);
168+
for (Edge edge : fromEdges) {
169+
ClassVertex to = edge.getTo();
170+
if (isHookClass(to.getClassName())) {
105171
return to;
106-
}
107-
else getSuperHookClasses(to.getClassName());
172+
} else getSuperClasses(to.getClassName());
108173
}
109174
return null;
110175
}

0 commit comments

Comments
 (0)