Libraries

发布日期:2019年02月10日 类别:pwn 题目来源:ctflearn.com 题目链接:https://ctflearn.com/problems/393 (需要注册登录)

这道题与 Java 及 JNI 有关。登录到主机后,看一下目录:

dir

flag 仍然存放在 flag.txt 中,并且提供了源代码。

点击此处显示 Writeup
点击此处隐藏 Writeup

这道题的主要问题部分在 Helloworld.java 中:

首先我们关注到 19 行处,如果字符串 msg 中包含了“flag”,那么程序就会打印出真正的 flag。msg 本身是不包含“flag”的,但这段 Java 程序通过 JNI 调用了一个动态链接库的函数。看来我们需要从这个地方下手。

同时注意到 43 行在拷贝自身资源中的动态链接库文件时,直接 catch 住了所有的异常,这意味着即使复制失败了,程序也会继续执行。再往上看几行,32 行处构造动态链接库目录时使用了 user.home 这一系统属性,而这个属性是可以从环境变量中注入的。至此思路大致就清晰了:首先我们需要传入一个自定义的 user.home 路径,其中包含了我们自己的 libhello.so,进而在 print 函数中修改字符串的值。

那么如何设置 user.home 呢?首先想到的是在 Java 虚拟机启动时使用命令行参数传入。但是由于在程序入口 hellotest.cpp 中固定了传入虚拟机参数,我们无法使用这种方法:

但除了直接通过命令行参数的方式将属性传给 Java 虚拟机,我们还有另一种传入属性的方法:_JAVA_OPTIONS 环境变量。我们只需要在这个环境变量中写好虚拟机的参数,与直接通过命令行参数传入是一样的。因此只需使用

_JAVA_OPTIONS=-Duser.home=/tmp/test ./hellotest

启动程序就可以了。此时程序会输出 Picked up _JAVA_OPTIONS: -Duser.home=/tmp/test,这就表示我们成功地将 user.home 改为 /tmp/test了。

下一步就是设计我们自己的 libhello.so。首先看一下原版的 hellolib.c 的内容:

OK,就是打印出传入的字符串。下面我们需要通过反射把 msg 的内容改变:

将我们自己编译生成出的 libhello.so 放入 /tmp/test/.helloWorld/ 目录中,并使用 chmod -wx 将文件权限设为只读,这样才不会被 Helloworld.java 中的 File.copy 所覆盖。

执行一下 _JAVA_OPTIONS=-Duser.home=/tmp/test ./hellotest,程序就能够成功打印出 flag 了。

dontpan1c 的 CTF 笔记
南阳一出即相,淮阴一出即将。

知识共享许可协议

本站所有作品均采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

本站不包含明令禁止公开解题过程的题目。

本站由 Jekyll 强力驱动。