Cydiasubstrate modules 簡單編程之Java Hook 心得篇

Cydiasubstrate對於果粉來說一點也不陌生,越獄必備也提供了很多modules供用戶個性化使用。當然Cydiasubstrate也推出了Android版。當然Xposed也能實現了對應的功能,但兩者實現的技術手段有些不一樣,由於Xposed開源,也有不少相關文章分析了實現方式,其主要原理是替換了/system/bin/app_process這個程序,在機子啓動時加載自身的XposedBridge.jar完成對虛擬機的劫持。而Cydiasubstratet並不開源但根據比對兩者"installer",我猜測Cydiasubstrate應該是採用注入的方式完成hook的:




總的來說,要學習還是建議Xposed畢竟是開源,要快速部署我還是比較推薦Cydiasubstrate,畢竟開發簡潔,也支持Native。這一篇文章主要介紹Cydiasubstrate modules 的java開發。官方網站 http://www.cydiasubstrate.com/ 文檔簡單明瞭,也提供了下載地址,也有saurik 就Xposed區別的聲明http://www.cydiasubstrate.com/id/34058d37-3198-414f-a696-73e97e0a80db/

編寫模塊之前我們需要一些部署工作:

1.root手機

由於不捨得拿自己的機子開刀,索性在模擬器上進行了部署我們需要下載一些必備的工具su busybox mkfs.yaffs2.arm下載好了上面必備的工具,我們就開始root 吧

adb shell
#mount -o remount,rw /dev/block/mtdblock0 /system
adb push su /system/bin/
#chmod 4755 /system/bin/su
#exit
adb install super.apk
adb install busybox.apk 

各種安裝好後,在adb shell中執行 su grep等擴展命令成功後,證明我們完成了相應的工作,但這時候別急,如果關掉模擬器的話,是不會寫到對應system.img裏的,當我們下次重新啓動模擬器的時候,一切又回到的原點,所以我們還需要如下操作:

adb shell
#mkdir /filesname
#exit
adb push mkfs.yaffs2.arm /filesname
adb shell
#cd /filesname
#./mkfs.yaffs2.arm /system /filesname/my_system.img
#exit
adb pull /filesname/my_system.img 


接着將該my_system.img替換  $ANDROID_SDK/sdk/system-images/android-xx 下的system.img即可


2.應用設置

安裝好com.saurik.substrate.apk之後


3.模塊開發

首先得先下載Cydiasubstrate SDK,打開AndroidSDK Manager -> tools -> add on site 



不一會就下好了,之後可以開始進行開發,創建一個新工程吧,完成的功能是對系統發送的短信進行監聽,首先將如下關鍵字加入到AndroidManifestxml中:

<meta-data android:name="com.saurik.substrate.main" android:value=".Main"/>
<uses-permission android:name="cydia.permission.SUBSTRATE"/>

AndroidManifestxml如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.rois.hookdroid"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
        <meta-data android:name="com.saurik.substrate.main" android:value=".Main"/>
        
        <activity
            android:name="com.rois.hookdroid.CydiaTest"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    
    <uses-permission android:name="cydia.permission.SUBSTRATE"/>

</manifest>

我新建的項目src目錄如下:



Main是必須包含的,完成一些必要的初始化工作,有initialize函數負責,MS.hookClassLoad的功能在於:當xxxx類要被加載的時候,使用我們自己構造的ClassLoader,我這裏是要hook android.telephony.SmsManager類實現對對短信的監聽,Main如下:

package com.rois.hookdroid;

import com.rois.core.SmsHookClassLoader;
import com.saurik.substrate.MS;



public class Main {
	static void initialize(){
		MS.hookClassLoad("android.telephony.SmsManager", SmsHookClassLoader.getInstance());
	}
}

當然這裏我把對應的ClassLoader繼續了一次封裝,因爲要是對多個類進行hook,代碼也實現在同一個文件我會有強迫症,看官網的教程更加簡潔,SmsHookClassLoader如

下:

package com.rois.core;

import java.lang.reflect.Method;
import android.app.PendingIntent;
import android.util.Log;
import com.rois.utils.Config;
import com.saurik.substrate.MS;

public class SmsHookClassLoader implements MS.ClassLoadHook{
	
	private static SmsHookClassLoader smsHookClassLoader;
	
	public SmsHookClassLoader() {
		super();
	}
	
	public static SmsHookClassLoader getInstance(){
		if (smsHookClassLoader == null) {
			smsHookClassLoader = new SmsHookClassLoader();
		}
		return smsHookClassLoader;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void classLoaded(Class<?> SmsManager) {
        //code to modify the class when loaded
    	Method sendTextMessage;
    	try {
			sendTextMessage = SmsManager.getMethod("sendTextMessage", 
					new Class[]{String.class,String.class,String.class,PendingIntent.class,PendingIntent.class});
			
		} catch (NoSuchMethodException e) {
			sendTextMessage = null;
		}
    	MS.hookMethod(SmsManager, sendTextMessage, new MS.MethodAlteration() {
    		public Object invoked(Object _this,Object... _args) throws Throwable{
    			Log.i(Config.TAG,"SEND_SMS");
    			Log.i(Config.TAG,"destination:"+_args[0]);
    			Log.i(Config.TAG,"source:"+_args[1]);
    			Log.i(Config.TAG,"text:"+_args[2]);
				return invoke(_this, _args);
			}
    	});
    	
    }

}

主要是我們需要實現:

1.MS.ClassLoadHook中的classLoaded(Class<?> xxxx)函數,其表示在android.telephony.SmsManager第一次被加載的時候,我們要執行的classLoaded的功能,這裏我通過反射找到sendTextMessage函數。

2.利用void hookMethod(Class _class, Member member, MS.MethodAlteration alteration);對方法進行hook,第一個參數爲classLoaded傳下來的類參數,第二個參數爲之前反射得到需要hook的方法,第三個參數爲MS.MethodAlteration它完成了最後跳轉的封裝。

3.我們需要實現MS.MethodAlteration.invoked(Object _this, Object... args),在這個方法中完成我們的自定義功能,this表示類,args爲該函數的參數,由於我們是監聽短信發送,所以,僅僅打印log……


通過這個Application標籤,我們知道這段代碼被加載在了com.android.mms 我們的短信進程中進行

Cydiasubstrate很簡潔,這樣下來在hook幾個方法動態分析的demo就搞定了,當然官網說支持native,我看了下demo感覺只是說可以通過native實現功能,好像不能hook native函數,也希望瞭解的人給我一個答案。折騰了一天,雖然實現了功能,沒有學到任何東西,除非分析它的工作原理,那麼還是洗洗睡吧


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章