Skip to content

Commit aaa7b1d

Browse files
committed
第一次提交
0 parents commit aaa7b1d

File tree

15 files changed

+852
-0
lines changed

15 files changed

+852
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Created by .ignore support plugin (hsz.mobi)

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Java Object Searcher | java内存对象搜索
2+
3+
## 简介
4+
5+
可以用挖掘request对象用于回显,但不仅仅限制
6+
7+
## 使用
8+
9+
搜索语法
10+
11+
```
12+
FiledName:
13+
FiledValue:
14+
FiledType:
15+
```
16+
17+
```
18+
Thread target = Thread.current();
19+
String[] keys = new String[]{"Servlet","request"};
20+
String[] backlist = new String[]{"logger"};
21+
int dig_depth = 100;
22+
RequestSearcher searcher = new RequstSearcher(target,keys,"SearchRequst",dig_depth);
23+
searcher.searchObject();
24+
```

pom.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>me.gv7.tools</groupId>
8+
<artifactId>java-object-searcher</artifactId>
9+
<version>0.1</version>
10+
11+
<dependencies>
12+
13+
<!--log4j-->
14+
<dependency>
15+
<groupId>org.apache.logging.log4j</groupId>
16+
<artifactId>log4j-core</artifactId>
17+
<version>2.3</version>
18+
</dependency>
19+
<dependency>
20+
<groupId>org.slf4j</groupId>
21+
<artifactId>slf4j-log4j12</artifactId>
22+
<version>1.7.25</version>
23+
</dependency>
24+
</dependencies>
25+
</project>

src/main/java/META-INF/MANIFEST.MF

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Manifest-Version: 1.0
2+
Main-Class: me.gv7.tools.josearcher.JavaObjectSearcher
3+
6 KB
Binary file not shown.
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
/**
2+
* author: c0ny1
3+
* date: 2020-04-12 23:17
4+
* description: 本类用于搜索对象中所有的属性
5+
* ps: avicii 在写完《waiting for love》是否也是一样的心情。
6+
*/
7+
package me.gv7.tools.josearcher;
8+
9+
import me.gv7.tools.josearcher.test.TestClass;
10+
import org.apache.log4j.Logger;
11+
import java.lang.reflect.Field;
12+
import java.util.*;
13+
import static me.gv7.tools.josearcher.util.Common.*;
14+
import static me.gv7.tools.josearcher.util.Common.write2log;
15+
import static me.gv7.tools.josearcher.util.TypeUtils.*;
16+
17+
public class JavaObjectSearcher {
18+
private Logger logger = Logger.getLogger(JavaObjectSearcher.class);
19+
private Object target;
20+
private String[]keys;
21+
private boolean is_search_all = false; /* true:搜索全部 false:搜到就返回,不会继续对命中目标的属性继续搜索 */
22+
private int max_search_depth = 100;/* 递归搜索深度 */
23+
private boolean is_debug = false;
24+
private String project_name;
25+
private String result_file;
26+
private String all_chain_file;
27+
private List<Object> searched = new ArrayList<>();
28+
29+
30+
public JavaObjectSearcher(Object target, String[] keys, String project_name){
31+
this.target = target;
32+
this.keys = keys;
33+
this.project_name = project_name;
34+
this.result_file = String.format("%s_result_%s.txt",project_name,getCurrentDate());
35+
this.all_chain_file = String.format("%s_chain_%s.txt",project_name,getCurrentDate());
36+
}
37+
38+
39+
public JavaObjectSearcher(Object target, String[] keys, String project_name, int max_search_depth){
40+
this.target = target;
41+
this.keys = keys;
42+
this.result_file = String.format("%s_result_%s.txt",project_name,getCurrentDate());
43+
this.all_chain_file = String.format("%s_chain_%s.txt",project_name,getCurrentDate());
44+
this.max_search_depth = max_search_depth;
45+
}
46+
47+
48+
public JavaObjectSearcher(Object target, String[] keys, String project_name, int max_search_depth, boolean is_debug){
49+
this.target = target;
50+
this.keys = keys;
51+
this.result_file = String.format("%s_result_%s.txt",project_name,getCurrentDate());
52+
this.all_chain_file = String.format("%s_chain_%s.txt",project_name,getCurrentDate());
53+
this.max_search_depth = max_search_depth;
54+
this.is_debug = is_debug;
55+
}
56+
57+
58+
public void searchObject(){
59+
searchObject(null,target,"",0);
60+
}
61+
62+
63+
private void searchObject(String filed_name,Object filed_object,String log_chain,int father_depth) {
64+
int current_depth = father_depth;
65+
66+
//最多挖多深
67+
if(current_depth > max_search_depth){
68+
return;
69+
}
70+
71+
if (filed_object ==null || checkObjectIsSysType(filed_object) || checkObjectIsBacklist(filed_object)){
72+
//如果object是null/基本数据类型/包装类/日期类型,则不需要在递归调用
73+
return;
74+
}
75+
76+
//如果已经搜索过这个对象就返回不再继续搜索
77+
if(searched.size() <= 0){
78+
searched.add(filed_object);
79+
}else {
80+
for (Object obj : searched) {
81+
if (obj == filed_object) {
82+
return;
83+
}
84+
}
85+
searched.add(filed_object);
86+
}
87+
88+
89+
String new_log_chain = "";
90+
Class clazz = filed_object.getClass();
91+
92+
if(log_chain != null && log_chain != ""){
93+
current_depth++;
94+
new_log_chain = String.format("%s \n%s ---> %s = {%s}",log_chain,getBlank(current_depth),filed_name,clazz.getName());
95+
}else{
96+
new_log_chain = String.format("%s = {%s}","TargetObject",filed_object.getClass().getName());
97+
}
98+
99+
100+
// 搜索
101+
if(!is_search_all){
102+
if(matchClassType(clazz.getName(),this.keys)){
103+
write2log(result_file,new_log_chain + "\n\n\n");
104+
if(is_debug) {
105+
write2log(all_chain_file, new_log_chain + "\n\n\n");
106+
}
107+
return;
108+
}
109+
}
110+
111+
112+
if (filed_object instanceof Map){
113+
Map map = (Map)filed_object;
114+
if (map!=null && map.size()>0){
115+
Iterator iterator = map.values().iterator();
116+
while (iterator.hasNext()){
117+
searchObject(filed_name,iterator.next(),new_log_chain,current_depth);
118+
}
119+
}
120+
}
121+
122+
if(clazz.isArray()){
123+
try {
124+
//Object[] 没有属性
125+
Object[] obj_arr = (Object[]) filed_object;
126+
if (obj_arr != null && obj_arr.length > 0) {
127+
for(int i=0; i < obj_arr.length; i++){
128+
if(obj_arr[i] == null){
129+
continue;
130+
}
131+
String arr_type = obj_arr[i].getClass().getName();
132+
String arr_name = String.format("[%d] = {%s}",i,arr_type);
133+
searchObject(arr_name,obj_arr[i], new_log_chain,current_depth);
134+
}
135+
}
136+
}catch (Throwable e){
137+
logger.error(String.format("%s - %s",project_name,"clazz.isArray"),e);
138+
}
139+
}
140+
141+
142+
/**
143+
* 问题一:getDeclaredFields无法获取从父类获取的属性,需要向上遍历父类
144+
*/
145+
int father_level = 0;
146+
for (; clazz != Object.class; clazz = clazz.getSuperclass()) {//向上循环 遍历父类
147+
Field[] fields = clazz.getDeclaredFields();
148+
149+
for (Field field : fields) {
150+
// 不搜索父类的私有属性
151+
// if(father_level > 0 && field.isAccessible()){
152+
// return;
153+
// }
154+
155+
field.isAccessible();
156+
field.setAccessible(true);
157+
String proType = field.getGenericType().toString();
158+
String proName = field.getName();
159+
160+
if (isBasicType(field)) {
161+
//属性是基本类型跳过
162+
continue;
163+
} else if (isWrapperClass(field)) {
164+
//属性是包装类跳过
165+
continue;
166+
} else if(isBacklistType(field)){
167+
continue;
168+
}else if (isList(field)) {
169+
//对List,ArrayList类型的属性遍历
170+
try {
171+
List list = (List) field.get(filed_object);
172+
if (list != null && list.size() > 0) {
173+
current_depth++;
174+
String tmp_log_chain = String.format("%s \n%s ---> %s = {%s}", new_log_chain, getBlank(current_depth), proName, proType);
175+
int len = list.size();
176+
for (int i = 0; i < len; i++) {
177+
if (list.get(i) == null) {
178+
continue;
179+
}
180+
String list_name = String.format("[%d]", i);
181+
searchObject(list_name, list.get(i), tmp_log_chain, current_depth);
182+
}
183+
}
184+
} catch (Throwable e) {
185+
logger.error(String.format("%s - %s",project_name,"isList"),e);
186+
}
187+
} else if (isMap(field)) {
188+
try {
189+
//对Map,HashMap类型的属性遍历
190+
Map map = (Map) field.get(filed_object);
191+
if (map != null && map.size() > 0) {
192+
current_depth++;
193+
String tmp_log_chain = String.format("%s \n%s ---> %s = {%s}", new_log_chain, getBlank(current_depth), proName, proType);
194+
195+
Iterator<String> iter = map.keySet().iterator();
196+
while (iter.hasNext()) {
197+
String key = iter.next();
198+
Object value = map.get(key);
199+
String map_name = String.format("[%s]", key);
200+
searchObject(map_name, value, tmp_log_chain, current_depth);
201+
}
202+
}
203+
204+
} catch (Throwable e) {
205+
logger.error(String.format("%s - %s",project_name,"isMap"),e);
206+
}
207+
} else if (field.getType().isArray()) {
208+
try {
209+
//属性是数组类型则遍历
210+
//field.setAccessible(true);
211+
Object[] objArr = (Object[]) field.get(filed_object);
212+
if (objArr != null && objArr.length > 0) {
213+
current_depth++;
214+
for (int i = 0; i < objArr.length; i++) {
215+
if (objArr[i] == null) {
216+
continue;
217+
}
218+
219+
String tmp_log_chain = String.format("%s \n%s ---> %s = {%s}", new_log_chain, getBlank(current_depth), proName, proType);
220+
221+
String arrType = objArr[i].getClass().getName();
222+
String arr_name = String.format("[%d]", i);
223+
searchObject(arr_name, objArr[i], tmp_log_chain, current_depth);
224+
225+
}
226+
}
227+
} catch (Throwable e) {
228+
logger.error(String.format("%s - %s",project_name,"isArray"),e);
229+
}
230+
} else {
231+
try {
232+
//class类型的遍历
233+
Object subObj = field.get(filed_object);
234+
if (subObj != null) {
235+
searchObject(proName, subObj, new_log_chain, current_depth);
236+
} else {
237+
continue;
238+
}
239+
} catch (Throwable e) {
240+
logger.error(String.format("%s - %s",project_name,"class"),e);
241+
}
242+
}
243+
}
244+
father_level++;
245+
}
246+
// 搜索
247+
if(is_search_all){
248+
String[] chain = new_log_chain.split("--->");
249+
String end_point = chain.length != 0 ? chain[chain.length-1]:chain[0];
250+
if(matchClassType(end_point,this.keys)){
251+
write2log(result_file,new_log_chain + "\n\n\n");
252+
253+
}
254+
}
255+
256+
if(is_debug) {
257+
write2log(all_chain_file, new_log_chain + "\n\n\n");
258+
}
259+
System.out.println(new_log_chain);
260+
System.out.println("\n\n\n");
261+
//logger.info(new_log_chain);
262+
}
263+
264+
265+
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
266+
Thread thread = Thread.currentThread();
267+
Field f = thread.getClass().getDeclaredField("threadLocals");
268+
f.setAccessible(true);
269+
Object bb = f.get(thread);
270+
271+
String[] keys = new String[]{"Request","ServletRequst", "Entity"};
272+
273+
TestClass test = new TestClass();
274+
JavaObjectSearcher grab = new JavaObjectSearcher(test,keys,"log",50,true);
275+
grab.searchObject();
276+
}
277+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package me.gv7.tools.josearcher;
2+
3+
/**
4+
* 本类用于搜索Java对象中是否存在request相关的属性,比如可以在反序列化需要回显的场景,用于辅助挖掘request对象。
5+
*/
6+
public class RequestObjectSearcher {
7+
private String[] keys; /* name:xxx,value:xxx,type:request|context */
8+
private String[] backlist; /* */
9+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package me.gv7.tools.josearcher.test;
2+
3+
public class EntityTest {
4+
private int id;
5+
private String name;
6+
7+
public int getId() {
8+
return id;
9+
}
10+
11+
public void setId(int id) {
12+
this.id = id;
13+
}
14+
15+
public String getName() {
16+
return name;
17+
}
18+
19+
public void setName(String name) {
20+
this.name = name;
21+
}
22+
}

0 commit comments

Comments
 (0)