Analyze a mobile malware

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:

  • 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:

  • Đố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, ….

    • 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

    • 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.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:

  • Như đã nói ở trên ta sẽ phân tích class SecAppWrapper :

    • Đầ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:

        → 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)-> attachBaseContext -> 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

    • 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:

    • Đầu tiên ta xem phần Sections

      → 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ữ.

  • Tìm trong list các hàm trong thư viện ta đã thấy hàm JNI_OnLoad()

    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()

  • 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

    • 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

    • 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

→ 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:

    • Để 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

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()

  • 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

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:

    • 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

      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

  • 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

    • 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

  • Tiếp tục theo sau đó ta sẽ thu được một vùng memory khác chứa chữ ký khác

    • 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

    • 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

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:

  • Vì là file .zip nên thực hiện decompress, sau đó ta sẽ có file .dex:

  • 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:

  • Xem xét hàm OnCreate() trong class FileManagerActivity()

    • Sau khi xem xét thì ta sẽ thấy hàm initadv() gọi class Nws:

    • Trong Nws.getStart() sẽ thực hiện startService() của class PG

  • 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:

  1. readDex()

    • 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

    • Cuối là gọi hàm getAppid() của class Pls

→ 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

  1. dxFile()

    • Code trong hàm này được định nghĩa như sau trong class Pls:

      • 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()

        • 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

  2. DexClassLoader()

    • Lớp này có cấu trúc như sau:

    • Đâ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()

      • 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.

    • Sau khi ghi vào mda.ico thành công thì sẽ đến hàm initData()

    • Bên dưới là cấu trúc hàm initData():

  2. Cấu trúc của hàmsilentInstall() có dạng như sau:

    • 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:

  • Nội dung của class getDex():

    • 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[.]gowdsy.]com: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():

  • Bắt đầu với copyRootFile()

    • 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.

  • Tiếp trong hàm executeRootAct() thì sẽ thực hiện với nội dung sau:

    • 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:

→ 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.apk 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:

  • File AndroidManifest.xml:

    • Package chạy trong máy nạn nhân sẽ là com.android.sync
  • class đầu tiên ta phân tích là com.sfy.oyr.R:

  • Vì gọi đến class D hàm a() nên ta phân tích

    • Mở đầu là một loạt khai báo các kiểu string

    • Chuyển mã Ascii sẽ là:

        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():

    • Dựa vào kí tự đã giải mã thì đây là yêu cầu thực hiện hàm doSO() trong class com.android.sync.ADBoot

  • Còn thành phần onStart() của class D sẽ thực hiện decrypt file jif.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:

  • 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[.]comgrs[.]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:

    • 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

  • Thực hiện push nhiều thông báo trên thiết bị:

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