1. 程式人生 > >安卓逆向實踐7——樂固脫殼實戰

安卓逆向實踐7——樂固脫殼實戰

待分析應用zxxy拖到Android killer中反編譯:

可以看到是加了樂固殼的。檢視lib目錄下的so檔案為libshella-2.8.so,字尾為a表示基於ARM平臺,x代表x86平臺,這裡的版本是2.8.0版本的樂固殼。要分析如何脫殼,那麼這個libshella-2.8.so就是分析的重點了。拖到IDA中靜態分析,一開始就無法解析並且出現警告提示,這裡老師上課講過了,是對elf檔案中的section header table做了混淆處理,因為我們在實際裝載過程中並不需要連結檢視中的section資訊,所以只需要找到section header table將其全部置為0,就可正常打開了。這裡檢視section header table的檔案偏移以及大小可以在虛擬機器Linux上使用readelf -a libshella-2.8.so來檢視,然後使用010Editor來編輯。另外一種方法就是使用xAnSo-master 這個工具進行修復,這是Github上面提供的,搜一下就能找到。==
處理之後IDA靜態分析如下:


這裡就能檢視到一些匯入函數了,在exports匯出函式中可以看到JNI_Onload函式,點選去看發現數據都是經過加密處理的,直接make code(快捷鍵c)並不能將資料轉化為程式碼。那麼猜想JNI_Onload函式肯定是在init_array或者init中進行了處理。接下來進行動態除錯so檔案進行分析,除錯的步驟這裡就不多說了,請參考上一篇文章。
這裡寫圖片描述
點選執行,在上圖中載入libshella-2.8.so時停下來,接下來我們先定位到init_array的位置:
這裡寫圖片描述
可以看到init_array的偏移地址為0x3e84,在動態分析IDA中ctrl+s檢視libshella-2.8.so載入到記憶體中的基地址:
這裡寫圖片描述

那麼其地址為基地址+偏移地址,0x7631FE84,
這裡寫圖片描述
這裡對應函式地址0x7631C944, 跳轉到該地址檢視。

// write access to const memory has been detected, the output may be wrong!
int sub_944()
{
  unsigned int v0; // [email protected]
  unsigned int v1; // [email protected]
  unsigned int v2; // [email protected]
  char v3; // [email protected]
int v4; // [email protected] int j; // [sp+34h] [bp-18h]@13 char v7; // [sp+38h] [bp-14h]@13 char v8; // [sp+39h] [bp-13h]@13 char v9; // [sp+3Ah] [bp-12h]@13 char v10; // [sp+3Bh] [bp-11h]@13 unsigned int v11; // [sp+3Ch] [bp-10h]@4 int v12; // [sp+40h] [bp-Ch]@4 int i; // [sp+44h] [bp-8h]@1 for ( i = (unsigned int)sub_944 & 0xFFFFF000; *(_DWORD *)i != 1179403647; i -= 4096 ) ; v12 = *(_DWORD *)(i + 28) + i; v11 = 0; while ( *(_WORD *)(i + 44) > v11 ) { if ( *(_DWORD *)v12 != 1 || *(_DWORD *)(v12 + 24) != 5 ) { if ( *(_DWORD *)v12 == 1 && *(_DWORD *)(v12 + 24) == 6 ) { v1 = *(_DWORD *)(v12 + 8) & 0xFFFFF000; v2 = (*(_DWORD *)(v12 + 8) + *(_DWORD *)(v12 + 16) + 4095) & 0xFFFFF000; break; } } else { v0 = (*(_DWORD *)(v12 + 8) + *(_DWORD *)(v12 + 16) + 4095) & 0xFFFFF000; } ++v11; v12 += 32; } v10 = 43; v9 = -103; v8 = 32; v7 = 21; mprotect(i, 0, 3); for ( j = 0; j <= 0; ++j ) { v3 = *(_BYTE *)(i + j); *(_BYTE *)(i + j) ^= (unsigned __int8)(((v9 - v8) ^ j) + v7) ^ v10; *(_BYTE *)(i + j) += v8 & v7 ^ v9; v10 += (v9 + v8 - v7) & v3 & j; v9 += (j + v10) ^ v3; v8 ^= (v3 - v10) ^ j; v7 += j - (v3 + v10); } mprotect(i, 0, 5); v4 = sub_7E8(i, 0); dword_4008 = i; return sub_898(v4); }

這裡就是init_array對應的函式,通過檢視相應的函式可以看到前面實際上是進行了一些位元組變換,然後呼叫了mprotect,sub_B6F083DC和sub_B6F0F630三個函式。sub_B6F083DC函式就是做了 cacheflush和syscall操作。猜想這裡就是對JNI_Onload程式碼區的資料進行解密還原,這裡不是關注的重點。我們直接執行單步進入到sub_898函式內部,當前版本中並沒有反除錯程式碼。
這裡寫圖片描述
更改名稱之後的兩個函式向日志中列印tag為txtag的日誌資訊,然後留意一下第一個函式,點進去看到有“LD_PRELOAD”關鍵字,猜想這裡應該是跟環境變數共享庫的設定有關,無需過分關注,直接單步跳過去。檢視最後一個函式呼叫,unk_7631E74C:
這裡寫圖片描述
其實這個地址7631E74C剛好就是靜態分析對應的JNI_Onload地址,也就是說此時加密資料已經被還原了,能夠被我們IDA識別出來。
具體的流程就不用管了,我們知道肯定會去執行JNI_Onloadh函式,就在上圖這個函式中下斷點,然後執行到這個地方:
這裡寫圖片描述
這裡想說一個很有效的除錯技巧,在除錯時可以結合反彙編出來的函式形式,通過檢視引數以及返回值來判斷函式的大致功能(檢視暫存器值,arm中r0-r4傳遞引數)。
通過檢視引數我們看到這段程式碼呼叫了dlopen和dlsym兩個函式。dlopen開啟一個動態連結庫,dlsym根據動態連結庫操作控制代碼(handle)與符號(symbol),返回符號對應的地址(這裡的符號為JNI_Onload)。使用這個函式不但可以獲取函式地址,也可以獲取變數地址。
那麼也就是說最終v7才是真正希望執行的JNI_Onload函式地址,也就是對應如下arm程式碼中的BLX R3;中的R3暫存器中的地址:
這裡寫圖片描述
檢視對應的C程式碼:

signed int __fastcall sub_7632DADC(int a1)
{
  signed int v1; // [email protected]
  int v2; // [email protected]
  int v4; // [sp+4h] [bp-14h]@1

  v1 = 0;
  v2 = a1;
  v4 = 0;
  if ( ((int (__cdecl *)(int, int *))unk_7632DA50)(a1, &v4) )
  {
    if ( ((int (__fastcall *)(_DWORD, _DWORD, signed int))unk_7632DA50)(v2, &v4, 65540) )
    {
      if ( ((int (__fastcall *)(int, int *, signed int))unk_7632DA50)(v2, &v4, 65538) )
      {
        if ( ((int (__fastcall *)(int, int *, signed int))unk_7632DA50)(v2, &v4, 65537) )
          return v1;
        v1 = 65537;
      }
      else
      {
        v1 = 65538;
      }
    }
    else
    {
      v1 = 65540;
    }
  }
  else
  {
    v1 = 65542;
  }
  if ( v4 )
  {
    ((void (*)(void))unk_7632E270)();
    ((void (*)(void))unk_7632DAA0)();
  }
  return v1;
}

依次點選其中的函式檢視程式碼,最後一個函式程式碼如下所示:
這裡寫圖片描述
看到了registerNatives,那麼這裡肯定就是手動註冊native方法了,跟到上面的函式中:
這裡寫圖片描述
那麼這裡我們重點關注RegisterNatives函式的引數,其函式原型為:
jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)
第二個引數是一個結構體:
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;

也就是說,我們跟蹤到這個引數的時候就可以知道其註冊的native方法載入到記憶體後的函式地址,即對應結構體的第三個引數。從而可以獲取到在Java程式碼中呼叫了哪些原生函式進行脫殼操作。這裡結構體指標對應著第三個引數v6,因為第一個引數還傳入了env。
單步執行到這裡:
這裡寫圖片描述
這裡我們看到第一個註冊方法的地址為7628CB55,那麼實際的地址應該為7628CB56,跳轉到該地址,檢視反彙編程式碼:
這裡寫圖片描述
通過一些列印資訊提示可以猜測這裡肯定是與脫殼載入相關的函式程式碼。
這裡寫圖片描述
這裡根據不同的虛擬機器指令版本執行不同的Load操作,那麼這裡的標出來的函式就應該是脫殼並載入的關鍵程式碼了。
接下來如何dump dex直接參考後面給出來的連結。
脫殼結果:
這裡寫圖片描述
這裡還是比較坑的,除錯過程中即使是在真機上也會報出各種異常,不過還好最後一次除錯成功了。

相關推薦

逆向實踐7——實戰

待分析應用zxxy拖到Android killer中反編譯: 可以看到是加了樂固殼的。檢視lib目錄下的so檔案為libshella-2.8.so,字尾為a表示基於ARM平臺,x代表x86平臺,這裡的版本是2.8.0版本的樂固殼。要分析如何脫殼,那麼這個l

逆向之基於Xposed-ZjDroid

重定位 war fill 沙盒 mar 內存 ces 鼠標 文件加載 http://bbs.pediy.com/thread-218798.htm 前言 之前介紹了普通常見的反編譯模式 但對於使用了 360加固 棒棒 愛加密 等等的加固應用就沒辦法了、 你

【天翼杯題二】 愛加密實戰

encode ask ner 符號 rom fse write 找到 ace 前言 這個apk使用愛加密加密,加密時間是2017.6月。這個題其實就是個脫殼題,脫完立馬見flag。(出題人也太懶了) 題目鏈接:https://gitee.com/hac425/blog_da

逆向

配置路徑jdk等,安裝好android studio ,下載所需應用,新建一個app(hello world) 輸出成apk 直接在cmd中輸入 adb install  (拖入剛生成的apk檔案) 下載安裝android killer  看下smali語法:https://blo

逆向除錯smali筆記

  我的系統環境配置: win7 64 android studio 3.2 jdk 1.8.0_144   注意:由於android studio3.0以上版本中的ADDM被取消,目前只能在NDK的tools工具中開啟monitor.bat 1、開啟前關閉android s

unity+android:大版本更新安裝下好的apk,相容任意5.0,7.0,8.0版本

Android Studio 1:在專案的res目錄下建立xml目錄,再建立file_paths.xml檔案。 <?xml version="1.0" encoding="utf-8"?> <paths> <root-pa

進階(7)之OkHttp3.10攔截器原理解析

部落格流程 用一個demo介紹如何新增自定義的攔截器; 介紹攔截器是怎麼產生攔截效果的; 介紹okhttp裡預設的各個攔截器的作用。 新增自定義的log攔截器 在使用okhttp時,我們可能需要獲取

逆向學習筆記(0)- HelloWorld.apk的檔案結構

        META-INF資料夾存放著apk的簽名信息。如果你還不瞭解安卓簽名機制,請看這篇文章:[014] Android應用程式簽名詳解         開啟META-INF資料夾,可以看到3個檔案:CERT.RSA,CERT.SF,MANIFEST.MF。其中CERT.RSA包含了公鑰資訊和釋出機

逆向搭建環境

開始記錄了,首先需要搭建安卓相關環境,雖然不一定是以開發作為標準,但是基礎的環境還是需要的。 既然app是需要執行在特定裝置的,但是我們使用的是PC,所以可以使用模擬器進行測試,當然真機也是行的。 開發 可能會使用Genymotion Genymotion是網上

逆向系列教程 4.11 優酷 APK 去廣告

4.11 優酷 APK 去廣告 作者:飛龍 這次要破解優酷的 APK,去掉播放視訊開頭的廣告: 我們先抓包,看到了api.mobile.youku.com,這個就是廣告所在的域名。

逆向學習筆記 -- 七少月團隊:35天的收穫

七月六號到今天八月十九號,我跟七少月團隊學習35天了(大部分時間都是研究自己渴望有的東西),今晚就抽出玩遊戲的時間,寫一篇文章分享一下加入七少月團隊35天的經歷以及收穫。 在我沒有加入七少月團隊

[開發基礎] 7.7 intent 的種類

Intent 分為隱式 ,和顯示 。 顯示: 目標組建可以為 廣播,activity,或者服務。明確知道元件名稱的時候使用。  顯示Intent用法: 隱式:   Intent 開啟網頁: btn_start.setOnClickListe

2019最新春秋零基礎入門Android逆向教程

├─第一章 │ 課時1.mp4 │ 課時2 .mp4 │ 課時3.mp4 │ 課時4 mp4 │ 課時5 .mp4 │ 課時6 .mp4 │ 課時7 .mp4 │ 課時8 .mp4 │ ├─第七章 │ 1.mp4 │ 10.mp4 │ 11.mp4 │ 12.mp4 │ 13.mp4 │ 14.mp

JB的測試之旅-聽說微信7.0不能抓https?

前言 最近公司有個小程式要提測,因為之前反饋過使用Ip測試的時候,埠響應太慢了,因此這次改成了域名的方式 ; 研發提測,體驗,發現有個疑似bug的東西,想著抓包看下是不是介面資料的問題,結果問題出現了,按照以前的常規操作,開啟fiddler,設定ip代理(https證書已經安裝了),結果一看,fiddle

逆向學習筆記 (3)- 使用IDA Pro靜態分析so檔案

        安卓應用程式的開發語言是java,但是由於java層的程式碼很容易被反編譯,而反編譯c/c++程式的難度比較大,所以現在很多安卓應用程式的核心部分都使用NDK進行開發。關於NDK的開發知識點,請看這篇部落格:Android之NDK開發。         使

逆向入門之如何連線夜神與AndroidKiller,以及一個簡單crackme

準備工作 為了確保夜神與其他相關的能夠連線上,在用Android killer的時候,就將Android killer中的adb+2個dll拷貝至夜神中,用到Android studio的時候,就將sdk中的platform中的這個adb+2個dll

逆向學習---初始APK、Dalvik字節碼以及Smali

靜態 格式 鏈接 變量 char har 占用空間 方法參數 調用 參考鏈接:https://www.52pojie.cn/thread-395689-1-1.html res目錄下資源文件在編譯時會自動生成索引文件(R.java ), asset目錄下的資源文件無需生成索

逆向-修改APK-戰鬥直接勝利

前言   很久沒有總結過關於逆向程式設計的文章了,來寫一篇實踐分享給大家。主要來說說如何通過逆向修改APK來實現遊戲進入後直接獲得勝利領取獎勵。為了學習發展就不分享遊戲名稱了。下面我們開始吧: 使用到工具 AndroidKiller / IDE 3.1.0

筆記-第一次ZjDroid實戰

看了那麼多逆向破解的文章,總得來點實戰的了,正所謂實踐出真知嘛。 拜讀了姜維大神的「Android中Xposed框架篇—基於Xposed的一款脫殼神器ZjDroid工具原理解析」,準備來個應用動手試試了,想起我自己之前有個應用恰好是大數字加固的,於是想試試破自己的應用。  (純粹是個人

IDA pro實戰過反除錯

IDA pro脫殼實戰過反除錯 標籤(空格分隔): Apk逆向 1. 前言 之前總結了IDA pro脫殼的基本步驟,包括除錯步驟和在libdvm.so的dvmDexFileOpenPartial函數出下斷點,從記憶體中dump出dex檔案。  這次以360一代加殼為例,試著在m