一、簡述

為了能夠更加靈活的提供分析和信息交互,GDA從3.6版本開始提供了對python腳本的支持。GDA為分析人員提供了整個APK文件中的類和方法的相關信息,其中分別以列表和字典的方式來組織類和方法,提高類和方法的訪問速度。當然使用腳本之前你必須打開了某個apk/dex/odex/oat/gda文件。

二、入口規範

GDA的所有腳本必須以GDA_MAIN函數為入口,並且你不需要導入任何GDA文件,為了方便調試,你可以導入GdaImport,GDA腳本引擎對此並不是必須的。GDA腳本引擎默認已經幫你處理了導入操作的很多細節。

Example:

腳本引擎會對apk中所有的類和方法進行分析,並且將這些分析好的數據傳遞給入口函數GDA_MAIN。GDA_MAIN只存在一個參數gda_obj,當然你可以修改該參數名稱。通過該參數你可以訪問這些類和方法,以及他所提供的介面。gda_obj實際上為類GDAInterface的實例化對象。該類提供了所有數據和API以供編程使用。

三、類GDAInterface提供的介面數據

為了讓用戶能夠通過腳本的方式訪問到所有的類和方法,我將GDA所分析得到的基本數據通過列表和字典來組織。其中該數據介面提供在gda_obj對象的DexList成員中,

該成員也是一個列表,因為部分APK中會存在多個dex文件,因此我用一個列表來存儲之,如果只有一個dex文件,那麼你只需要訪問其第一個實體即可。

DexList的每個實體(GdaDex類)包含了三部分信息:Dex 頭信息、類、方法。其中類和方法均以列表和字典的方式存儲。

你可以根據該實體獲取到該Dex文件的所有解析結果,詳細可以參見GdaImport.py文件。

四、GDAInterface提供的介面函數:

為了能夠訪問到更加詳細的信息,GDA提供了如下介面函數:

API

功能描述

GetAppString(dexId=0)

返回字元串,獲取所有被引用過的字元串

log(str)

返回列印長度,列印字元串到gda窗口

GetPermission()

返回字元串,獲取permission信息

GetCert()

返回字元串,獲取簽名信息

GetSupicous(dexId=0)

返回字元串,獲取可疑行為信息

GetStringById(idx,dexId=0)

返回字元串,通過字元串index獲取字元串

GetMethodNameById(idx,dexId=0)

返回字元串,通過方法的index獲取方法名

SetClassName(idx,name,dexId=0)

返回bool,修改類名,同時會修改到UI界面上

SetMethodName(idx,name,dexId=0)

返回bool,修改方法名,同時會修改到UI界面上

GetClassCodeById(idx,dexId=0)

返回字元串,獲取類代碼(只包含方法和成員變數聲明)

GetSmaliCodeById(idx,dexId=0)

返回字元串,獲取方法的smali代碼

GetJavaCodeById(idx,dexId=0)

返回字元串,獲取方法的java代碼

GetUrlString(dexId=0)

返回字元串,獲取APK中的url字元串

FindClassId(descriptor,dexId=0)

返回int(index),通過類描述器,得到類的index

GetMethodDeclare(idx,dexId=0)

返回字元串,獲取方法的聲明

DumpBin(fileName,offset,size,dexId=0)

返回bool,根據偏移offset,及大小size, dump二進位數據到文件filename中

DumpData(offset,size,width_=16,dexId=0)

返回字元串,以十六進位方式dump數據

WriteBinaryToDex(offset,bytes,buffLen,dexId=0)

返回bool,向當前dex文件的指定偏移出寫入指定長度的數據

五、案例分析

1、最簡單的樣例-提取信息

下面是一個單純用於獲取信息的非常簡單的腳本

通過gda_obj對象,調用gda_obj.GetPermission()函數用於當前apk所聲明的許可權信息,並該信息通過gda_obj.log()函數將其列印到GDA的界面上,然後再將許可權信息寫入到當前目錄的out.txt文件中。效果如圖:

是不是非常簡單。

2、案例二:dump二進位數據

接下來我提供的第二例子是用於dump數據的樣例。我想根據一個偏移地址dump指定大小的內存數據,該如何操作,比如獲取字元串偏移表。就可以通過gda_obj對象找到dex,再根據dex得到dex header,接下來根據頭部的stringIdsOff利用DumpData API就可以進行dump了。

當然你也可以利用DumpBin函數將數據直接dump到文件。你也可以利用WriteBinaryToDex向Dex文件的指定偏移寫入數據。輸出到GDA上顯示如下:

其他案例:

3、案例三:找到一個方法所調用的方法

4、案例四:找到一個方法的調用者方法

這3和4兩個案例可以用於列印向上和向下的調用圖。

5、案例五:列印類和方法的反編譯代碼

6、案例6:反混淆腳本

該腳本利用某些程序員在配置混淆器時,為了方便調試而未對類文件名進行混淆,使得利用類文件名可以在一定程度上進行反混淆操作。利用GDA做為分析工具,可以使用短短的幾行代碼就可實現。

gda=gda_obj

Dex0=gda.DexList[0]

for classi in Dex0.ClassList:

sourceFileName=gda.GetStringById(classi.sourceFileIdx)

newName=sourceFileName[:-5]

oldName=classi.className

if len(oldName)<=2 and not(newName==oldName):

gda.SetClassName(classi.idx,newName)

反混淆前後對比:

這種方法有個問題,有時候一個類文件會包含多個類,尤其是內部類,這個時候通過這種方法就會反混淆出多個同名的類。如果需要更為精確的反混淆,可以利用GDA製作庫簽名來精確識別出方法名和類名。製作庫簽名:選中一個包名右鍵菜單可以製作一個該包名下所有方法的簽名。

下次分析時如果懷疑使用了同樣的庫,可以在File菜單下點擊」Load Flirt Sig」載入簽名文件運行,還原方法名和類名。如圖:


推薦閱讀:
相关文章