Tabby 分析 Java 程序

注意
本文最后更新于 2024-03-01,文中内容可能已过时。

Tabby 分析 Java 程序

可以从官网下载相应的包, Download

Neo4j v5 版本 apoc 插件改成了两个部分 apoc-coreapoc-extend,可自行在以下两个库下载

关于 apoc 插件的版本选择方法:Neo4j 数据库版本的前两位对应 apoc 插件的版本 比如 Neo4j 数据库版本为 v5.3.0,则选择 apoc 插件 v5.3.x 版本

在 Desktop 处新建一个新的 Project 和一个本地数据库,初始化的时候需要设置密码。

image-20230714141314938

新建成功后将会得到一个默认名为 neo4j 的数据库,下面连接使用这个数据库。

image-20230714141639509

首先修改当前数据库的配置文件 neo4j.conf。

image-20230714142149849

# 注释下面的配置,允许从本地任意位置载入csv文件
#server.directories.import=import

# 允许 apoc 扩展
dbms.security.procedures.unrestricted=jwt.security.*,apoc.*

# 修改内存相关配置 
# 可以通过官方的neo4j-admin来推荐配置内存大小,https://neo4j.com/docs/operations-manual/current/tools/neo4j-admin/neo4j-admin-memrec/
dbms.memory.heap.initial_size=1G
dbms.memory.heap.max_size=4G
dbms.memory.pagecache.size=4G

然后同一个目录下 新建 apoc.conf 文件。

apoc.import.file.enabled=true
apoc.import.file.use_neo4j_config=false

最后,配置一下 apoc 和 tabby 插件,打开 plugins 目录将对应的 jar 复制到该数据库的 plugins 目录。

image-20230714142905014

上述步骤做完之后,重启数据库

启动图数据库并打开 Neo4j Brower。

image-20230714143116910

看到如下窗口和信息即说明数据库没有问题。

image-20230714143239112

查询 CALL apoc.help('all') 验证 apoc 插件是否正常。

image-20230714143453100

为了加快导入/删除的速度,这里提前对节点进行索引建立。

CREATE CONSTRAINT c1 IF NOT EXISTS FOR (c:Class) REQUIRE c.ID IS UNIQUE;
CREATE CONSTRAINT c2 IF NOT EXISTS FOR (c:Class) REQUIRE c.NAME IS UNIQUE;
CREATE CONSTRAINT c3 IF NOT EXISTS FOR (m:Method) REQUIRE m.ID IS UNIQUE;
CREATE CONSTRAINT c4 IF NOT EXISTS FOR (m:Method) REQUIRE m.SIGNATURE IS UNIQUE;
CREATE INDEX index1 IF NOT EXISTS FOR (m:Method) ON (m.NAME);
CREATE INDEX index2 IF NOT EXISTS FOR (m:Method) ON (m.CLASSNAME);
CREATE INDEX index3 IF NOT EXISTS FOR (m:Method) ON (m.NAME, m.CLASSNAME);
CREATE INDEX index4 IF NOT EXISTS FOR (m:Method) ON (m.NAME, m.NAME0);
CREATE INDEX index5 IF NOT EXISTS FOR (m:Method) ON (m.SIGNATURE);
CREATE INDEX index6 IF NOT EXISTS FOR (m:Method) ON (m.NAME0);
CREATE INDEX index7 IF NOT EXISTS FOR (m:Method) ON (m.NAME0, m.CLASSNAME);
:schema //查看表库
:sysinfo //查看数据库信息

image-20230714144343428

如果经过很多的导入/删除操作,图数据库占用了很多的硬盘存储,那么可以将原有的图数据库删除,重新按照上面的步骤新建图数据库。 删除所有约束。

DROP CONSTRAINT c1;
DROP CONSTRAINT c2;
DROP CONSTRAINT c3;
DROP CONSTRAINT c4;
DROP INDEX index1;
DROP INDEX index2;
DROP INDEX index3;
DROP INDEX index4;
DROP INDEX index5;
DROP INDEX index6;
DROP INDEX index7;

在 tabby 下新建文件夹 cases,放入我们要分析的 JAR 文件。这里我们以 Xstrem 反序列化的环境作为例子。

接下来编辑 Tabby 的配置文件 /tabby/conf/settings.properties

# need to modify
tabby.build.enable                        = true
tabby.load.enable                         = true

tabby.build.target                        = cases/xstream-sample-1.4.15.jar
tabby.build.libraries                     = libs
tabby.build.mode                          = gadget
tabby.output.directory                    = ./output/dev

# debug
tabby.debug.details                       = false

# jdk settings
tabby.build.isJDKProcess                  = false
tabby.build.withAllJDK                    = false
tabby.build.excludeJDK                    = false
tabby.build.isJDKOnly                     = false

# dealing fatjar
tabby.build.checkFatJar                   = true

# pointed-to analysis
tabby.build.isFullCallGraphCreate         = false
tabby.build.thread.timeout                = 2
tabby.build.isNeedToCreateIgnoreList      = false

# db settings
tabby.cache.isDockerImportPath            = false

tabby.neo4j.username                      = neo4j
tabby.neo4j.password                      = xyw647584
tabby.neo4j.url                           = bolt://127.0.0.1:7687

参数字段的具体说明在[Tabby 配置文件介绍](https://github.com/wh1t3p1g/tabby/blob/master/doc/Tabby 配置文件介绍.md)。我们此处只需要修改密码和目标参数,即 tabby.build.targettabby.neo4j.password

运行方式

java -Xmx20g -jar tabby.jar

或使用项目里的 run.sh 文件 内存大小根据实际情况进行调整。

运行的输出大概如下,没有报错说明没有问题。

C:\Users\Administrator\Desktop\tabby>java -Xmx35g -jar tabby.jar
 ___________   __       _______   _______  ___  ___
("     _   ") /""\     |   _  "\ |   _  "\|"  \/"  |
 )__/  \\__/ /    \    (. |_)  :)(. |_)  :)\   \  /
    \\_ /   /' /\  \   |:     \/ |:     \/  \\  \/
    |.  |  //  __'  \  (|  _  \\ (|  _  \\  /   /
    \:  | /   /  \\  \ |: |_)  :)|: |_)  :)/   /
     \__|(___/    \___)(_______/ (_______/|___/
                      v1.2.0
              Happy Hunting Bugs! XD
         https://github.com/wh1t3p1g/tabby

2023-07-14 14:43:57.537  INFO 17188 --- [           main] tabby.App                                : Starting App using Java 1.8.0_102 on WIN-HOST-200 with PID 17188 (C:\Users\Administrator\Desktop\tabby\tabby.jar started by Administrator in C:\Users\Administrator\Desktop\tabby)
2023-07-14 14:43:57.543  INFO 17188 --- [           main] tabby.App                                : The following 1 profile is active: "default"
2023-07-14 14:44:02.820  INFO 17188 --- [           main] tabby.core.container.RulesContainer      : load 57 rules success!
2023-07-14 14:44:04.944  INFO 17188 --- [           main] tabby.App                                : Started App in 8.514 seconds (JVM running for 10.018)
2023-07-14 14:44:04.980  INFO 17188 --- [bby-collector-1] tabby.core.container.DataContainer       : Clean old tabby.core.data in Neo4j.
2023-07-14 14:44:05.340  INFO 17188 --- [           main] tabby.core.Analyser                      : Get 2 JDK dependencies
2023-07-14 14:44:05.343  INFO 17188 --- [           main] tabby.core.Analyser                      : Try to collect all targets
2023-07-14 14:44:05.864  INFO 17188 --- [           main] tabby.core.Analyser                      : Load basic classes
2023-07-14 14:44:06.494  INFO 17188 --- [bby-collector-1] tabby.core.container.DataContainer       : Clean old tabby.core.data in Neo4j. DONE!
2023-07-14 14:44:07.995  INFO 17188 --- [           main] tabby.core.Analyser                      : Load dynamic classes
2023-07-14 14:44:07.995  INFO 17188 --- [           main] tabby.core.Analyser                      : Total analyse 39 targets.
2023-07-14 14:44:08.002  INFO 17188 --- [           main] tabby.core.Analyser                      : Target 39, Dependencies 41
2023-07-14 14:44:08.002  INFO 17188 --- [           main] tabby.core.scanner.ClassInfoScanner      : Start to collect 39 targets' class information.
2023-07-14 14:44:15.787  INFO 17188 --- [           main] tabby.core.scanner.ClassInfoScanner      : Total 10400 classes.
2023-07-14 14:44:15.805  INFO 17188 --- [           main] tabby.core.scanner.ClassInfoScanner      : Build 10400 classes' edges.
2023-07-14 14:44:15.808  INFO 17188 --- [           main] tabby.core.scanner.ClassInfoScanner      : Build 0/10400 classes.
2023-07-14 14:44:33.487  INFO 17188 --- [           main] tabby.core.scanner.ClassInfoScanner      : Build 10000/10400 classes.
2023-07-14 14:44:33.801  INFO 17188 --- [           main] tabby.core.scanner.ClassInfoScanner      : Build 10400/10400 classes.
2023-07-14 14:44:33.801  INFO 17188 --- [           main] tabby.core.scanner.ClassInfoScanner      : Start to save remained data to graphdb.
2023-07-14 14:44:40.292  INFO 17188 --- [           main] tabby.core.scanner.ClassInfoScanner      : Graphdb saved.
2023-07-14 14:44:40.309  INFO 17188 --- [           main] tabby.core.scanner.CallGraphScanner      : Build call graph. START!
2023-07-14 14:47:28.849  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 5.0%, Remain: 77096
2023-07-14 14:48:27.926  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 10.0%, Remain: 73039
2023-07-14 14:48:51.205  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 15.0%, Remain: 68982
2023-07-14 14:49:18.355  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 20.0%, Remain: 64925
2023-07-14 14:49:33.021  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 25.0%, Remain: 60868
2023-07-14 14:49:49.118  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 30.0%, Remain: 56811
2023-07-14 14:49:59.110  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 35.0%, Remain: 52754
2023-07-14 14:50:13.855  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 40.0%, Remain: 48697
2023-07-14 14:50:22.646  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 45.0%, Remain: 44640
2023-07-14 14:50:30.322  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 50.0%, Remain: 40583
2023-07-14 14:50:38.200  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 55.0%, Remain: 36526
2023-07-14 14:50:45.485  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 60.0%, Remain: 32469
2023-07-14 14:50:51.392  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 65.0%, Remain: 28412
2023-07-14 14:50:57.594  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 70.0%, Remain: 24355
2023-07-14 14:51:02.794  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 75.0%, Remain: 20298
2023-07-14 14:51:07.769  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 80.0%, Remain: 16241
2023-07-14 14:51:12.145  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 85.0%, Remain: 12184
2023-07-14 14:51:16.599  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 90.0%, Remain: 8127
2023-07-14 14:51:20.591  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 95.0%, Remain: 4070
2023-07-14 14:51:27.575  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 100.0%, Remain: 13
2023-07-14 14:51:27.582  INFO 17188 --- [           main] tabby.util.TickTock                      : Status: 100.0%, Remain: 0
2023-07-14 14:51:27.582  INFO 17188 --- [           main] tabby.util.TickTock                      : Wait for all tasks to complete. Timeout: 120s
2023-07-14 14:51:27.585  INFO 17188 --- [           main] tabby.util.TickTock                      : All tasks completed.
2023-07-14 14:51:27.589  INFO 17188 --- [           main] tabby.core.scanner.CallGraphScanner      : Build call graph. DONE!
2023-07-14 14:51:27.592  INFO 17188 --- [           main] tabby.core.scanner.CallGraphScanner      : Save remained data to graphdb. START!
2023-07-14 14:51:48.359  INFO 17188 --- [           main] tabby.core.scanner.CallGraphScanner      : Save remained data to graphdb. DONE!
2023-07-14 14:51:48.359  INFO 17188 --- [           main] tabby.core.Analyser                      : Total cost 7 min 40 seconds.
2023-07-14 14:51:48.379  INFO 17188 --- [           main] tabby.core.container.DataContainer       : Total 121218, classes: 13897, methods: 107321
2023-07-14 14:51:48.586  INFO 17188 --- [           main] t.d.c.service.RelationshipsService       : Total 297613, has count: 107321, call count: 149771, extend count: 4289, alias count: 29395, interfaces count: 6837
2023-07-14 14:51:48.586  INFO 17188 --- [           main] tabby.core.container.DataContainer       : Save cache to CSV.
2023-07-14 14:51:54.126  INFO 17188 --- [           main] tabby.core.container.DataContainer       : Save cache to CSV. DONE!
2023-07-14 14:51:54.126  INFO 17188 --- [           main] tabby.core.Analyser                      : Start to save cache.
2023-07-14 14:51:54.133  INFO 17188 --- [           main] tabby.core.container.DataContainer       : Save methods to Neo4j.
2023-07-14 14:53:03.690  INFO 17188 --- [           main] tabby.core.container.DataContainer       : Save classes to Neo4j.
2023-07-14 14:53:04.902  INFO 17188 --- [           main] tabby.core.container.DataContainer       : Save relation to Neo4j.
2023-07-14 14:53:04.902  INFO 17188 --- [           main] tabby.dal.neo4j.service.ClassService     : Save Extend relationship
2023-07-14 14:53:06.468  INFO 17188 --- [           main] tabby.dal.neo4j.service.ClassService     : Save Interface relationship
2023-07-14 14:53:07.743  INFO 17188 --- [           main] tabby.dal.neo4j.service.ClassService     : Save Has relationship
2023-07-14 14:53:18.720  INFO 17188 --- [           main] tabby.dal.neo4j.service.ClassService     : Save Call relationship
2023-07-14 14:53:35.496  INFO 17188 --- [           main] tabby.dal.neo4j.service.ClassService     : Save Alias relationship
2023-07-14 14:53:38.346  INFO 17188 --- [           main] tabby.core.Analyser                      : Cost 1 min 44 seconds.
2023-07-14 14:53:38.346  INFO 17188 --- [           main] tabby.App                                : Done. Bye!

进入数据库之后查看数据保存是否完成。

image-20230714145753637

我们查询几个类看看。

MATCH (n:Class) 
RETURN n 
LIMIT 10

结果之一如下,可以观察其中的字段。

{
  "identity": 107324,
  "labels": [
    "Class"
  ],
  "properties": {
    "HAS_INTERFACES": false,
    "IS_STRUTS_ACTION": false,
    "HAS_DEFAULT_CONSTRUCTOR": true,
    "HAS_SUPER_CLASS": true,
    "INTERFACES": "[]",
    "IS_INTERFACE": false,
    "ID": "e0efd3dfa9f74c9aa133e585e9314157",
    "IS_ABSTRACT": false,
    "IS_SERIALIZABLE": false,
    "SUPER_CLASS": "org.apache.catalina.valves.ValveBase",
    "NAME": "org.apache.catalina.valves.ErrorReportValve"
  },
  "elementId": "107324"
}

假如想查询 fastjson jar包里面的类呢。

MATCH (n:Class) 
WHERE n.NAME STARTS WITH 'com.alibaba.fastjson'
RETURN n  
LIMIT 10
getDataSourceName:825, BaseRowSet (javax.sql.rowset)
connect:624, JdbcRowSetImpl (com.sun.rowset)
getDatabaseMetaData:4004, JdbcRowSetImpl (com.sun.rowset)	< ======================== 进入JdbcRowSetImpl类
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
get:343, Accessor$GetterSetterReflection (com.sun.xml.internal.bind.v2.runtime.reflect)	< ======================== 4
serializeURIs:402, ClassBeanInfoImpl (com.sun.xml.internal.bind.v2.runtime)
childAsXsiType:662, XMLSerializer (com.sun.xml.internal.bind.v2.runtime)
write:256, MarshallerImpl (com.sun.xml.internal.bind.v2.runtime)
marshal:89, BridgeImpl (com.sun.xml.internal.bind.v2.runtime)
marshal:130, Bridge (com.sun.xml.internal.bind.api)
marshal:161, BridgeWrapper (com.sun.xml.internal.ws.db.glassfish)
writeTo:109, JAXBAttachment (com.sun.xml.internal.ws.message)	< ======================== 3 第一次出现JdbcRowSetImpl对象
asInputStream:99, JAXBAttachment (com.sun.xml.internal.ws.message)
getInputStream:125, JAXBAttachment (com.sun.xml.internal.ws.message)
getMessage:366, XMLMessage$XMLMultiPart (com.sun.xml.internal.ws.encoding.xml)
getAttachments:465, XMLMessage$XMLMultiPart (com.sun.xml.internal.ws.encoding.xml)
getAttachments:103, MessageWrapper (com.sun.xml.internal.ws.api.message)
get:111, ResponseContext (com.sun.xml.internal.ws.client)	< ======================== 2
compareIndices:2492, DataTransferer$IndexedComparator (sun.awt.datatransfer)
compare:2971, DataTransferer$IndexOrderComparator (sun.awt.datatransfer)	< ======================== POC的第二个类
siftDownUsingComparator:721, PriorityQueue (java.util)
siftDown:687, PriorityQueue (java.util)
heapify:736, PriorityQueue (java.util)
readObject:796, PriorityQueue (java.util)	< ======================== 1 进入PriorityQueue类的 readObject 方法 CC2?
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
callReadObject:132, SerializationMembers (com.thoughtworks.xstream.core.util)	< ======================== 准备进入PriorityQueue类的 readObject 方法
doUnmarshal:443, SerializableConverter (com.thoughtworks.xstream.converters.reflection)
unmarshal:277, AbstractReflectionConverter (com.thoughtworks.xstream.converters.reflection)	< ======================== 第一次出现PriorityQueue对象 result
convert:72, TreeUnmarshaller (com.thoughtworks.xstream.core)
convert:72, AbstractReferenceUnmarshaller (com.thoughtworks.xstream.core)
convertAnother:66, TreeUnmarshaller (com.thoughtworks.xstream.core)
convertAnother:50, TreeUnmarshaller (com.thoughtworks.xstream.core)
start:134, TreeUnmarshaller (com.thoughtworks.xstream.core)	< ======================== 第一次出现PriorityQueue Class对象
unmarshal:32, AbstractTreeMarshallingStrategy (com.thoughtworks.xstream.core)
unmarshal:1409, XStream (com.thoughtworks.xstream)
unmarshal:1388, XStream (com.thoughtworks.xstream)
fromXML:1273, XStream (com.thoughtworks.xstream)
fromXML:1264, XStream (com.thoughtworks.xstream)
read:20, HelloController (org.vulhub.xstreamsample)

第一段

match (source:Method {NAME:"fromXML",CLASSNAME:"com.thoughtworks.xstream.XStream"})
match (sink:Method {NAME:"unmarshal",CLASSNAME:"com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy"})
with source, collect(sink) as sinks
call tabby.algo.findPath(source, sinks, 8, false, false) YIELD path
return path

image-20230714183416264

第二段

match (source:Method {NAME:"start",CLASSNAME:"com.thoughtworks.xstream.core.TreeUnmarshaller"})
match (sink:Method {NAME:"convert",CLASSNAME:"com.thoughtworks.xstream.core.TreeUnmarshaller"})
with source, collect(sink) as sinks
call tabby.algo.findPath(source, sinks, 10, false, false) YIELD path
return path

image-20230714183956689

第三段

match (source:Method {NAME:"unmarshal",CLASSNAME:"com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter"})
match (sink:Method {NAME:"callReadObject",CLASSNAME:"com.thoughtworks.xstream.core.util.SerializationMembers"})
with source, collect(sink) as sinks
call tabby.algo.findPath(source, sinks, 8, false, false) YIELD path
return path

image-20230714184514612