1. 程式人生 > >Java逆向基礎之初識AspectJ

Java逆向基礎之初識AspectJ

java 逆向 aspectj

AspectJ是一個面向切面編程的框架,它擴展了Java語言。AspectJ定義了AOP語法所以它有一個專門的編譯器用來生成遵守Java字節編碼規範的Class文件。

AspectJ目前支持以下三種編織的方式

編譯時編織:把aspect類(aop的切面)和目標類(被aop的類)放在一起用ajc編譯。

後編譯時編織:目標類可能已經被打成了一個jar包,這時候也可以用ajc命令將jar再編織一次

加載時編織Load-time weaving (LTW):在jvm加載類的時候,做字節碼修改或替換

逆向工程中可以用到後兩個:後編譯時編織和加載時編織。


1.安裝AspectJ

下載地址:http://www.eclipse.org/aspectj/downloads.php

選擇裏面的1.9版本下載,下載完成之後是個jar包

安裝命令

java -jar aspectj-1.9.1.jar

根據提示設置好java主目錄和aspectj的安裝目錄,這裏采用默認的C:\aspectj1.9

安裝完成後,設置如下環境變量

設置ASPECTJ_HOME

ASPECTJ_HOME = C:\aspectj1.9

添加/修改CLASSPATH,把aspectjrt.jar添加進去

CLASSPATH = .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar;%ASPECTJ_HOME%\lib\aspectjrt.jar

PATH變量新增值

%ASPECTJ_HOME%\bin

環境變量設置完成之後,驗證命令

ajc -version

出現如下結果說明環境變量配置成功

技術分享圖片


2.看兩個簡單的例子

第一個項目helloworld

Java文件HelloWorld.java

//HelloWorld.java
public class HelloWorld {
	public void sayHello() {
		System.out.println("Hello, world!");
	}

	public static void main(String[] argv) {
		HelloWorld hw = new HelloWorld();
		hw.sayHello();
	}
}

Aspectj文件MyAspect.aj

//MyAspect.aj
public aspect MyAspect {
	pointcut say():call(void HelloWorld.sayHello());

	before():say() {
		System.out.println("before say hello....");
	}

	after():say() {
		System.out.println("after say hello....");
	}
}

Load-time weaving (LTW) 加載時編織命令

編譯

ajc -outjar myjar.jar HelloWorld.java
ajc -outjar MyAspect.jar -outxml MyAspect.aj  -classpath "myjar.jar;%CLASSPATH%"

運行

aj5 -classpath "MyAspect.jar;myjar.jar;%CLASSPATH%" HelloWorld

運行結果

技術分享圖片

可以看到在helloworld字符串上有上下兩行文字


第二個項目,輸出參數和返回值

java文件Main.java

//Main.java
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[] args) {
		Main m = new Main();
		System.out.println(m.add(1, 2));
		System.out.println(m.add(1, 2, 3));
	}
}

Aspectj文件Tracing.aj

//Tracing.aj
public aspect Tracing {
	private pointcut mainMethod():
            execution(public static void main(String[]));

	before(): mainMethod() {
		System.out.println("> " + thisJoinPoint);
	}

	after(): mainMethod() {
		System.out.println("< " + thisJoinPoint);
	}

	private pointcut addMethod():
            execution(public int add(..));

	before(): addMethod() {
		System.out.println("> " + thisJoinPoint);
		Object[] args = thisJoinPoint.getArgs();
		for (int i = 0; i < args.length; i++) {
			System.out.println("args[" + i + "]: " + thisJoinPoint.getArgs()[i].toString());
		}

	}

	after(): addMethod() {
		System.out.println("< " + thisJoinPoint);
	}

	after() returning(Object o) :addMethod(){
		System.out.println("Return value: " + o.toString());
	}
}

編譯

ajc -outjar myjar.jar com/vvvtimes/Main.java
ajc -outjar Tracing.jar -outxml Tracing.aj  -classpath "myjar.jar;%CLASSPATH%"

運行

aj5 -classpath "Tracing.jar;myjar.jar;%CLASSPATH%" com.vvvtimes.Main

運行結果

技術分享圖片

可以看到,add方法的參數和返回值都打印出來了


順便說一下三個編織期的區別,從命令行角度比較如下:

Compile-time weaving 編譯時編織

ajc -outjar mytarget.jar HelloWorld.java MyAspect.aj

運行

aj5 -classpath "mytarget.jar;%CLASSPATH%" HelloWorld


Post-compile weaving 後編譯時編織

ajc -outjar myjar.jar HelloWorld.java
ajc -inpath myjar.jar MyAspect.aj -outjar mytarget.jar

運行

aj5 -classpath "mytarget.jar;%CLASSPATH%" HelloWorld


Load-time weaving (LTW) 加載時編織

編譯

ajc -outjar myjar.jar HelloWorld.java
ajc -outjar MyAspect.jar -outxml MyAspect.aj  -classpath "myjar.jar;%CLASSPATH%"

運行

aj5 -classpath "MyAspect.jar;myjar.jar;%CLASSPATH%" HelloWorld


Java逆向基礎之初識AspectJ