Java逆向基础之简单的补丁

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java逆向基础之简单的补丁相关的知识,希望对你有一定的参考价值。

本文参考:http://www.vuln.cn/7118

本文参考:《Reverse Engineering for Beginners》Dennis Yurichev著

本文需要用到IDA


简单的补丁

看一个例子

public class nag {
	public static void nag_screen() {
		System.out.println("This program is not registered");
	};

	public static void main(String[] args) {
		System.out.println("Greetings from the mega-software");
		nag_screen();
	}
}

我们怎样去掉打印"This program is not registered"这个字符串?

编译后用IDA载入class文件

作者的IDA view视图同步显示了hex的值,可能装了插件或者改了设置,这里的IDA view视图与hex需要切换视图

ALT+T,搜索文本This program is not registered,定位到相关指令附近

技术分享图片

我们首先尝试将getstatic指令改成返回指令

点击getstatic,然后点击hex视图

技术分享图片

可以看到B2 00 02对应这条指令

右键修改B2 为B1,然后右键应用更改

技术分享图片

再切回IDA view视图

技术分享图片

最后菜单点击Edit-->Patch Program-->Apply patches to input file,将更改应用到文件

技术分享图片

在弹出的对话框点确定即可修改class文件

但是这么修改运行的时候会报错,可能是有一些栈和帧的校验

C:\Users\admin\Desktop>java nag
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: Expecting a stack map frame
Exception Details:
  Location:
    nag.nag_screen()V @1: nop
  Reason:
    Error exists in the bytecode
  Bytecode:
    0x0000000: b100 0212 03b6 0004 b1

        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.privateGetMethodRecursive(Unknown Source)
        at java.lang.Class.getMethod0(Unknown Source)
        at java.lang.Class.getMethod(Unknown Source)
        at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

原作者在JDK1.7下不工作,我在1.8下也是,报的是栈帧映射异常

既然此路不通,那么就选另一条路,去掉nag()方法的调用

找到main方法

技术分享图片

中间的

.line 8

invokestatic nag.nag_screen()V

这一句就是调用nag()方法,查看对应的hex视图

技术分享图片

其中的B8 00 06就是调用这个方法

改成00 00 00(填充3个NOP指令)

技术分享图片

对应的IDA view视图

技术分享图片

变成了3个nop指令

最后菜单点击Edit-->Patch Program-->Apply patches to input file,将更改应用到文件

修改完看运行效果

技术分享图片

修改成功


再看第二个例子

这是一个简单的crackme的例子

public class password {
	public static void main(String[] args) {
		System.out.println("Please enter the password");
		String input = System.console().readLine();
		if (input.equals("secret"))
			System.out.println("password is correct");
		else
			System.out.println("password is not correct");
	}
}

反编译后的class用IDA打开

搜索字符串"secret"定位到判断代码附近

技术分享图片

其中ifeq指令当栈顶int型数值等于0时跳转 ,栈顶存的是String.equals()方法的返回值

首先我们考虑改跳转的位置,改到line 6后面的getstatic指令那里,那么这个指令对应偏移块是多少呢

点击getstatic,状态栏会显示

技术分享图片

这个偏移块是24

目标就是将ifeq met002_35修改成ifeq met002_24

ifeq指令所在偏移块是21,35-21=14对应16进制是E,找出hex视图对应的E

技术分享图片

可以看到99 00 0E,所以我们要修改其中的E

那么改成多少呢,24-21=3对应16进制的3,所以将E改成3

技术分享图片

再看看IDA view视图符不符合预期

技术分享图片

最后菜单点击Edit-->Patch Program-->Apply patches to input file,将更改应用到文件

原作者的修改在JDK1.7下不工作,我这里的JDK1.8也报错了

C:\Users\admin\Desktop>java password
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 24
Exception Details:
  Location:
    password.main([Ljava/lang/String;)V @21: ifeq
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0x0000000: b200 0212 03b6 0004 b800 05b6 0006 4c2b
    0x0000010: 1207 b600 0899 0003 b200 0212 09b6 0004
    0x0000020: a700 0bb2 0002 120a b600 04b1
  Stackmap Table:
    append_frame(@35,Object[#20])
    same_frame(@43)

        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.privateGetMethodRecursive(Unknown Source)
        at java.lang.Class.getMethod0(Unknown Source)
        at java.lang.Class.getMethod(Unknown Source)
        at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

这里必须要提的是,这种改法再JDK1.6上是可以运行的

我们也尝试将if eq 这个占用3个字节的指令用0(NOP指令)填充,结果也是校验失败,不能工作

貌似再JDK1.7上比1.6多了更多的帧栈校验


接下来我们尝试替换整个equals方法,并用iconst_1将常数1压入栈顶,这样后面ifeq判断的时候值始终为flase,就不往偏移块35跳转了

iconst_1的指令是0x04

技术分享图片

即将图中的2B 12 07 B6 00 08改成04 00 00 00 00 00

改完后看下IDA view视图

技术分享图片

改完之后工作正常

以上是关于Java逆向基础之简单的补丁的主要内容,如果未能解决你的问题,请参考以下文章

Java逆向基础之ZKM字符串混淆与还原

201555332盛照宗—网络对抗实验1—逆向与bof基础

20155201 李卓雯 《网络对抗技术》实验一 逆向及Bof基础

逆向及Bof基础实践

20155311高梓云《网络对抗》逆向及Bof基础

20145301赵嘉鑫《网络对抗》逆向及Bof基础