本文基于 VSCode 与 Maven 在 Win 10 配置 java 漏洞调试环境,并未使用 IDEA 与 Gradle

是的我用 VSCode 调 java,事实证明 IDEA 更好用,由于我懒得申请学生账号才用这么别扭的方法调 java,本文仅供参考

jdk 多版本安装与切换

对于某些漏洞,需要使用较旧版本的 jdk,例如 CC1 链在 jdk8u71 版本被修复,我们使用 8u71 之后的 jdk 版本就无法成功复现该链子

为了方便地在各种 jdk 版本之间切换,我们可以同时安装多个版本的 jdk

安装特定版本 JDK

以 jdk8u65 和 jdk8u71 为例

https://www.oracle.com/java/technologies/downloads/archive/ 找到 java8

img

点进去找到要安装的 jdk 小版本

jdk8u71:

img

jdk8u65:

img

根据自己的系统版本下载对应的 jdk 安装包,注意是 jdk,也就是 Java SE Development Kit

别误下载了 jre,也就是 Java SE Runtime Environment

在 Oracle 官网下载 JDK 是需要登录 Oracle 账号的,没有的话请先注册一个

如果你的电脑是 win10,下载完成后你应该能找到下面这样的安装包

img

运行程序安装即可

我们不需要独立 JRE,所以该模块我们将其设置为 “不可用”

img

然后修改一下 JDK 的安装路径,你喜欢默认安装路径就别改

img

然后点击 “下一步” 安装即可,我就都安装到 d:/Java 里了

img

配置环境变量

环境变量配置:

JAVA_HOME=这里填JDK的安装路径
PATH=%JAVA_HOME%/bin;%JAVA_HOME%/jre/bin

以防万一,这里提醒一下,不要把 PATH 变量中的其他内容给删掉

以我安装的 jdk8u65 为例

img

img

在终端使用 java -versionjavac -version 验证安装

img

安装 VSCode 插件

直接找到微软提供的整合包安装即可

img

切换 JDK 版本

需要切换 jdk 版本时,修改 JAVA_HOME 即可,这里从 8u65 切换到 8u71

img

对于较高版本的 jdk,是不存在 %JAVA_HOME%/jre 这个文件夹的

但是没有关系,按照前面的方法配置环境变量,照样能够正常使用

来跑个 HelloWorld

新建 d:/MyCode/java 文件夹,创建 hello.java

public class hello {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

javac hello.java; java hello 编译执行

img

输出了 Hello World,确认 jdk 可以正常使用

Maven 安装与配置

Maven 是 Apache 基金会维护的一个 Java 构建工具,需要研究一些第三方 java 包中的漏洞时,就可以用 Maven 下载这些包

安装 Maven

到 Maven 官网:https://maven.apache.org/ 中下载 maven 安装包

img

下载后解压到你喜欢的路径中

img

然后添加环境变量

PATH=Maven安装路径/bin

在终端使用 mvn -v 验证安装

img

配置 Maven

Maven 安装路径下存在一个 conf 文件夹,里面的 settings.xml 是 Maven 的配置文件

修改 Maven 仓库路径

Maven 默认将软件包存储在 用户家目录/.m2/repository/ 下,通过 localRepository 标签我们可以更改本地仓库的路径

img

添加镜像源

默认源服务器位于国外,下载速率可能较慢,而且受网络波动的影响会比较大

这时我们可以配置一些位于国内的源服务,通过 mirrors 标签进行设置

以阿里云为例,我们向 mirrors 标签中添加如下内容即可

<mirror>
  <id>aliyunmaven</id>
  <mirrorOf>*</mirrorOf>
  <name>阿里云公共仓库</name>
  <url>https://maven.aliyun.com/repository/public</url>
</mirror>

img

下面是对配置项的解释

配置项 意义
id 镜像源的唯一 id
mirrorOf 指定哪些软件包需要使用该镜像源进行下载,设置为 * 即所有软件包都使用该镜像源
name 镜像源的名称
url 镜像源的地址

配置 VSCode Maven 插件

在 settings.json 中添加 maven-settingsFilejava.configuration.maven.globalSettings

img

将 Maven 的配置文件所在路径填入即可

来跑个 HelloWorld

到 Maven 官网中能找到一个快速创建 Maven 项目模板的命令

img

mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 -DinteractiveMode=false

-DgroupId 修改为你的组织id,一般来说使用倒置域名,例如 cn.caterpie.app

-DartifactId 修改为项目名称

其余选项保持默认即可,运行该命令,就会在当前目录创建一个符合 Maven 项目结构的文件夹

img

img

使用 vscode 打开该项目,能看到:

img

其中的 App.java 中已经包含了 HelloWorld 代码

img

使用 mvn compile package 编译并打包项目

然后使用 java -cp target/生成的jar包 组织id.App 运行

img

调试环境搭建

jdk 提供的部分核心类是只有字节码的(也就是 class 文件)

我们启动调试的时候要想跟进某段代码,就必须有源代码(也就是 java 文件)

为了调试某个与核心类有关的漏洞,我们要想办法拿到这些字节码的 java 源码

从 OpenJDK 中获取核心类源码

以 jdk8u 为例,到 https://hg.openjdk.org/jdk8u/jdk8u/jdk/tags 查找 openjdk 的仓库

然后找到 tag 为 jdk8u65 和 jdk8u71 的提交记录,下载源码包

img

解压后在 src\share\classes 目录即可找到源码

img

一般来说关注 sun 包中的代码即可

接下来需要让 vscode java 插件读取源码内容,这里是最恶心的地方,IDEA 在这个方面可以说完爆 vscode

首先我们要有一个 java 项目,可以是 maven 项目也可以是普通的 java 项目

无论是哪一种 java 项目,我们要引入的源码内容都无法超出项目根目录,也就是说我们的 sun 包(或其他你想引入的软件包)源码必须要在项目目录之下

当然你不需要把整个 sun 文件夹复制到你的项目里,只需要使用一个软链接即可

img

然后在 pox.xml 中添加源码目录,这里使用 build-helper-maven-plugin 插件实现

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>build-helper-maven-plugin</artifactId>
  <version>3.3.0</version>
  <executions>
    <execution>
      <id>add-source</id>
      <phase>generate-sources</phase>
      <goals>
        <goal>add-source</goal>
      </goals>
      <configuration>
        <sources>
          <source>src/main/java</source> <!-- 默认源代码目录 -->
          <source>source_jdk8u65</source> <!-- 自定义源代码目录 -->
        </sources>
      </configuration>
    </execution>
    <execution>
      <id>add-test-source</id>
      <phase>generate-test-sources</phase>
      <goals>
        <goal>add-test-source</goal>
      </goals>
      <configuration>
        <sources>
          <source>src/test/java</source> <!-- 默认测试源代码目录 -->
        </sources>
      </configuration>
    </execution>
  </executions>
</plugin>

此时 VSCode 查找某函数或属性等引用的时候就能找到 jdk 核心类中的引用,在调试模式下也能够正常跳转到 jdk 核心类的代码段中

img

不过 VSCode 有一个致命的问题,那就是它会对引入的 jdk 源码进行语法检查(IDEA 使用 SDKs 添加 jdk 源码路径的时候,是不会做语法检查的,因为没有必要),导致花费大量的系统资源,还会产生大量的错误提示

img

所以大伙有条件的话还是用 IDEA 吧 😅

获取依赖项源码

vscode 管理的 maven 项目似乎会自动下载依赖项源码 🤔

实际调试体验

目前尝试使用这种方式调试了几条 CC 链,体验还行

不过每次启动项目的时候速度都比较慢,因为 VSCode java 插件非要分析一通我引入的 jdk 源码

img