使用 IDEA 快速远程调试 Docker 中运行的 Java 应用程序 (附解决思考过程)

0x01 前言:

最近在复现&分析 Java 领域历史相关漏洞,学习学习 Java 框架漏洞代码审计思路。分析原理少不了调试,然而每次都得搭建漏洞环境,又是构建maven, 又是引入依赖,挺繁琐的。Github 有很多其他同行利用 Docker 搭建好的漏洞环境镜像,一键拉取运行即可, 但是问题来了, 运行在 docker 容器里的程序我怎么断点调试呢?手上没有构建镜像时的源代码,该怎么办呢?


0x02 解决思路:(有兴趣可了解)

Docker 容器里面一般运行的是 java 打包的 jar 包,那么就等于要解决怎么远程调试正在运行的 jar 包?我们先看看本地项目市如何 Debug 的,仔细的你是否察觉到平时IDEA上Debug本地项目的时候都会出现的一行信息?
在这里插入图片描述
为什么 Debug 会出现这么一行信息呢?由于博主学过一些 JVM 虚拟机相关知识 (Java 开发必须了解 JVM😥😥),IDEA Debug 大致过程如下:
在这里插入图片描述

以上过程被称为 JPDA调用体系。

JPDA(Java Platform Debugger Architecture)是 sun 公司开发的 java平台调试体系, 它主要有三个层次组成,即 Java 虚拟机工具接口 (JVMTI) ,Java 调试线协议(JDWP)以及 Java 调试接口(JDI)

  • JVMTI (JVMDI): jdk1.4 之前称为JVMDI,之后改为了JVMTI,它是虚拟机的本地接口,其相当于 Thread 的 sleep、yield native 方法
  • JDWP(Java Debug Wire Protocol):java调试网络协议,其描述了调试信息的格式,以及在被调试的进程(server)和调试器(client)之间传输的请求
  • JDI:java调试接口,虚拟机的高级接口,调试器(client)自己实现 JDI 接口,比如 idea 等其他编译器。

综上我们知道了 IDEA 调试的原理大致如下:

1、先建立起了 socket 连接
2、将断点位置创建了断点事件通过 JDI 接口传给了 服务端(程序端)的 VM,VM 调用 suspend 将 VM 挂起
3、VM 挂起之后将客户端需要获取的 VM 信息返回给客户端,返回之后 VM resume 恢复其运行状态
4、客户端获取到 VM 返回的信息之后可以通过不同的方式展示给客户端


好了,讲了这么多,现在我们知道了本地调试其实也可以认为是远程调试,IDEA 通过 127.0.0.1:20256(端口随机)与 JVM 进行 socket 通信。那么这个端口到底怎么设置的?这就要搬出咱们的 jdk-8xxx-docs-all 官方完整文档 来查阅了👏👏。端口是由 JVM 创建的这毋庸置疑,所以直接点击最下层的 Java HotSpot Client and Server VM 进行查阅:
在这里插入图片描述

进入以后选择对应的操作系统 (当前需要运行的 Java 程序在什么操作系统上,以 Windows 为例):
在这里插入图片描述 跳转以后 Ctrl + f 搜索 Debug 关键字如下:
在这里插入图片描述

文档中详细描述了,启动 Java 程序之前,如果需要 Debug,需要添加参数:-agentlib:jdwp=transport=dt_socket,server=y,address=xxxx 。adderss 填写自定义端口。

👏👏 现在咱们知道 JVM 如何手动开通 Debug 端口了,但是又一个问题来了,IDEA 如何自定义连接 JVM 的呢 ?只要不会咱们就翻官方文档,官方文档往往会带来惊喜。具体如何连接,请自行前往查阅:👉 Tutorial: Remote debug

在这里插入图片描述在这里插入图片描述

由于咱们是引入的别人的docker镜像,咱们手上又没有构建docker镜像时的源代码,咱们最多只能提取 docker 容器中的 jar 包。突然想到我们平时 IDEA 引入第三方 jar 包,只要 Add as Library 操作,jar 包就被打开了,可以看到 “源代码”,并且 jar 包内的ClassName就可以被我们实例化调用,还可以在 jar 包的.class 文件里打断点进行调试。咱们不妨试试这样行不行得通? 事实上是可行的!

在这里插入图片描述


👏👏 OK ,经过这一路上的思考过程,远程调试 Docker 中运行的 Java 程序也就 so easy 啦!

🌟实现步骤:

1、在 docker-compose.yml 配置映射端口让 jvm debug 端口能外部访问。
2、在 docker-compose.yml 中使用 command 字段添加自定义启动命令:java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=xxxx -jar jar包名称.jar
3、容器启动后,从容器中把运行的 jar 包复制出来,新建一个文件夹 ,IDEA 点击 Open 打开这个文件夹, 复制粘贴 jar 包, 右键jar包,选择 Add as Lirary 添加到项目依赖库中,并在代码上打上几个断点。
4、 IDEA 配置 Remote Debug,点击 Debug 运行即可。


0x03 具体操作:

以 fastjson 反序列化漏洞docker镜像为例进行远程调试。

1、在 docker-compose.yml 配置映射端口让 jvm debug 端口能外部访问。

在这里插入图片描述

2、在 docker-compose.yml 中使用 command 字段添加自定义启动命令:java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=xxxx -jar jar包名称.jar

是不是突然发现自己不知道 jar 包名字叫啥?😆😆 咱们可以先启动容器,然后执行 docker ps --no-trunc 不截断输出完整的容器描述,就可以看到容器名称以及容器中的路径。

在这里插入图片描述

3、容器启动后,从容器中把运行的 jar 包复制出来,新建一个文件夹 (例:CVE-2017-18349),IDEA 点击 Open 打开 CVE-2017-18349 文件夹, 复制粘贴 fastjsondemo.jar, 右键jar包,选择 Add as Lirary 添加到项目依赖库中,并在代码上打上几个断点。

启动容器后,执行命令:docker cp 容器id:jar包路径 目标路径, 将 jar 复制出来。
在这里插入图片描述

在这里插入图片描述
4、 IDEA 配置 Remote Debug,点击 Debug 运行即可。

在这里插入图片描述
测试发现远程 debug 失败… 到底是什么原因呢?

请添加图片描述

问题解决: 打开一个自己原先开发的项目,瞅一瞅引入的 jar 包结构是啥样的, 比较区别

在这里插入图片描述Project Structure,Modules->Dependencies 添加要调试的class文件的目录 BOOT-INF

在这里插入图片描述
再次测试远程断点调试是否生效:

在这里插入图片描述
但是还是有问题,断点调试无法进入第三方依赖包中,我们需要把lib文件夹复制到根目录,并右键 Add as Library 。

在这里插入图片描述
在这里插入图片描述

最终远程断点调试的前期准备全部完成,可以快快乐乐的打断点了~


0x04 提醒:

❗️❗️❗️如果你是一名Java开发人员,请注意如果生产环境下迫不得已需要远程调试,调试完一定要关闭JDWP服务,或者JDWP服务监听的端口不对公网开放。❗️❗️❗️

附一篇优秀的 JDWP 服务漏洞利用文章 ===> JDWP调试接口远程命令执行漏洞原理分析

  • 16
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
### 回答1: VS Code是一款非常流行的开发工具,它提供了丰富的功能和插件来支持远程调试。在使用VS Code进行远程调试docker的node.js应用程序时,我们需要进行以下几个步骤。 首先,我们需要在docker容器安装VS Code Server。我们可以通过运行以下命令将VS Code Server添加到我们的Dockerfile: ``` RUN apt-get update && \ apt-get install -y curl && \ curl -fsSL https://code-server.dev/install.sh | sh ``` 然后,我们需要设置docker容器的端口映射,将VS Code Server的端口映射到主机的一个端口上。我们可以使用以下命令来运行docker容器: ``` docker run -d -p 8080:8080 -v "$(pwd):/home/coder/project" my-node-app ``` 这个命令将容器的端口8080映射到主机的端口8080上,并将当前目录挂载到容器的`/home/coder/project`目录。 接下来,我们需要在VS Code安装Remote - Containers插件。我们可以在VS Code的插件商店搜索并安装该插件。 安装成功后,我们可以在VS Code的底部状态栏找到一个绿色的“><”图标。点击该图标,然后选择“Remote-Containers: Attach to Running Container”选项。 在弹出的菜单,我们可以选择我们之前运行docker容器。选择后,VS Code将会连接到docker容器,并在VS Code的界面打开一个新的窗口。 在VS Code,我们可以打开我们的node.js项目,并在需要的位置设置断点。然后,我们可以使用VS Code的调试功能来启动我们的程序,并进行远程调试。我们可以点击VS Code界面左侧的调试图标,然后选择我们的调试配置并点击“启动调试”按钮。 此时,VS Code将会与我们的程序建立远程连接,并在断点处停下。我们可以使用VS Code的调试工具来查看变量的值、单步调试等操作。 通过以上步骤,我们成功地在VS Code实现了远程调试docker的node.js应用程序使用VS Code的强大调试功能,我们可以更方便地进行代码调试和错误排查。 ### 回答2: 要在VSCode远程调试Docker的Node.js应用程序,需要按照以下步骤进行设置和配置。 首先,确保已经在本地安装了VSCode和Docker。 1. 在本地的VSCode安装"Remote - Containers"插件。这个插件可以让我们连接到Docker容器的开发环境。 2. 在Docker设置你的Node.js应用程序。可以在Dockerfile指定要使用的基础镜像,并将Node.js应用程序复制到容器。 3. 创建一个名为".devcontainer"的目录,并在其创建一个名为"devcontainer.json"的文件。在这个文件,可以指定要使用Docker镜像和连接到容器时要运行的命令。 4. 在"devcontainer.json"文件,你还需要配置"ports"选项,以便将容器的端口映射到本地。通过指定要映射的本地端口和容器内部的端口号,可以让VSCode在本地打开容器应用程序。 5. 在VSCode,按下Ctrl + Shift + P,然后选择"Remote-Containers: Open Folder in Container",然后选择项目文件夹。VSCode将会连接到Docker容器。 6. 在VSCode打开你的Node.js应用程序调试视图。点击左侧的调试按钮,然后点击配置按钮,选择Node.js环境。 7. 在VSCode调试视图,点击启动按钮。VSCode将连接到Docker容器的Node.js应用程序,并开始远程调试。 通过按照上述步骤设置和配置,你就可以在VSCode远程调试Docker的Node.js应用程序了。这样,你就可以在本地编写和调试代码,同时在Docker容器运行和测试应用程序。 ### 回答3: 使用VSCode进行远程调试Docker的Node.js应用可以通过以下几个步骤完成。 首先,确保你的机器上安装了VSCode和Docker,并且Docker已经成功安装并运行。 其次,在VSCode安装Remote Development扩展。这个扩展提供了远程开发的功能,并且可以与Docker集成。 接下来,在你的终端或命令行工具使用Docker运行你的Node.js应用。使用适当的Docker命令和参数,将你的应用程序容器化,并确保容器对外暴露了Node.js应用程序调试端口。 然后,打开VSCode并进入扩展的Remotes视图。点击“Attach to Running Container”按钮,并选择你的Node.js应用程序Docker容器。 接下来,在VSCode的调试视图,点击“添加配置”按钮,并选择Node.js环境。在生成的launch.json配置文件,确保指定了正确的远程主机和调试端口。 最后,点击“启动调试”按钮,VSCode将会连接到你的Docker容器,并开始调试你的Node.js应用程序。你可以在VSCode设置断点、查看变量和调试输出,就像在本地开发环境一样。 总结起来,通过这些步骤,你可以很方便地使用VSCode对Docker的Node.js应用进行远程调试,提高开发效率和调试能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0rta1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值