为了账号安全,请及时绑定邮箱和手机立即绑定

Java逆向基础之异常

标签:
Java

异常

由之前月份处理修改的例子

//清单1IncorrectMonthException.java

public class IncorrectMonthException extends Exception {	private int index;	public IncorrectMonthException(int index) {		this.index = index;	}	public int getIndex() {		return index;	}}

//清单2Month2.java

class Month2 {	public static String[] months = { "January", "February", "March", "April", "May", "June", "July", "August",			"September", "October", "November", "December" };	public static String get_month(int i) throws IncorrectMonthException {		if (i < 0 || i > 11)			throw new IncorrectMonthException(i);		return months[i];	};	public static void main(String[] args) {		try {			System.out.println(get_month(100));		} catch (IncorrectMonthException e) {			System.out.println("incorrect month index: " + e.getIndex());			e.printStackTrace();		}	};}

编译

javac Month2.java

只写一个Month2.java,这里是IncorrectMonthException.java也会自动编译

反编译

javap -c -verbose Month2.classjavap -c -verbose IncorrectMonthException.class

IncorrectMonthException方法

 public IncorrectMonthException(int);    descriptor: (I)V    flags: ACC_PUBLIC    Code:      stack=2, locals=2, args_size=2         0: aload_0         1: invokespecial #1                  // Method java/lang/Exception."<init>":()V         4: aload_0         5: iload_1         6: putfield      #2                  // Field index:I         9: return

本质上,IncorrectMonthException类只是做了对象构造,还有访问器方法。IncorrectMonthException类是继承于Exception类,所以,IncorrectMonthException类构造之前,构造父类Exception,然后传递整数给IncorrectMonthException类作为唯一的属性值

getIndex方法

 public int getIndex();    descriptor: ()I    flags: ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1         0: aload_0         1: getfield      #2                  // Field index:I         4: ireturn

getIndex()只是一个访问器,引用到IncorrectMonthException类,被传到局部变量的索引值0的位置(this指针),用aload_0指令取得, 用getfield指令取得对象的整数值,用ireturn指令将其返回。


再看Month2.class的get_month方法

  public static java.lang.String get_month(int) throws IncorrectMonthException;    descriptor: (I)Ljava/lang/String;    flags: ACC_PUBLIC, ACC_STATIC    Code:      stack=3, locals=1, args_size=1         0: iload_0         1: iflt          10         4: iload_0         5: bipush        11         7: if_icmple     19        10: new           #2                  // class IncorrectMonthException        13: dup        14: iload_0        15: invokespecial #3                  // Method IncorrectMonthException."<init>":(I)V        18: athrow        19: getstatic     #4                  // Field months:[Ljava/lang/String;        22: iload_0        23: aaload        24: areturn

部分指令解释

0: iload_0 //第0个变量(即变量i)压入操作数栈

1: iflt 10 //当栈顶int型数值小于0时跳转到偏移块10(这里是从栈顶弹出一个值进行比较)

4: iload_0 //第0个变量(即变量i)压入操作数栈

5: bipush 11 //将11压入操作数栈

7: if_icmple 19 //会从栈中弹出两个值进行比较,如果第二个(变量i)小于或者等于第一个(数字11),那么跳转到偏移位19

10: new #2 // class IncorrectMonthException //创建IncorrectMonthException对象的引用并压入栈顶

13: dup //复制栈顶值压入栈顶

14: iload_0 //第0个变量(即变量i)压入操作数栈

15: invokespecial #3 // Method IncorrectMonthException."<init>":(I)V //调用IncorrectMonthException的"<init>"方法,这里需要从栈顶弹出两个值,1是IncorrectMonthException对象的引用,2是变量i

18: athrow //将栈顶的异常抛出

19: getstatic #4 // Field months:[Ljava/lang/String; //获取静态成员months数组的引用压入栈

22: iload_0 //第0个变量(即变量i)压入操作数栈

23: aaload //栈顶弹出两个值,将引用型数组指定索引的值推送至栈顶,这里索引i为第一个弹出值,数组引用months为第二个弹出值,即months[i]的值送入栈顶

24: areturn //返回栈顶值


Month2.class的main方法

  public static void main(java.lang.String[]);    descriptor: ([Ljava/lang/String;)V    flags: ACC_PUBLIC, ACC_STATIC    Code:      stack=3, locals=2, args_size=1         0: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;         3: bipush        100         5: invokestatic  #6                  // Method get_month:(I)Ljava/lang/String;         8: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V        11: goto          47        14: astore_1        15: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;        18: new           #8                  // class java/lang/StringBuilder        21: dup        22: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V        25: ldc           #10                 // String incorrect month index:        27: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;        30: aload_1        31: invokevirtual #12                 // Method IncorrectMonthException.getIndex:()I        34: invokevirtual #13                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;        37: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;        40: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V        43: aload_1        44: invokevirtual #15                 // Method IncorrectMonthException.printStackTrace:()V        47: return      Exception table:         from    to  target type             0    11    14   Class IncorrectMonthException

注意Exception table:文字以及下面的表数据

异常表的第一行数据表示从0到11行若发生异常,则跳转到偏移块14的位置,同时也指明异常的类型为IncorrectMonthException类

异常从偏移块14开始执行,如果没有这个异常表的数据,则偏移块14后的指令不会被执行


这有个例子,IDA是如何显示异常表:

原作者用的自己电脑里的random.class,这里用刚才的Month2.class替代

    .catch IncorrectMonthException from met003_begin to met003_11 using \met003_14



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消