多读书多实践,勤思考善领悟

Java逆向基础之二十二.Byteman

本文于1983天之前发表,文中内容可能已经过时。

Byteman的是由Jboss发明主要是为了支持多线程和多JVM测试的自动化。

Byteman规则语言提供了一组标准的内置操作,这些操作支持特定的上述类别中的任务

为了简化测试自动化,Byteman已经与两种流行的测试框架JUnit和TestNG集成

在逆向中,我们也可以利用Byteman来帮助我们分析方法的调用

1. 安装

Byteman下载地址:http://byteman.jboss.org/downloads.html

环境变量配置

1
BYTEMAN_HOME = C:\byteman-download-4.0.2

PATH添加%BYTEMAN_HOME%\bin

安装验证

1
bmcheck

QQ截图20180502083044.png

2. 看一个例子

HelloWorld.java

1
2
3
4
5
6
//HelloWorld.java
public class HelloWorld {
public static void main(String[] argv) {
System.out.println("Hello, world!");
}
}

规则文件appmain.btm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#appmain.btm
RULE trace main entry
CLASS HelloWorld
METHOD main
AT ENTRY
IF true
DO traceln("entering main")
ENDRULE

RULE trace main exit
CLASS HelloWorld
METHOD main
AT EXIT
IF true
DO traceln("exiting main")
ENDRULE

编译

1
javac HelloWorld.java

运行

1
java HelloWorld

规则检查

1
bmcheck -cp . -v appmain.btm

Byteman运行

1
java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=script:appmain.btm HelloWorld

运行结果

QQ截图20180502084108.png

规则文件定义

1
2
3
4
5
6
7
8
# 规则骨架
RULE <规则名>
CLASS <类名>
METHOD <方法名>
BIND <绑定事件>
IF <条件>
DO <动作>
ENDRULE

在脚本中我们使用了traceln语句,那么这个调用的其实是Byteman的org.jboss.byteman.rule.helper.Helper类的方法,这些方法都是已经内置的,可以直接在脚本中调用。我们也可以扩展Helper类进行调用。

从上面我们可以看出Byteman的使用方法:1.写规则文件,2.写Helper类的扩展方法(可选),3.指定脚本文件调用

3. 再看一个例子

输出参数和返回值

Main.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.vvvtimes;

public class Main {

public int add(int x, int y) {
return x + y;
}

public int add(int x, int y, int z) {
return x + y + z;
}

public static void main(String[] argv) {
Main m = new Main();
System.out.println(m.add(1, 2));
System.out.println(m.add(1, 2, 3));
}
}

规则文件appmain.btm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
RULE trace arg1
CLASS com.vvvtimes.Main
METHOD add(int,int)
AT ENTRY
IF true
DO traceln("arg1=" + $1 + " arg2=" + $2)
ENDRULE
RULE trace return value1
CLASS com.vvvtimes.Main
METHOD add(int,int)
AT EXIT
IF true
DO traceln("Return value: " +$!)
ENDRULE
RULE trace arg2
CLASS com.vvvtimes.Main
METHOD add(int,int,int)
AT ENTRY
IF true
DO traceln("arg1=" + $1 + " arg2=" + $2 + " arg3=" + $3)
ENDRULE
RULE trace return value2
CLASS com.vvvtimes.Main
METHOD add(int,int,int)
AT EXIT
IF true
DO traceln("Return value: " +$!)
ENDRULE

编译

1
javac com/vvvtimes/Main.java

运行

1
java com.vvvtimes.Main

规则检查

1
bmcheck -cp . -v scripts/appmain.btm

byteman运行

1
java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=script:scripts/appmain.btm com.vvvtimes.Main

运行结果

QQ截图20180502110959.png

这里的$0指的是当前对象。$1指的是当前方法的第一个参数,如果有多个参数,数字依次增长。$!指返回值,AT与AFTER同义

需要注意的是,RULE的语法规则中的CLASS METHOD都不支持通配符模式,逆向中如果用这个规则去写会很麻烦,官方建议用批量脚本去生成。。。

所以如果同名方法很多,还是用前面的AspectJ去找吧

更多内容可参考docs/byteman-programmers-guide.pdf

网上有个追踪局部变量的没啥用。需要-g编译,逆向中用不了

4. 扩展Helper类

看一个例子

新建目标项目和扩展Helper类项目,结构如下

QQ截图20180503133008.png

其中目标项目使用上一篇博客的第二个例子的代码

扩展Helper类项目需要用到第三方jar,在C:\byteman-download-4.0.2\lib找到byteman.jar复制过来

TraceHelper.java代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.vvvtimes;

import org.jboss.byteman.rule.Rule;
import org.jboss.byteman.rule.helper.Helper;

public class TraceHelper extends Helper {

protected TraceHelper(Rule rule) {
super(rule);
}

public boolean myprint(String message) {
return super.traceln("!!! IMPORTANT EVENT !!!" + message);
}
}

将这个项目导出为BytemanHelperDemo.jar

目标项目里的规则文件tracing.btm内容如下,其中HELPER项指定自定义了Helper类名

1
2
3
4
5
6
7
8
RULE trace return value1
CLASS com.vvvtimes.Main
METHOD add(int,int)
HELPER com.vvvtimes.TraceHelper
AT EXIT
IF true
DO myprint("Return value: " +$!)
ENDRULE

编译

1
javac com/vvvtimes/Main.java

运行

1
java com.vvvtimes.Main

加helper类的规则文件检查,注意多了个-cp BytemanHelperDemo.jar

1
bmcheck -cp . -cp BytemanHelperDemo.jar  -v scripts/tracing.btm

byteman运行

1
java -cp ".;BytemanHelperDemo.jar;%CLASSPATH%" -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=script:scripts/tracing.btm com.vvvtimes.Main

运行结果如下

QQ截图20180503135751.png

如果我们将上面的目标项目打包成jar,则命令可以改成如下形式

目标项目打包成的jar名为BytemanDemo2.jar

运行

1
java -cp "BytemanDemo2.jar;%CLASSPATH%" com.vvvtimes.Main

加helper类的规则文件检查

1
bmcheck -cp BytemanDemo2.jar -cp BytemanHelperDemo.jar  -v scripts/tracing.btm

byteman运行

1
java -cp "BytemanDemo2.jar;BytemanHelperDemo.jar;%CLASSPATH%" -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=script:scripts/tracing.btm com.vvvtimes.Main

运行结果如图

QQ截图20180503135840.png

5. 运行后注入

Byteman可以在目标程序运行后进行注入,命令如下

运行后注入

  1. 查看java进程,找到目标进程的pid
1
jps
  1. 安装pid
1
bminstall <pid>
  1. 装载规则脚本
1
bmsubmit -l tracing.btm

//指定监听端口默认是9091

//bmsubmit -p -l tracing.btm

  1. 卸载规则脚本
1
bmsubmit -u tracing.btm

//指定监听端口

//bmsubmit -p -u tracing.btm

规则文件如果用到了自定义的扩展Helper类,需要先加载扩展类的jar包

  1. 装载jar包
1
bmsubmit -s helpers.jar
  1. 装载规则脚本
1
bmsubmit -l tracing.btm

看一个例子

Main.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Main.java
package com.vvvtimes;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {

public static void main(String[] args) {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("please input the first param:");
String p1 = bufferedReader.readLine();
System.out.println("please input the first param:");
String p2 = bufferedReader.readLine();
System.out.println("result is " + add(Integer.parseInt(p1), Integer.parseInt(p2)));
System.out.println("press ENTER TO EXIT ...");
bufferedReader.readLine();
} catch (Exception e) {
e.printStackTrace();
}
}

public static int add(int a, int b) {
return a + b;
}
}

tracing.btm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
RULE trace arg1
CLASS com.vvvtimes.Main
METHOD add(int, int)
AT ENTRY
IF true
DO traceln("arg1=" + $1 + " arg2=" + $2)
ENDRULE


RULE trace return value1
CLASS com.vvvtimes.Main
METHOD add(int, int)
AT EXIT
IF true
DO traceln("Return value: " +$!)
ENDRULE

编译

1
javac com/vvvtimes/Main.java

运行

1
java com.vvvtimes.Main

新开窗口查看注入到Main进程

查看进程

1
jps

安装pid

1
bminstall 6852

规则检查

1
bmcheck -cp . -v scripts/tracing.btm

装载规则脚本

1
bmsubmit -l scripts/tracing.btm

之后回到Main窗口输入参数

运行结果如下

QQ截图20180509110435.png

QQ截图20180509110550.png