需求场景

可以接触Java程序的运行环境,可以得到jar包,但是不能得到源码,并且程序很复杂,依赖多,配置杂,不好构建本地调试环境。在这样的场景下,如何进行远程调试?

环境介绍

要调试的程序demo.jar

这是一个普通的java程序,功能是打印"Hello, World!",然后循环计数。

正常启动命令:

1
java -jar demo.jar

图片描述

IDEA环境

图片描述

无源码情况下IDEA远程调试JAR包方法

1.加jdwp参数使demo.jar程序支持远程调试

1
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005 -jar demo.jar

图片描述

参数说明:

参数 解释
-agentlib:jdwp 使用Java Debug Wire Protocol(JDWP)来允许远程调试
transport=dt_socket 指定传输协议为socket
server=y 设置为服务器模式。将等待一个调试客户端(如IntelliJ IDEA或Eclipse)连接到它。
suspend=n 如果设置为y,则JVM在启动时会挂起(暂停),直到调试客户端连接。这里设置为n,意味着JVM将立即开始执行,而不会等待调试客户端连接。
address=0.0.0.0:5005 指定监听的IP地址和端口

2.随便建个Java工程,在依赖库里加入demo.jar

使用IDEA新建一个Java控制台窗口程序

1
NewProject->Java->Create project from template->...

图片描述
图片描述
图片描述
图片描述
图片描述

在依赖库中加入demo.jar

1
File->Project Structure->Libraries->点击+->Java->选择demo.jar->...

图片描述
图片描述
图片描述
图片描述
执行完上述操作之后,demo.jar被加到依赖库中。
图片描述

3.添加远程调试配置(Remote JVM Debug)

1
Edit Configurations->点击+->选择Remote JVM Debug->配置远程IP与调试端口->...

图片描述
图片描述
图片描述

4.下断点开始调试

1
在依赖库中点开demo.jar->选中想要调试的class文件->在想要调试的地方下断点->选择远程调试配置->开始调试

图片描述
触发了断点
图片描述
为了展示动态调试能力,这里把i设置为111111并继续运行(在i上右键选择Set Value或者快捷键F2可修改变量的值)。
图片描述
图片描述
发现i已经被动态改变
图片描述

--------------------------------

问题1.如果class文件去掉了调试符号,则断不下来,只能对函数名称处下断点,或者系统函数的代码下断点,这很不方便

(2024.11.11补充,IDEA 2024.2.4)

在没有符号的情况下,对业务代码函数体内的地方下断点失效。
图片描述

对系统函数的代码下断点是可以的,但系统函数断点往往断的很频繁,离关键位置有点远,不方便。
图片描述

在没有符号的情况下,对业务代码的add函数名称处下断点可以断下来,而对业务代码函数体内的地方下断点则断不下来。
图片描述

相关信息

1.javac编译时添加-g:none可以去掉调试符号,或者使用加壳混淆工具基本也可以去掉调试符号。

1
javac -g:none -d . D:\workspace_idea\demo\src\demo.java

如果只是测试,可以把编译好的demo.class替换掉demo.jar里的对应class,会发现去掉调试符号后大小会变小。

2.没有符号的情况下,不清楚如何直接断在业务代码。有个比较繁琐的方法,感觉可行,但未实践。把想要分析的class拉出来反编译成java代码(无符号的demo.class->demo.java),然后把原jar包的资源当作依赖库,把java代码再重新编译成带符号的class(demo.java->有符号的demo.class),最后把带符号的class扔到jar包里。

上传的附件 demo.jar
demo_g_none.jar

最新回复:
guduzhe 2024-07-05 19:37:26
没混淆的直接反编译就行了,搞个混淆过的试试,这种调试也不行。
Jtian 2024-07-05 19:43:17
guduzhe 没混淆的直接反编译就行了,搞个混淆过的试试,这种调试也不行。
针对的是没有对抗,但程序比较复杂,不好本地复现的场景。
知否 2024-07-29 09:31:02
jar已经在服务器运行了,没有办法添加启动参数也可以?如-agentlib:jdwp
appview 2024-10-12 09:54:37
请问大佬如何调试Charles、BurpSuite那种自带jre运行环境的软件?
Jtian 2024-10-13 22:40:58
appview 请问大佬如何调试Charles、BurpSuite那种自带jre运行环境的软件?

称呼师傅即可,大佬不太合适。 通过测试,用文章中说的jdwp远程调试的方法是可以对burpsuite_pro.jar下断点调试的。 简要说明如下: 我的环境中,用"E:\program\BurpSuite\BurpSuitePro202307\jre\bin\java.exe" -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005  "--add-opens=java.desktop/javax.swing=ALL-UNNAMED" "--add-opens=java.base/java.lang=ALL-UNNAMED" "--add-opens=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED" "--add-opens=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED" "--add-opens=java.base/jdk.internal.org.objectweb.asm.Opcodes=ALL-UNNAMED" "-javaagent:E:/program/BurpSuite/BurpSuitePro202307/BurpLoaderKeygen.jar" "-noverify" "-jar" "E:\program\BurpSuite\BurpSuitePro202307\burpsuite_pro.jar" 执行时会报错“Could not find agent library jdwp on the library path, with error: Can't find dependent libraries”,不知道这个是否是你的困惑。其实这个问题无关紧要的,换成自己的java环境就好了。自带的java环境只是方便你使用,不是必须的。 需要注意的是,一般来说要选择好java版本,避免出现兼容性问题。虽然我测试的时候版本是不对应的,不过能跑,能下断点,就没管太多了。


截图里是随便对System.getProperty下的断点,能断下来。本来想下个抓包改包逻辑相关的断点的,这样说明问题会更深刻一些,但不太清楚具体位置,感觉有点麻烦就没折腾了。


KingSelyF 2024-10-14 10:23:52
我有一个写字机的排版软件,就是jar程序,之前不懂还写了jar代理打印里边的类跟变量,这个方法方便多了