android开发apk捆绑,Android 下 APK 捆绑器的实现
Android 下 APK 捆綁器的實(shí)現(xiàn)
作者: 海東青
利用捆綁器向正常程序捆綁病毒、木馬等惡意程序,以達(dá)到隱蔽安裝、運(yùn)行的目的,這
在 Windows 平臺(tái)下是一種很常規(guī)的攻擊手段。那么,在智能終端十分流行的今天,如何實(shí)
現(xiàn)針對(duì)手機(jī)應(yīng)用的捆綁器呢?對(duì)此,本文針對(duì) Android 平臺(tái)的應(yīng)用程序 APK 文件,給出了
類(lèi)似 Windows 下捆綁器的實(shí)現(xiàn)方案。
原理與基礎(chǔ)
對(duì)任意的兩個(gè) APK 應(yīng)用程序 A 和 B 進(jìn)行捆綁,并且在手機(jī)上安裝、運(yùn)行捆綁生成的
APK 程序 C 后,仍然具備和 A 一樣的運(yùn)行效果,要實(shí)現(xiàn)這一目的,捆綁過(guò)程可以從兩個(gè)思
路去實(shí)現(xiàn)。
1)對(duì) Android 應(yīng)用程序 A 進(jìn)行反編譯,通過(guò)修改反編譯生成的 smali 代碼,控制執(zhí)行
流程,使其具備安裝和執(zhí)行應(yīng)用程序 B 的功能,最后再打包生成捆綁后的應(yīng)用 C。此方法
和早期的 Windows 環(huán)境下的 PE 病毒類(lèi)似,插入額外的功能代碼,修改入口點(diǎn)改變程序執(zhí)行
流程,最后再回到原有流程執(zhí)行 A 的功能。
2)考慮到 A、B 的任意性,以及生成程序 C 的穩(wěn)定性,在這里重點(diǎn)介紹另外一種通過(guò)
宿主程序?qū)崿F(xiàn)釋放、安裝、運(yùn)行 A 和 B 的方法。其思路亦來(lái)自 Windows 下的捆綁器,即專(zhuān)
門(mén)寫(xiě)一個(gè) host 程序作為宿主,其中應(yīng)用程序 A、B 作為 host 的資源文件,運(yùn)行 host 時(shí)可以
釋放、安裝和運(yùn)行 A 和 B 的功能。此外,若考慮到安全性、免殺性,可對(duì) A 和 B 進(jìn)行加密、
編碼。因此,根據(jù)方法2,可得出PC端和Android手機(jī)端的軟件工作流程如圖1和圖2所示
QQ圖片20140404144049.jpg (50.11 KB, 下載次數(shù): 26)
2014-4-4 15:02 上傳
QQ圖片20140404150245.jpg (30.84 KB, 下載次數(shù): 20)
2014-4-4 15:04 上傳
功能實(shí)現(xiàn)
通過(guò)上面的介紹,可以知道總共需要實(shí)現(xiàn)兩個(gè)程序,即作為宿主程序的 Android 應(yīng)用
host.apk,以及作為捆綁器的 Windows 應(yīng)用程序“捆綁器”,下面將詳細(xì)介紹這兩個(gè)程序內(nèi)
部原理和實(shí)現(xiàn)方法。
1.宿主應(yīng)用程序
1)工作流程
對(duì)于宿主程序 host.apk,要實(shí)現(xiàn)上文所定義的功能需求,則其內(nèi)部的工作流程可設(shè)計(jì)如
成如圖 3 所示的結(jié)構(gòu)。在宿主程序初始化時(shí),會(huì)調(diào)用MainActity 的 onCreate 函數(shù)。在 onCreate
函數(shù)中,通常用來(lái)初始化 MainActivity,但是考慮到最終呈現(xiàn)給用戶的界面(即 Activity)
為 A 的界面,所以宿主程序的 onCreate 函數(shù)中無(wú)需處理自身界面,只需想辦法啟動(dòng) A 的
Activity 即可。
QQ圖片20140404144738.jpg (81.05 KB, 下載次數(shù): 16)
2014-4-4 15:03 上傳
釋放和安裝指定的應(yīng)用程序通常需要較長(zhǎng)時(shí)間(與應(yīng)用程序的大小相關(guān)),若所有流程
均在 onCreate 函數(shù)流程中實(shí)現(xiàn),則會(huì)導(dǎo)致宿主程序界面卡頓或假死,故可通過(guò)在 onCreate
函數(shù)中創(chuàng)建子線程的方式避免該問(wèn)題,在子線程中實(shí)現(xiàn)相關(guān)功能,其中主要有釋放和安裝應(yīng)
用程序,以及啟動(dòng)主應(yīng)用程序這兩部分。
2)釋放和安裝應(yīng)用程序
①釋放指定文件
對(duì)于 Android 應(yīng)用程序,需要捆綁的資源文件可以直接放置到 assets 目錄下。在宿主程
序中,共計(jì)需要釋放三個(gè)文件,即配置文件 config、主程序 update.res 和捆綁進(jìn)去的程序
data.res,釋放方式如下。當(dāng)程序安裝后,需要釋放時(shí)可通過(guò)如下方式實(shí)現(xiàn)。
//dstFilePath 為釋放出來(lái)的文件路徑,resFileName 為需要釋放的文件路徑
private void dropFile(String dstFilePath, StringresFilename){
if(isFileExist(dstFilePath)) return;
InputStream inputFS;
try { inputFS = this.getResources().getAssets().open(resFilename);
} catch (IOException e1) {return; }
File outFile = new File(dstFilePath);
byte buf[] = new byte[1024];? ?int len;
try {
OutputStream outputFS = new FileOutputStream(outFile);
while((len = inputFS.read(buf))>0) {??outputFS.write(buf,0,len);}
outputFS.close();??inputFS.close();
} catch (IOException e) { return ; }
return;
}
②安裝應(yīng)用程序
文件釋放后,接下來(lái)就要根據(jù)需要進(jìn)行安裝程序。對(duì)用戶而言,已經(jīng)安裝程序了,故接
下來(lái)安裝程序需要在后臺(tái)完成,即不引起用戶察覺(jué),這就需要使用 shell 下的 pm 命令(Package
Manage),而 pm 命令需要 system 權(quán)限,故執(zhí)行此操作時(shí)需要確保可以獲取 root 權(quán)限。安裝
一個(gè)指定程序可通過(guò)“pm installtarget_apk”實(shí)現(xiàn)。而執(zhí)行 shell 命令利用 runtime.exec 即可
實(shí)現(xiàn),可將其簡(jiǎn)單封裝為 runCommand(String str)。
private void runCommand(String strCommand){
Runtime runtime = Runtime.getRuntime();
try { runtime.exec(strCommand);
} catch (IOException e) {e.printStackTrace(); }
}
綜上,釋放、安裝的功能實(shí)現(xiàn)代碼如下。
//Install the specified apk
public String installAPK(String apkFileName)
{
//獲取 assets 中文件安裝后的實(shí)際路徑
String tmpDir =this.getApplicationContext().getFilesDir()+"/";
String apk_path = tmpDir+apkFileName;
//釋放文件
dropFile(apk_path, apkFileName);
//安裝的 apk 文件需要讀寫(xiě)權(quán)限,故賦予讀寫(xiě)權(quán)限
runCommand("su -c chmod 666 "+apk_path);
//使用 pm 安裝文件
runCommand("su -c pm install -t "+apk_path);
return apk_path;
}
3)啟動(dòng)應(yīng)用程序
啟動(dòng)應(yīng)用程序可通過(guò)切換 Activity 實(shí)現(xiàn),即調(diào)用主程序 A 的 MainActivity 就可實(shí)現(xiàn)啟動(dòng)
A 程序并切換界面為 A,該過(guò)程可通過(guò)如下幾步實(shí)現(xiàn)。
①獲取需要啟動(dòng)的 apk 的信息
具體包括 apk 的packagename 和MainActivity 名。對(duì)于宿主程序而言,由于捆綁器已成
功獲取并將此信息寫(xiě)入了 config 文件,故只需要從 config 中分別讀取這兩個(gè)字符串即可。
②新建 intent
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
③切換 Activity,啟動(dòng)程序
ComponentName cn = new ComponentName(main_app,main_app_Acitivty);
intent.setComponent(cn);
startActivity(intent);
2.捆綁器程序
運(yùn)行在 Windows 下的捆綁器程序主要是為宿主程序做準(zhǔn)備:獲取主程序 A 的
packagename 和MainActivity 信息,獲取捆綁進(jìn)去的程序 B 的 packagename;修改宿主程序
的圖標(biāo),使其和程序 A 的一致;將準(zhǔn)備好的宿主程序打包、簽名等。下面將詳述每個(gè)部分。
1)提取信息
需要提取的信息為應(yīng)用程序的 Packagename 和 MainActivity 名,這些信息可以從 manifest
中解析,但更簡(jiǎn)單的辦法就是使用現(xiàn)有工具 apktool。該工具可以對(duì) apk 程序進(jìn)行解包、打
包、提取信息等。具體的,提取信息僅需命令“aapt.exedump badging apk_name”即可。為
了方便應(yīng)用,我們可以寫(xiě)一個(gè)專(zhuān)門(mén)提取信息的批處理腳本 aapt_apkinfo.bat,具體如下:
set PATH=%CD%;%PATH%;
"%~dp0\aapt.exe" dump badging %1 > %2
該批處理以“aapt_apkinfo.bata.apk info.txt”的方式調(diào)用,其中第一個(gè)參數(shù)為 apk 路徑,
第二個(gè)參數(shù)為信息存儲(chǔ)文件。在程序中則可以如下調(diào)用。
ShellExecute(NULL, TEXT("open"),szAaptCommand,szParameter, NULL, SW_HIDE);
其中,szAaptCommand 指向aapt_apkinfo.bat,szParameter 為參數(shù) 1 和參數(shù) 2 構(gòu)成的字
符串,如“a.apkinfo.txt”。
由于此時(shí)獲取到的信息如圖 4 所示,內(nèi)容太過(guò)冗余,我們需要從中解析出packagename
和 MainActivity。易知,此時(shí)得到的信息是按行存儲(chǔ)的,即 info.txt 中的每行為一類(lèi)或一條信
息 , 故 解 析 時(shí) 逐 行 判 斷 即 可 。 其 中packagename 通 常 以 此 種 格 式 出 現(xiàn) “ package:
name='com.tencent.mobileqq' ”, 可 以 認(rèn) 為 package: name 之 后 的 單 引 號(hào) 內(nèi) 的 內(nèi) 容 為
packagename。mainactivity 的信息如圖 5 所示,故同樣易得其信息。相關(guān)文本搜索、字符串
判斷等相關(guān)代碼不再羅列。
QQ圖片20140404160507.jpg (219.29 KB, 下載次數(shù): 15)
2014-4-4 16:07 上傳
圖 4 利用 apt 從 apk 中提取的原始信息
QQ圖片20140404160522.jpg (98.85 KB, 下載次數(shù): 16)
2014-4-4 16:07 上傳
圖 5 info.txt 中 mainactivity 的格式
最后,通過(guò)上述方法將提取到的信息存入 assets 目錄下的 config 文件中,供宿主程序使
用。
2)替換圖標(biāo)和標(biāo)簽
①獲取圖標(biāo)和標(biāo)簽信息
考慮到安全性,需要對(duì) host 程序進(jìn)行必要的偽裝,即重新打包后的 host 程序,安裝后
在應(yīng)用列表看上去要和 A 程序的一致,故還需要替換圖標(biāo)和標(biāo)簽。同理,通過(guò)上述方法,
可從 info.txt 中獲得 label 和 icon 的信息,如圖 6 所示。
QQ圖片20140404160866666666666666666.jpg (70.56 KB, 下載次數(shù): 15)
2014-4-4 16:10 上傳
圖 6 info.txt 中的 label 和 icon 信息
②替換圖標(biāo)和標(biāo)簽信息
在獲得 icon 路徑和 label 之后,接下來(lái)需要替換 host.apk 中的這些信息。
首先需要對(duì)主程序 A.apk 進(jìn)行解包,以獲得圖標(biāo)文件。Apk 解包同樣使用 apktool。直
接使用 apktool 解包的命令為“java –jar apktool.jar –d apkpathunpackeddir”,其中 apktool 支
持很多參數(shù),實(shí)現(xiàn)其他功能,方便起見(jiàn)將其封裝為 bat 文件 unpack_apk.bat,內(nèi)容如下。
set PATH=%CD%;%PATH%;
java -jar "%~dp0\apktool.jar" d %1 %2
該批處理的第一個(gè)參數(shù)為 apk 路徑,第二個(gè)參數(shù)為解包后的目錄路徑。在捆綁器程序中,
可通過(guò)如下命令調(diào)用該批處理,實(shí)現(xiàn)相應(yīng)的解包功能。
ShellExecute(NULL, TEXT("open"), szBatfilePath,szParameters, NULL, SW_HIDE);
其中,szParameters 即為批處理文件對(duì)應(yīng)的兩個(gè)參數(shù)。
在成功解包之后,替換圖標(biāo)就很簡(jiǎn)單了,只需要用上述 icon 路徑對(duì)應(yīng)的文件替換宿主
程序 host.apk 中的“\res\drawable-mdpi\ic_launcher.png”、 \res\drawable-hdpi\ic_launcher.png”、
“\res\drawable-ldpi\ic_launcher.png”和“\res\drawable-xhdpi\ic_launcher.png”文件。
宿主程序的標(biāo)簽信息位于“\res\values\strings.xml”中,具體如圖 7 所示。
只需將其中的app_name 對(duì)應(yīng)的值替換為前面獲取到的 label 的值即可。
QQ圖片20140404160910777777777777777.jpg (44.96 KB, 下載次數(shù): 16)
2014-4-4 16:11 上傳
圖 7 宿主程序的 strings 文件內(nèi)容
3)打包、簽名
通過(guò)前面的步驟,我們已經(jīng)成功修改好了宿主程序 host.apk,接下來(lái)需要對(duì)其進(jìn)行打包、
簽名。
①打包
對(duì) APK 的打包,仍舊采用 apktool,將其封裝成apk_apk.bat,內(nèi)容如下。
set PATH=%CD%;%PATH%;
java -jar "%~dp0\apktool.jar" b %1
QQ圖片2014040416131288888888888888.jpg (90.95 KB, 下載次數(shù): 16)
2014-4-4 16:14 上傳
其所需的唯一一個(gè)參數(shù)即為需要打包成 apk 的目錄。類(lèi)似的,程序中的調(diào)用方法依舊使
用“ShellExecute(NULL,TEXT("open"), szPackBatfile, m_szFinalApkDir, m_pctApkToolDir,
SW_HIDE);”。
②簽名
對(duì) apk 的簽名,可通過(guò)使用工具 autosign 實(shí)現(xiàn)。其調(diào)用方式為“java -jar signapk.jar
testkey.x509.pem testkey.pk8 unsigined.apk signed.apk”,需要的兩個(gè)參數(shù)為簽名的文件路徑和
成功簽名后的文件路徑。將其寫(xiě)為 sign.bat,內(nèi)容為:“java -jar signapk.jar testkey.x509.pem
testkey.pk8 %1 %2”。在捆綁器程序中相應(yīng)的調(diào)用方式為“ShellExecute(NULL, TEXT("open"),
szSignBatfile, szParameters, m_pctAutoSignDir, SW_HIDE);”,最終即可獲得捆綁后的 apk 程
序。
總結(jié)
通過(guò)前面的步驟,最終生成了一套由“apktool”、“auto-sign”、“host.apk”和“捆綁器”
組成的 apk 捆綁器工具,如圖 8 所示。
圖 8 捆綁器工具組成(左)和捆綁器運(yùn)行界面(右)
最終捆綁之后的 apk 應(yīng)用程序具備和正常安裝的 apk 一樣的運(yùn)行效果,但卻能隱蔽的安
裝所指定的任意 apk 文件,達(dá)到預(yù)期的目的和功能效果。
同時(shí),在上述實(shí)現(xiàn)過(guò)程中仍存在一定的不足,如在安裝捆綁之后的 apk 應(yīng)用時(shí),所顯示
的權(quán)限和非正常安裝的程序(主程序 A.apk)的權(quán)限不一致。一種更完美的方法則可以考慮
在修改 host.apk 文件時(shí),同時(shí)將主程序 A.apk 的 manifest 中的權(quán)限也復(fù)制到 host.apk 的
manifest 中,有興趣的讀者可以自行嘗試。
總結(jié)
以上是生活随笔為你收集整理的android开发apk捆绑,Android 下 APK 捆绑器的实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: react引入静态图片的方式
- 下一篇: Android--APK 捆绑器的实现