Hôm nay mình sẽ giới thiệu với các bạn một khả năng cực kì hay ho với một chiếc điện thoại Android đã được root (chiếm quyền quản lý cao nhất trong hệ điều hành Android). Đó chính là hooking.

Hooking là kĩ thuật can thiệp, và thay đổi hành vi của một ứng dụng mà không cần thay đổi mã nguồn (source code) của ứng dụng ấy. Nói cách khác, ứng dụng bị hook sẽ không hề hay biết là nó đã bị thay đổi/chỉnh sửa hoạt động bình thường của nó.

hook-diagram

Ví dụ như chúng ta hook vào ứng dụng System UI (đây là ứng dụng cơ bản được tích hợp sẵn trong Android) để thay đổi biểu tượng cột sóng chẳng hạn.

Dĩ nhiên kĩ thuật này chỉ thực hiện được trên các thiết bị Android đã được root. Ngoài ra nó còn yêu cầu một điều kiện khác nữa là Xposed framework và Xposed Management đã được cài đặt trên máy. Giải thích thêm chút xíu về hai khái niệm này. “Xposed framework” cung cấp môi trường để hook của chúng ta hoạt động, đồng thời cung cấp sẵn thư viện để công việc viết hook trở nên dễ dàng. “Xposed Management” các hook của chúng ta sau khi được tạo ra sẽ cần phải import vào môi trường Xposed, và đó là lý do ta cần “Xposed Management”.

Trước khi đi vào chi tiết mình sẽ vạch ra các bước mà chúng ta sẽ phải đi qua:

1. Một chiếc điện thoại Android được root, có cài sẵn “Xposed framework” và Xposed Management”.

2. Phân tích vị trí (cụ thể là một hàm nào đó- function) nơi mà ta sẽ can thiệp (hook) vào.

3. Tiến hành viết code cho hook của chúng ta.

4. Tiến hành cài đặt hook vào điện thoại và xem kết quả.

 

Bước 1:

Theo như https://forum.xda-developers.com/showthread.php?t=3034811, các bạn tải và cài đặt XposedInstaller_3.1.apk (xposed management) và xposed*.zip (xposed framework).

 

Bước 2:

Bước này cần một chút đọc hiểu mã nguồn (source code) của ứng dụng mà bạn muốn can thiệp.

Các bạn có thể dùng bất cứ công cụ nào trên mạng dùng để dịch ngược mã nguồn của ứng dụng Android (tiếng anh gọi là Apk decompiler).

Ở đây mình sử dụng công cụ Jadx(https://github.com/skylot/jadx).

Giả sử sau khi đọc qua mã nguồn của ứng dụng System UI (đây là ứng dụng của hệ thống Android có package name là “com.android.systemui”), bạn muốn thay đổi màu sắc của đồng hồ hiển thị trên thanh trạng thái (status bar) THÌ các bạn cần phải hook vào hàm “updateClock” nằm trong lớp (class) “com.android.systemui.statusbar.policy.Clock”.

Nói sơ qua hàm “updateClock” một tí. Nó là hàm được gọi đến mỗi giây một lần để vẽ lại kim giờ phút giây của đồng hồ. Vì thế hook vào hàm này chắc chắn sẽ làm giảm hiệu suất đáng kể của hệ thống. Vì đây chỉ là một ví dụ nên chúng ta tạm thời bỏ qua vấn đề hiệu suất, nhưng trong tương lai ở một ứng dụng cụ thể thì chúng ta nên tránh hook vào những hàm được gọi đến nhiều lần.

 

Bước 3:

Đây là bước thực hành để tạo ra một con hook nhằm thực hiện ý đồ đã nói ở trên, thực tế việc tạo hook cũng giống như tạo một ứng dụng Android thông thường vậy. Các bước như sau:

1. Tạo project rỗng trong Android Studio.

2. Tạo metadata để Xposed Management nhận dạng được con hook của chúng ta. Giống như khai lý lịch bản thân vậy á.

3. Import thư viện Xpose Bridge

4. Tạo ra một class bất kì của chúng ta mà cài đặt (implement) XposedHookLoadPackage interface.

Ở bước 2, các bạn thêm metadata sau vào file AndroidManifest.xml. Tên của từng metadata cũng đã nói lên ý nghĩa của nó.

<application android:label="Red clock example" >
<meta-data android:name="xposedmodule" android:value="true" />
<meta-data android:name="xposeddescription" android:value="It's me" />
<meta-data android:name="xposedminversion" android:value="82" />
</application>

Tiếp theo là bước 3, import thư viện. Các bạn mở file build.grade và thêm vào như sau:

repositories {
    jcenter();
}

dependencies {
    provided 'de.robv.android.xposed:api:82'
    provided 'de.robv.android.xposed:api:82:sources'

}

Kế tiếp chúng ta tạo ra một class với tên bất kì, nhưng phải được implement IXposedHookLoadPackage interface

public class Example implements IXposedHookLoadPackage  {
    static final String MY_PACKAGE_NAME = "com.example.nhanbach.testxposed3";
   public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
        if (!lpparam.packageName.equals("com.android.systemui"))
            return;

        findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "updateClock", new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                // this will be called before the clock was updated by the original method
            }
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                // this will be called after the clock was updated by the original method

                TextView tv = (TextView) param.thisObject;
                String text = tv.getText().toString();
                tv.setText(text + " :)");
                tv.setTextColor(Color.RED);
            } 
}); } }

Một chút bàn luận về IXposedHookLoadPakage interface. Bên trong nó có một phương thức handleLoadPakage mà sẽ được Xposed framework gọi khi nó duyệt qua tất cả các package trong hệ thống.

Phương thức findAndHookMethod sẽ tìm và hook vào hàm mà chúng ta mong muốn, ở đây là hàm updateClock nằm trong lớp com.android.systemui.statusbar.policy.Clock.

Phương thức findAndHookMethod sẽ nhận 4 tham số như sau: class_name, class_loader, method_name, và callback. Mình sẽ giải thích thêm về tham số cuối cùng callback. Về ý nghĩa, callback là nơi chúng ta sẽ đặt code chỉnh sửa ở đây, và hàm callback này có thể sẽ được gọi trước hoặc sau hàm updateClock. Tuy nhiên thực tế như đoạn code ở trên, các bạn thấy nó nhận vào một đối tượng XC_MethodHook chứa 2 phương thức beforeHookedMethod (hàm này được gọi trước khi hàm updateClock được gọi) và afterHookedMethod (hàm này được gọi sau khi hàm updateClock thực hiện xong). Như vậy từ lý thuyết đến thực tế thì tham số callback có một chút thay đổi về hình thái nhưng nội dung bản chất vẫn giữ nguyên.

 

Bước 4:

Đến lúc này chúng ta sẽ Run project này trên điện thoại. Mở Xposed Management ra, chúng ta sẽ thấy chương trình hook của chúng ta đã xuất hiện như một module và có thể được active hoặc deactive bất cứ lúc nào.

Lúc này hãy active chương trình hook của chúng ta và khởi động lại điện thoại. Nếu như bạn làm đúng các thao tác, đồng hồ trên thanh status bar sẽ chuyển sang màu đỏ.

 

Tóm lại, bạn có thể làm rất nhiều trò khác thú vị hơn với kỹ thuật hooking này. Tuy nhiên một điểm lưu ý duy nhất là kĩ thuật này nếu được cài đặt không khéo sẽ dẫn đến giảm hiệu suất đáng kể của điện thoại (hay còn gọi là leak memory). Để tránh điều này thì các bạn cần tránh tối đa hook vào các phương thức được gọi nhiều lần thường xuyên. Và đặc biệt là bạn phải có kĩ năng đọc mã nguồn khá tốt để biết vị trí nơi cần đặt hook.

 

Nguồn: https://github.com/rovo89/XposedBridge/wiki/Development-tutorial