学习java怎么能不装模作样的调试一下代码呢,以Shiro为例,漏洞环境最方便的是Vulhub这种漏洞靶场打包好的docker镜像,手上又没有构建docker时的代码,咋调试呢?

代码获取

新建一个空项目

漏洞环境的代码需要从docker中拖出来,以shiro为例,启动之后docker exec -it xxx /bin/bash 进入容器,找到漏洞环境的程序

-w605

可见漏洞环境被打包成了jar,然后通过java -jar启动的,那么把shirodemo-1.0-SNAPSHOT.jar 复制出来,就获取了漏洞环境的全部内容

1
docker cp a7:/shirodemo-1.0-SNAPSHOT.jar ./

还原代码

调试代码需要本地拥有代码文件,jar可以作为Library添加到项目,然后idea会自动将class还原成代码,但是添加之后发现jar中的lib目录还有jar,这里面引入的jar无法再次作为Library添加,所以看不到其中的代码

可以直接将jar解压到项目根目录

-w1128

再将右键lib目录添加到Library,然后打开Project Structure,Modules->Dependencies 添加要调试的class文件的目录BOOT-INF 这里如果不添加的话无法在class文件中的行断点无法击中,只能击中方法断点

-w183

-w1024

注意Project Structure 里要选择一个与远程java版本相同的jdk

这时连接上远程调试端口便可以开始调试了

还原项目的java代码可以使用cfr

1
2
3
brew install cfr-decompiler
cd /usr/local/bin
mv cfr-decompiler cfr

然后就可以使用cfr将class反编译回java代码了

1
cfr shirodemo-1.0-SNAPSHOT.jar --outputdir ./src

远程调试

IDEA其实有添加对docker调试的功能,前提是本地有完整的文件,代码+dockerfile

https://blog.jetbrains.com/cn/2019/07/intellij-idea-docker/

不适用于目前的情况,现在只有个docker镜像,和从里面拖出来编译后的文件

思路就是把拖出来的class或jar ,通过添加为库来获取其中的代码(上一步做的内容),然后像正常调试java程序一样,进入docker容器内部,修改java程序的启动命令,增加调试的支持,之后idea中添加一个remote来连接到docker中的调试端口即可

以idea默认的5005端口为例,修改docker-compose.yml添加一组暴露端口,用来供idea连接至docker内部

1
2
3
4
5
6
7
version: '2'
services:
web:
image: vulhub/shiro:1.2.4
ports:
- "9080:8080"
- "5005:5005"

然后docker-compose up -d正常启动容器

docker exec -it xxxx /bin/bash进入容器,然后想办法找到java程序的启动方式,

比如ps -ax

1
2
3
4
5
root@a7c7e2041409:/# ps -ax
PID TTY STAT TIME COMMAND
1 ? Ssl 0:10 java -jar /shirodemo-1.0-SNAPSHOT.jar
31 pts/0 Ss 0:00 /bin/bash
44 pts/0 R+ 0:00 ps -ax

或者docker-compose up -d之后使用docker ps --no-trunc 来查看容器默认的启动命令

-w1121

找到了程序启动方式,vulhub的shiro环境是java -jar xxx.jar的形式运行的,那么添加对jar程序启动的调试命令即可,在启动docker时用自定义的COMMAND替换默认的COMMAND

修改

1
2
3
4
5
6
7
8
version: '2'
services:
web:
image: vulhub/shiro:1.2.4
ports:
- "9080:8080"
- "5005:5005"
command: java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar /shirodemo-1.0-SNAPSHOT.jar

然后重新docker-compose up -d 即可

idea里添加一个remote

-w1071
点debug,出现Connected to the target VM, address: 'localhost:5005', transport: 'socket'
即是正常连接
-w762

打个断点
-w1123

断点上出现勾号表示成功
command进入方法,再下一个断点同样成功
-w769

-w610
浏览器提交登录请求

-w1123

成功击中断点

IDEA各种断点
https://blog.csdn.net/f641385712/article/details/93145454

对java常见的几种启用调试的方法做了总结

JAR

1
2
3
4
jdk<=1.7
java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n -jar
jdk>1.7
java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n -jar

Tomcat

catalina.sh 中添加

1
2
3
JPDA_TRANSPORT=dt_socket
JPDA_ADDRESS=5005
JPAD_SUSPEND=n

1
CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=60222,suspend=n,server=y"

Weblogic

Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh 中添加

1
2
debugFlag="true"
export debugFlag
⬆︎TOP