# Analyze a Mobile Malware

# Lý thuyết

### Giới thiệu về mã độc file Helper

* Đây là mã độc được giả dạng trông như một ứng dụng trợ giúp tệp hợp pháp, quản lý tệp và các tài nguyên khác được lưu trữ trên điện thoại Android của bạn.
    
* Mã độc được phát hiện hoạt động trên các dòng máy android từ bản 4.1.x đến 5.x chạy trên nền kiến trúc ARM
    

### Tổng quan về Rootkit

* Mã độc thuộc rootnik, một dạng mã độc (malware) nhắm vào hệ điều hành Android. Rootnik được phân loại là một loại rootkit, cho phép kẻ tấn công kiểm soát hoàn toàn thiết bị bị nhiễm. Ngoài ra nó có khả năng xâm nhập vào hệ thống và cấp quyền truy cập root mà không cần sự cho phép của người dùng
    
* Các đặc điểm chính của Rootkit:
    
    * **Quyền truy cập root**: Rootkit khai thác các lỗ hổng bảo mật để có được quyền truy cập root trên thiết bị, cho phép nó cài đặt các ứng dụng khác mà không cần sự cho phép của người dùng.
        
    * **Khả năng ẩn mình**: Rootnik có khả năng ẩn mình khỏi các công cụ bảo mật và quản lý, làm cho việc phát hiện và loại bỏ nó trở nên khó khăn hơn.
        
    * **Chức năng đa dạng**: Có thể thực hiện nhiều hành động khác nhau như ghi lại các hoạt động của người dùng, đánh cắp thông tin cá nhân, tải xuống và cài đặt các ứng dụng độc hại khác, và gửi dữ liệu nhạy cảm đến máy chủ điều khiển của kẻ tấn công.
        
    * **Phát tán thông qua ứng dụng giả mạo**: Thường được phát tán thông qua các ứng dụng giả mạo hoặc các file APK không rõ nguồn gốc. Người dùng có thể vô tình tải và cài đặt nó khi nghĩ rằng đó là ứng dụng hợp pháp.
        
    
    → Mã độc file Helper chứa tất cả các đặc điểm trên khi thực hiện cài mã độc trên máy ảo
    

### Luồng hoạt động chính

* Luồng hoạt động của mã độc được miêu tả trong ảnh sau:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170000295/aefd6826-abac-4db8-8794-7b680fd8391c.jpeg align="center")
    
* Nhìn vào sơ đồ ta có thể tóm gọn chu trình hoạt động gồm 3 hoạt động chính:
    
    * Đầu tìn chạy file .dex đầu tiên load file .so (file share objects binary) để lấy ra một file .dex thứ hai thực hiện
        
    * File .dex thứ hai thực hiện parse file KK.bin để lấy ra các file .dex, .apk , các file ELF
        
    * Phân tích từ các file được tải về từ remote server, tạo một file .js để thực hiện các command trong máy tạo 1 file .apk trong system/priv-app để thực hiện cac mục tiêu cuối
        
* Đoạn cuối sau khi cài thêm file BSetting.apk nữa thì máy nạn nhân sẽ các “triệu chứng” sau:
    
    * Máy bị tạo nhiều screen shortcut trên màn hình
        
    * Các quảng cáo xuất hiện kèm theo là nhiều thông báo từ các apps lạ
        
    * Download nhiều file khác nhau cho lên máy nạn nhân
        

## Phân tích file apk đầu vào

### Kết cấu file mã độc

* Đầu tiên sử dụng apktool giải mã file mã độc ta sẽ có cây thư mục của mã độc như sau:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170225281/df7b421b-444b-4126-9eab-bf228e4086a0.png align="center")
    
* Đối với phân tich mã độc trên Android thì đầu tiên chúng ta cần phải đọc tệp cấu hình `AndroidManifest.xml`. Đây là tệp tin cấu hình chính của ứng dụng Android và chứa các thông tin quan trọng như thành phần ứng dụng, quyền ứng dụng yêu cầu, ….
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170260766/4e9b11e8-ab04-4596-978e-5e7e5394bcde.png align="center")
    
    * Dòng đầu tiên cho chúng ta thấy package name cho mã độc xuât hiện trong máy sẽ là `com.web.sdlife` , thuộc tính `standalone="no"`: Chỉ ra rằng tài liệu này phụ thuộc vào các thực thể bên ngoài (external entities). Các phiên bản platform chỉ ra phiên bản mà mã độc được build lên
        
    * Bên dưới là các quyền mà mã độc yêu cầu để được sử dụng để hoạt động đúng cách. Mã độc đã yêu cầu hơn 50 quyền khác nhau cho hoạt động của mình
        
* Đọc xuống bên dưới sẽ cung cấp thêm thông tin về cách hoạt động của mã độc
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170298735/044d3160-5bf0-4d82-b653-c95629ede6c1.png align="center")
    
    * Chi tiết đoạn này đã khai báo application có chứa một lớp java có tên là `com.secshell.shellwrapper.SecAppWrapper` nhằm mục đích lớp này sẽ là lớp được chạy đầu tiên trước khi lớp mà hệ thống Android khởi tạo
        
    * Bên dưới là lớp Java định nghĩa action.main là [`com.sd`](http://com.sd)`.clip.activity.FileManagerActivity` , nhưng ta không thể tìm được lớp Java này, bên cạnh đó là các lớp java Service class or Broadcast class trong lớp class.dex chính của mã độc
        
        → Mã độc sẽ tải một file .dex khác và thực thi nó
        
* Giờ chúng ta đã biết đầu tiên chúng ta cần phải làm tìm hiểu lớp `com.secshell.shellwrapper.SecAppWrapper` trong class.dex
    

### Phân tích tĩnh class.dex

* Sau khi dùng d2j-jar và jd-gui ta thu được cấu trúc trong file class.dex sau:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170376865/0e5db2bf-2257-4815-a5ec-b7e0b9994c37.png align="center")
    
* Như đã nói ở trên ta sẽ phân tích class `SecAppWrapper` :
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170516026/5b7625bf-1d4e-4578-8de4-3e34988b50cb.png align="center")
    
    * Đầu tiên class đã thực hiện tải thư viện native `SecShell` và (nếu có) tải một thư viện từ đường dẫn được chỉ định bởi `Helper.PPATH`. Điều này có thể được sử dụng để tích hợp mã native hoặc thư viện bên ngoài vào ứng dụng.
        
        > Thư viện native là các tập tin thư viện được viết bằng các ngôn ngữ lập trình cấp thấp như C hoặc C++, và được biên dịch thành mã máy để có thể thực thi trực tiếp bởi phần cứng của hệ thống.
        
    * Bên dưới đó ta thấy hàm `attachBaseContext()` nhằm tạo đối tượng ứng dụng thật sự có thể là ứng dụng thực sự mà lớp `SecAppWrapper` đang cố gắng thay thế hoặc mở rộng. Ngoài ra còn gọi `Helper.attach` có thể là để gán bối cảnh hoặc thực hiện một số thao tác đặc biệt với ứng dụng thực sự.
        
        * Class Helper có cấu tạo như sau:
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170533609/6fe8e792-8392-4bca-846b-2cd51f3a298b.png align="center")
            
            → Có thể `Attach` là để dùng giao tiếp với code native
            
    * Cuối cùng là `OnCreate()` để thực hiện thao tác khởi tạo lên ứng dụng với `realApplication`
        

→ Tóm lại luồng cơ bản của class này sẽ là:

*Static code block (Load SecShell)-&gt; attachBaseContext -&gt; onCreate*

* Ngoài ra mã độc còn dùng multidex scheme để thực hiện tải file .dex thứ hai về từ thư viện native được thể hiện qua class DexInstall
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170553314/86816b01-c818-4530-8fea-f5d0f56bf50e.png align="center")
    
    * Sau đó, chương trình gọi phương thức cài đặt DexInstall để tải tệp dex phụ. Việc gọi phương thức cài đặt của DexInstall được thực thi ở thư viện native
        
        > Multidex scheme là một phương pháp trong Android để xử lý các ứng dụng có quá nhiều mã nguồn để đặt vào một tập tin APK đơn. Khi số lượng phương thức trong ứng dụng vượt quá giới hạn (65,65,536 phương thức) của `Dalvik Executable (DEX) file`, chương trình sẽ gặp lỗi vượt quá giới hạn phương thức (lỗi “method limit exceeded”) . Multidex giúp giải quyết vấn đề này bằng cách chia mã nguồn của ứng dụng thành nhiều file DEX thay vì chỉ một.
        
* Trong class này chỉ có 2 lớp chính như trên nên tiếp theo ta sẽ đi sâu vào phân tích thư viên native `SecShell`
    

### Phân tích tĩnh thư viện native

### Đọc luồng thực thi trong native code

* Ném file SecShell vào IDA Pro để đọc file:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170884069/e9d12801-5518-41f0-a9a6-25b720d46f58.png align="center")
    
    * Đầu tiên ta xem phần Sections
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170917181/c1d2e9b2-c48d-4c9d-8d04-c842516a33da.png align="center")
        
        → Ta có thể thấy được các thành phần của thư viện như bảng GOT, phần BSS, … cũng như các quyền của từng phần và địa chỉ
        
    * Nhìn sơ qua phần các hàm trong thư viện thì nó đều để tên obfuscated làm rối người phân tích
        
    * Nhưng vì đây là thư viện native giao tiếp với code trong Java nên ta sẽ đi tìm phần hàm `Java Native Interface` (JNI)
        
        > JNI là một khung lập trình cho phép mã Java chạy trên một Máy ảo Java (JVM) có thể gọi và được gọi bởi những ứng dụng gốc (các chương trình cụ thể cho một nền tảng phần cứng và hệ điều hành) và những thư viện được viết bằng các ngôn ngữ khác như C, C++ và hợp ngữ.
        > 
        > ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170942027/ede0a567-bdac-4d74-b310-2d4a38761759.png align="center")
        
* Tìm trong list các hàm trong thư viện ta đã thấy hàm JNI\_OnLoad()
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170962832/dad8928e-a393-4dfd-9d0f-17e086cbd36f.png align="center")
    
    > Trong trường hợp có các hàm JNI khác thì ta cũng nên bắt đầu bằng JNI\_Onload trước vì trước khi phương thức native code nào được chạy thì vẫn cần được load library vào trong memory trước. Đó là cũng là lí do nên phân tích JNI\_OnLoad trước
    

Khi bắt đầu nhìn vào đoạn code Assembly của phần hàm JNI\_Onload()

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723170980635/c63149ca-770b-49f9-8798-dfe821addf68.png align="center")

* Thư viện viết theo kiến trúc ARM
    

> Kiến trúc ARM sử dụng kiến trúc RISC (Reduced Instruction Set Computing), có nghĩa là nó sử dụng một tập lệnh đơn giản và tối ưu hóa để thực hiện các tác vụ nhanh chóng và hiệu quả. Điếm khác biệt lớn ngoài hiệu năng và thời gian so với Intel đó là phần thanh ghi của ARM có nhiều hơn so với Intel nhưng số lượng instruction thì không bằng

* Chúng ta sử dụng phân tích động để xem luồng hoạt động của phần này
    
    * Thực hiện Attach vào process của mã độc
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723171452597/899364a0-e09c-4311-97c9-7f68bce31133.png align="center")
        
    * Sau khi chạy nhiều lần chương trình thì ta sẽ thấy không thể tiếp tục tại chỗ này
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723171497484/4416e8f0-fcc1-4e50-a3f5-98d677cdfcc3.png align="center")
        
    * Lệnh tại địa chỉ `0xF832` nhày tới địa chỉ `Loc_F924`. Sau đó sẽ bị nhảy vào hàm `p7E7056598F77DFCC42AE68DF7F0151CA()` → bị out khỏi process debugging
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723171517919/9a8b9b98-8519-4540-8157-3d078bf6f4f0.png align="center")
        
    
    → Hàm `p7E7056598F77DFCC42AE68DF7F0151CA()` sẽ thực hiện chức năng anti-debugging
    
    > Anti-Debug là các kỹ thuật được sử dụng để vô hiệu hóa các Debugger, nhằm mục đích gây khó khăn cho công việc Reverse, làm tiêu tốn nhiều thời gian hơn khi thực hiện phân tích một mẫu
    
* Nhìn qua graph của hàm anti-debugging ta có thấy rất phức tạp:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723171548685/9ba70c57-f6ed-4228-8dbb-3ffa9461cb45.png align="center")
    
    * Để có thể anti-debugging thì trong phần này code đã thực hiện cả anti-hooking với sự xuất hiện như phát hiện một số hook framework phổ biến như Xpose, base, adbi, ddi, dexpose. Sau khi tìm thấy, hãy chương trình debug dùng hook bằng các hook framework phổ biến này thì nó sẽ kill quá trình liên quan
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723171566974/7d54eb1d-535f-4ef5-a2c7-108ad431c6d6.png align="center")
        
    
    > Kĩ thuật anti-hooking là các kỹ thuật và các chiến lược được sử dụng để ngăn chặn các kĩ thuật hooking trong phần mềm. Hooking là một kỹ thuật phổ biến được sử dụng trong lập trình máy tính để thay đổi hoặc mở rộng hành vi của các hàm, phương thức, hoặc sự kiện của một ứng dụng mà không cần thay đổi mã nguồn gốc của ứng dụng đó. Dễ hiểu hơn thì hook sẽ nhắm vào khoảng thời gian trước khi hệ thống đọc được dữ liệu thành công. Thư viện hook sẽ khiến cho hệ thống đọc sai địa chỉ lưu dữ liệu và các chỉ thị của hàm, từ đó khiến cho chương trình hoạt động sai so với thiết kế
    
    * Tiếp theo ta có thể tìm được hàm find\_hook\_features()
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723171598751/9a243343-549a-4409-9a25-791abef9ed77.png align="center")
        
    * Ngoài ra thư viện này còn thực hiện scan thread để xem có trình gỡ lỗi xuất hiện hay không
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723171618848/9962a194-b37d-4ffc-beab-d224560a4d06.png align="center")
        

### Thực hiện bypass anti-debugging

* Theo như chúng ta đã phân tích, điều cần làm là tránh cho chương trình chạy đến hàm `p7E7056598F77DFCC42AE68DF7F0151CA()` để thực thi hàm check có đang được debug hay không, do đó ta đi đến instruction trước khi gọi đến hàm `Loc_F924` . Vì vậy:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172241381/969cd63c-9e59-4417-b32e-92b81b8074e1.png align="center")
    
    * Như trên ảnh thay vì để instruction `“SUBS R1, R0, #0”` tại địa chỉ `0xF828` , với instructions trước R1 chứa kết quả của R0 - 0 lưu vào R1 và vì BNE là lệnh "Branch if Not Equal", nghĩa là nhảy đến địa chỉ đích nếu kết quả của lệnh trước đó không bằng 0 (dựa trên cờ Zero). có 2 kết quả sau:
        
        * Nếu R1 = 0 thì cờ Zero được bật → sẽ không nhảy đến địa chỉ `0xF828`
            
        * Nếu R1 khác 0 thì cờ Zero ko được bật → sẽ nhảy đến địa chỉ `0xF828`
            
    * Qua đó đến khi debug ta sẽ thực hiện thay đổi giá trị thanh ghi R1
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172263872/df63da23-d91d-416b-bfd0-55564e7c0023.png align="center")
        
        > Ta có thấy địa chỉ thay đổi do phân tích tĩnh ta đang xem gọi là địa chỉ ảo còn khi thực hiện thì chúng ta sẽ thấy gọi là địa chỉ vật lý khi hệ điều hành ánh xạ các địa chỉ ảo này sang địa chỉ vật lý thực tế trong không gian địa chỉ của quá trình. Để thực hiện điều này thì cờ Address Space Layout Randomization (ASLR) cần được bật
        
    * Sau đó sẽ nhảy đến local\_75178834
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172282206/7ca72dfe-3098-4b2a-b966-351ba32134ec.png align="center")
        
* Sau khi bypass khỏi hàm anti-debugging, ta tiếp tục theo luồng và gặp một hàm load vào memory
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172318791/2b5065f4-1f99-4d89-b75d-e5d175876522.png align="center")
    
    * Hàm p34D946B85C4E13BE6E95110517F61C41() gọi là decryption function vì đầu vào R0 là trỏ đến vùng nhớ có mã hex như trên và file size là 608830. Khi so sánh ta sẽ thấy mã hex của vùng nhớ đó tương đồng với file secData0.jar
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172343515/464154c3-3afe-42b6-8c09-1676fbd22617.png align="center")
        
* Tiếp tục theo sau đó ta sẽ thu được một vùng memory khác chứa chữ ký khác
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172364936/49caf3e6-4d76-4929-bbbf-b78481735417.png align="center")
    
    * Chữ ký PK tượng trưng cho đây là file .zip. Do đó ta sẽ thực hiện dump memory này ra để chương trình đã lấy điều gì qua script của IDA
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172410095/a4f89010-3679-4f46-a59d-dc504945ad74.png align="center")
        
    * Bên dưới ta sẽ có thể thấy một hàm như install file .dex qua lời gọi của JNI
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172431348/9692c193-ab1e-46ad-a35e-ad98d8102226.png align="center")
        

## Phân tích file class.dex thứ hai

* Sau khi thực hiện dump memory ta sẽ có file decrypt.dump như sau:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172895203/2ec4c702-8555-4d07-ab0a-bfce3db638ff.png align="center")
    
* Vì là file .zip nên thực hiện decompress, sau đó ta sẽ có file .dex:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172915705/459d30bb-25e4-415b-a3d1-e6f0a226f541.png align="center")
    
* Dùng jd-gui phân tích thì trong cây thư mục ta sẽ có các class đã nói ở phần một:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172932556/b9f43b21-77f6-4d50-8067-c835f2879b55.png align="center")
    
* Xem xét hàm `OnCreate()` trong class FileManagerActivity()
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172949304/e3cf3cd1-0554-4049-9759-57d2dc96bff9.png align="center")
    
    * Sau khi xem xét thì ta sẽ thấy hàm `initadv()` gọi class Nws:
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172964469/27d7b85d-fa3f-4fd5-b7a9-99378a57e90c.png align="center")
        
    * Trong `Nws.getStart()` sẽ thực hiện `startService()` của class PG
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723172987782/ffd02786-cde0-4070-a630-037ca39c4bfb.png align="center")
        
* Giờ chúng ta sẽ đi sâu vào class PG
    
    * Giờ chúng ta có class và từng phần dưới đây:
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173098552/0272aac2-eae5-481e-b3b9-115ba2a0cd26.png align="center")
        
    
    1. readDex()
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173079153/90d15b12-d417-4deb-b438-8f4d5cb3c2c9.png align="center")
        
        * Như trên ảnh thì đầu tiên lấy string là KK.bin ra biến V9 (KK.bin chính là file nằm trong cây thư mục gốc của file )
            
        * v10 sẽ lấy tên KK.bin đọc file đó trong thư mục assets (Vì KK.bin nằm trong thư mục KK.bin)
            
        * Đến phần cuối thì nó sẽ đọc trong file KK.bin thành các chuỗi ngắt nhau bằng dấu xuống dòng. Ta xem
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173121388/bbd30360-dd3e-4324-a7db-f6248f050f9d.png align="center")
            
        * Cuối là gọi hàm getAppid() của class Pls
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173134461/9b567a13-bd19-42c0-ba9d-17f73f337082.png align="center")
            
        
        → Cuối cùng ta thu được một list các tên app trong Pls sau khi decode Base64
        
        `Pls.Kbin: wddex.jar`
        
        `Pls.OI: xdt`
        
        `Pls.PL: com.svq.cvo.Rtow`
        
        `Pls.Jr: getDex`
        
        `Pls.Wv: sgdex`
        
        `Pls.as: dos.jar`
        
        `Pls.NQ: KK.bin`
        
    2. dxFile()
        
        * Code trong hàm này được định nghĩa như sau trong class Pls:
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173184586/556cfe4a-387d-40f7-a282-4eb542f46524.png align="center")
            
            * Nhận hai tham số đầu vào Pls.kobs và string wddex.jar
                
            * Câu lệnh đầu tiên khai báo file v5 sẽ nằm ở thư mục `/data/data/com.web.sdlife/app_sgdex` có tên là dos.jar
                
            * Tạo file v10 tại đường dẫn `/data/data/com.web.sdlife/files` với tên là wddex.jar
                
            * Nếu file này chưa tồn tại sẽ thực hiện hàm `UnZipFolder()`
                
                ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173448680/7e258029-b628-46d9-91f5-8f1857323526.png align="center")
                
                * Với dữ liệu như trên, ta có thể thấy tạo file wddex.jar là từ KK.bin bằng việc lấy dữ liệu từ 0x20 đến 0x1CDB và save file đó dưới dạng `/data/data/com.web.sdlife/files/wddex.jar`
                    
            * Với các dòng cuối thì sẽ thực hiện decrypt file wddex.jar vừa tạo bằng giải thuật DES để tạo thành file dos.jar
                
    3. DexClassLoader()
        
        * Lớp này có cấu trúc như sau:
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173470352/517ba50f-123a-4ae0-a752-86ba2e253b85.png align="center")
            
        * Đây là một lớp trong Android thuộc gói `dalvik.system`, được sử dụng để tải các lớp từ các tệp .jar và .apk, mà có chứa mã bytecode Java và cho phép bạn tải và sử dụng các lớp từ các tệp mà không cần phải biên dịch chúng vào APK chính của ứng dụng
            
        * Với dexpath là file muốn tải, OptimizedDirectory là nơi chứa thì có thể biết được đối số muốn load là `/data/data/com.web.sdfile/app_sgdex/dos.jar` và đầu ra sẽ là `/data/data/com.web.sdfile/app_xdt` .
            
    
    ## Phân tích file .dex từ dos.jar
    
    1. Phân tích class **com.svq.cvo.Rtow**
        
        * Phân tích lớp getDex()
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173494639/374270d6-19fd-4955-9263-6dfcd71237fd.png align="center")
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173504603/16b4e59e-be63-4ebc-ab31-eb9f560f7d35.png align="center")
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173513313/7eb2640b-c437-40b5-a15f-51d568cc4a21.png align="center")
            
            * Theo luồng thực hiện, ta đi đến class `com.kdw.xoa.Dwol()`. Như đã comment ở trên, đến cuối sẽ khai báo tên file là mda.ico trong folder `/data/data/com.web.sdfile/files` .
                
            * Sau đó tải một payload từ một remote server có url là \[`http://gt](<http://gt/>)[.]rogsob[.]com/stmp/ad.png` và save lại vào file mda.ico vừa khai báo.
                
                ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723173537859/6795d1a6-8c37-46c7-bc95-c46851510381.png align="center")
                
        * Sau khi ghi vào mda.ico thành công thì sẽ đến hàm `initData()`
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191666554/aa66dbb7-dfc0-4872-b4c4-58fa425ead4f.png align="center")
            
        * Bên dưới là cấu trúc hàm initData():
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191682796/8f3e05c5-1a88-4da3-a4bb-eefd5e1552c5.png align="center")
            
    2. Cấu trúc của hàm`silentInstall()` có dạng như sau:
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191701436/67884244-dd94-417f-be5f-041727524988.png align="center")
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191715707/ad9295ef-44e6-455f-b108-f8c448a44860.png align="center")
        
        * Tóm gọn 5 bước giải thích cho chức năng class trên là:
            
            * Hàm dxfile của class Dwol sẽ thực hiện decrypt file `/data/data/com.web.sdfile/files/mda.ico` và lưu file decrypt đầu ra vào `/data/data/com.web.sdfile/app_snex/dkt.jar`
                
            * Hàm unZipfile của class Ngss sẽ thực hiện giải nén file dkt.jar ở trên vào vào thư mục `/data/data/com.web.sdfile/files`.
                
            * Sau khi giải nén sẽ lần lượt xóa các file dkt.jar. thư mục app\_snex, file mda.ico
                
            * Rename file class.dex thành file wsh.jar
                
            * Sử dùng hàm `DexClassLoader()` để lấy ra file wsh.dex
                
            * Yêu cầu thực hiện hàm getDex trong class com.rootdex.MainActivity của file wsh.dex
                

### Phân tích file wsh.dex

* Cấu trúc của file như sau:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191800861/99775db1-4521-4a4c-9be4-82283278a576.png align="center")
    
* Nội dung của class getDex():
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191815433/02f90a1e-07ae-4d5c-93f1-89d75ccbfe16.png align="center")
    
    * Thực hiện nếu trong thư mục system không xuất hiện các apk trên sẽ thực hiện hàm GetActive() là được sử dụng để thu thập thông tin thiết bị và gửi nó đến máy chủ từ xa. URL của máy chủ từ xa là \[[`http://grs](<http://grs/>)[.]gowdsy[.]com:8092/active.do`](http://grs%5D(%3Chttp://grs/%3E)%5B.%5Dgowdsy%5B.%5Dcom:8092/active.do)
        
    * Kiểm tra xem một số tệp có tồn tại trong thư mục /data/data/com.web.sdfile/files/ hay không và thêm tên tệp của chúng vào danh sách mảng mà mã độc đang chuẩn bị cho bước tiếp theo là root thiết bị.
        
    * Thực thi rooting trên thiết bị.
        
* Theo hàm run() trong class MTKRoot(), ta sẽ xem xét hàm HandleRoot():
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191959434/5bf7c5a3-49c6-472f-b295-2db1519617b2.png align="center")
    
* Bắt đầu với copyRootFile()
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191913118/456e5a72-44c0-4693-9334-7c4eb6b0e214.png align="center")
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191937243/3cb97e05-7089-4464-9b91-bfb04a56467c.png align="center")
    
    * FileUtil.dxfile() được sử dụng để giải mã tệp /data/data/com.web.sdfile/files/png.ico và lưu nó dưới dạng tệp /data/data/com.web.sdfile/app\_dex/.do.
        
    * FileUtil.UnZip() được sử dụng để giải nén tệp /data/data/com.web.sdfile/app\_dex/.do vào thư mục /data/data/com.web.sdfile/.rtt, là thư mục hệ thống ẩn chứa sáu tệp thực thi ELF, như được hiển thị bên dưới. Nó bao gồm bốn khai thác root r1,r2,r3,r4.
        
    * Nó xóa các công cụ root đã được giải mã /data/data/com.web.sdfile/app\_dex/.do và thư mục /data/data/com.web.sdfile/app\_dex
        
    * Sau đó, nó tạo một tệp mới, psneuter.js, trong thư mục /data/data/com.web.sdfile/files/. Nội dung của nó được hiển thị dưới đây.
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191977506/86dd8ec0-2517-4026-98ec-4cd3ddaf6cd7.png align="center")
        
* Tiếp trong hàm executeRootAct() thì sẽ thực hiện với nội dung sau:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723191996236/0ef3bef9-c8a0-4476-83ea-c21ae62ea37e.png align="center")
    
    * Với nội dung trên, hàm muốn thực hiện một loạt command với nội dung được tóm tắt như sau:
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192014128/e734b83a-cac9-4178-875c-8ce116d7ee14.png align="center")
        

→ như vậy các thành phần từ r1 đến r4 sẽ thực hiện root được thiết bị còn thành phần psneuter.js sẽ thực hiện với quyền cao nhất tải các tệp thực thi vào `/system/priv-app`

## Phân tích file apk trong system

### Phân tích code

* Sau khi file abc.[a](http://jif.ng)pk chuyển tên thành BSetting.apk và được install vào máy nạn nhân nên ta sẽ thực hiện phân tích file abc.apk.
    
* Xem xét cấu trúc của file abc.apk sau:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192105228/dc046932-22f0-44d9-9ba8-cade76ff640f.png align="center")
    
* File AndroidManifest[.](http://jif.ng)xml:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192124036/0b376885-cef6-4023-9be1-9cde31fa376e.png align="center")
    
    * Package chạy trong m[á](http://jif.ng)y nạn nhân sẽ là [`com.android`](http://com.android)`.sync`
        
* class đầu tiên ta ph[â](http://jif.ng)n tích là `com.sfy.oyr.R`:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192139754/a8a10e59-d7d0-4617-b776-9feac2dad80e.png align="center")
    
* Vì gọi đến class D h[à](http://jif.ng)m a() nên ta phân tích
    
    * Mở đầu là một loạt k[h](http://jif.ng)ai báo các kiểu string
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192154877/476a0026-19c5-43f6-9c7a-3893c0ceed5b.png align="center")
        
    * Chuyển mã Ascii sẽ l[à](http://jif.ng):
        
        ```jsx
        public static String d = "testdex.jar";
        
        public static String e = "temp";
        
        public static String f = "com.android.sync.ADSservice";
        
        public static String g = "getDex";
        
        public static String h = "com.android.sync.ADBoot";
        
        public static String i = "getBDex";
        
        public static String j = "sdex";
        
        public static String k = "do.jar";
        
        public static String l = "jif.png";
        
        public static String m = "doSo";
        
        public static String n = "/system/app";
        
        public static String o = "intent.action.file.deleted";
        
        public static String p = "/system/priv-app";
        ```
        
    * Hàm a():
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192173151/94c9564f-80d1-4814-aa91-827a3f6aef1d.png align="center")
        
    * Dựa vào kí tự đã giả[i](http://jif.ng) mã thì đây là yêu cầu thực hiện hàm doSO() trong class [com.android](http://com.android).sync.ADBoot
        
* Còn thành phần onSta[r](http://jif.ng)t() của class D sẽ thực hiện decrypt file jif[.](http://jif.ng)png thành một file class.dex mới
    

### Phân tích file class.dex từ jif.png

* Ta có cấu trúc của file class.dex:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192297153/6fac2fec-31de-402a-8769-4f5a79c970d8.png align="center")
    
* Sau khi xem xét 2 class này ta sẽ thấy trong class ADService sẽ thực hiện fetch đến 2 domain là `grs[.]gowdsy[.]com` và `grs[.]rogsob[.]com`.
    
* Ở đây ta sẽ thấy các hành vi cuối cùng của mã độc như:
    
    * Tạo Shortcut trên giao diện:
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192327715/cbc6c82c-e43d-405f-9c03-3066fff75134.png align="center")
        
    * Thực hiện tải nhiều package chạy ngầm trên thiết bị thông qua tiện ích “pm install -r” của hệ thống Android
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192342709/ffa0f66d-6314-4b88-bad3-fb8cfea69bfe.png align="center")
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192357277/273f331e-bcd7-42c0-91c5-07d2455b3df3.png align="center")
        
* Thực hiện push nhiều thông báo trên thiết bị:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723192372415/b88a642c-b4ae-4846-b04b-842df326a1e1.png align="center")
    

## Tổng kết

Từ phân tích trên, chúng ta có thể thấy rằng phần mềm độc hại rootnik đã sử dụng các kỹ thuật Anti-debug và Anti-hooking để ngăn chặn kỹ thuật đảo ngược và các loại mã hóa khác nhau cho tệp và chuỗi. Ngoài ra, nó cũng sử dụng một lMultidex scheme để tải và cài đặt động tệp dex thứ cấp là logic chính của phần mềm độc hại này. Phần mềm độc hại sử dụng một số công cụ khai thác gốc Android nguồn mở. Sau khi giành được quyền root thành công trên thiết bị, phần mềm độc hại rootnik có thể thực hiện nhiều hành vi độc hại, bao gồm quảng cáo ứng dụng và quảng cáo, tạo shorcut trên màn hình chính, cài đặt ứng dụng âm thầm và đẩy thông báo, v.v.

### C&C Server

* gt\[.\]rogsob\[.\]com
    
* grs\[.\]gowdsy\[.\]com
    
* alog\[.\]umeng\[.\]com
