1. 程式人生 > >Cydiasubstrate modules 簡單程式設計之Java Hook 心得篇

Cydiasubstrate modules 簡單程式設計之Java Hook 心得篇

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


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

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函式,也希望瞭解的人給我一個答案。折騰了一天,雖然實現了功能,沒有學到任何東西,除非分析它的工作原理,那麼還是洗洗睡吧