最近安卓手機有個惡搞程序“一份禮物”登上熱搜.
該app的效果是打開之后手機便會以最大音量循環播放“我要o泡”音樂,并且無法調小音量,無法退出程序,甚至無法關機,讓中招者瞬間“社會性死亡”。
解決方法其實很簡單,就是打開任務管理清掉該app后臺,或者卸載該app。
某乎上也對這個app進行了激烈的討論,我看到一些人有對這個app做了逆向,但都很片面,甚至有些不懂裝懂的光看權限和一些包名就斷定這個app做了什么什么壞事,下面還有很多不明真相的群眾跟風對這個app進行詆毀。我們就來詳細地對這個app進行逆向分析。
我拿到的樣本應該是最近流傳最廣的一個"我要o泡"版本。
首先我們把apk扔到哈勃分析:
分析是失敗的,原因是這個apk的版本較高c語言惡搞關機小程序,哈勃內置的安卓虛擬機版本只有4.0,我們反編譯改下重打包就可以了:
行為分析:
分析結果表明這個app是沒有風險的,也沒有任何越權的行為。
接下來我們進行人工逆向分析:
載入jadx看下.xml:
得知該樣本包名是com.lc.nb,版本名是“涼城fork by Keven"
這里可以看出該APP應該是編寫的,我在很久之前有研究過,主要代碼都為lua語言,這里先不管,我們從程序入口點開始分析程序啟動后都做了些什么。
啟動是com..
跟進去看方法
這里代碼意思就是更改了界面的背景圖片,大概就是實現程序啟動圖的效果c語言惡搞關機小程序,然后啟動了Main.class這個。
繼續跟進Main.class:
這里啟動了一個,我看了下這個是百度統計的,大概是開發者用來統計用戶的,由于這個app沒有申請聯網權限,所以沒什么作用了。
其他代碼都沒有什么實質性的作用。
我們再來看看app的類都做了些什么。類也是安卓APP運行時實例化的主要類。
這個app的類是com..
我們首先看com..的方法:
這里jadx中反編譯失敗了,我們可以看smali分析,這段代碼主要作用就是在SD卡創建目錄,也沒有其他作用。
我們再找找其地方,這里可以看到Main繼承的類,所以類中初始化方法也會被執行,我們跟進去看看。
同樣定位到:
這里里執行了很多文件載入和函數調用操作,
其中主要方法有和,都是里的方法:
他載入的init.lua和main.lua都是里面的文件,我們打開看看:
全是亂碼,沒有文件頭,明顯是被加密了。
所以方法里之后肯定有解密。我們用ida載入他的.so:
一直跟進去:
到這里:
這里很明顯是個解密方法了,我們可以參考這一代碼,使用C語言編寫一個簡單的解密工具:
unsigned char *decrypt(const unsigned char *buff, size_t size) {
unsigned char *buff1 = (unsigned char *) malloc(size);
buff1[0] = 27;
int t = 0;
for (int i = 1; i < size; i++) {
t += size;
buff1[i] = buff[i] ^ (t
+ ((unsigned int) (((unsigned long) (-2139062143LL * t) >> 32) + t) >> 7)
+ ((signed int) (((unsigned long) (-2139062143LL * t) >> 32) + t) < 0));
}
return buff1;
}
unsigned char buff[20480];
int main(int argc, char *argv[]) {
char filename[20] = "main.lua";
if (argc == 2)
strcpy(filename,argv[1]);
printf("File name: %s \n", filename);
FILE *fp = fopen(filename, "rb");
size_t size = 0;
size = fread(buff, sizeof(unsigned char), 20480, fp);
printf("File size: %ld \n", size);
unsigned char *res = decrypt(buff, size);
strcat(filename, "c");
FILE *fp1 = fopen(filename, "wb");
fwrite(res, sizeof(unsigned char), size, fp1);
printf("Output: %s", filename);
return 0;
}
編譯這一代碼為.exe,并拷貝到文件夾下,執行以下命令來解密init.lua和main.lua
init.lua
main.lua
解密后的文件為init.luac與main.luac,發現其仍然不是Lua代碼,而是編譯后的luac文件。
我們還需要對其進行反編譯。
使用可以對luac文件進行反編譯,執行以下指令
java -jar .jar init.luac > init-.lua
java -jar .jar main.luac > main-.lua
通過反編譯,我們可以得到真正的Lua代碼文件init-.lua和main-.lua。
查看init-.lua,代碼的用途是聲明應用基本信息
local L0_0
appname = "一份禮物"
appver = "涼城fork by Keven"
appcode = "10"
appsdk = "15"
packagename = "com.lc.nb"
debugmode = true
L0_0 = {
"",
"WRITE_EXTERNAL_STORAGE"
}
user_permission = L0_0
執行具體功能的代碼位于main-.lua
require("import")
import("android.app.*")
import("android.os.*")
import("android.widget.*")
import("android.view.*")
import("android.view.View")
import("android.content.Context")
import("android.media.MediaPlayer")
import("android.media.AudioManager")
import("com.androlua.Ticker")
activity.getSystemService(Context.AUDIO_SERVICE).setStreamVolume(AudioManager.STREAM_MUSIC, 15, AudioManager.FLAG_SHOW_UI)
activity.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE)
m = MediaPlayer()
m.reset()
m.setDataSource(activity.getLuaDir() .. "/mc.mp3")
m.prepare()
m.start()
m.setLooping(true)
ti = Ticker()
ti.Period = 10
function ti.onTick()
activity.getSystemService(Context.AUDIO_SERVICE).setStreamVolume(AudioManager.STREAM_MUSIC, 15, AudioManager.FLAG_SHOW_UI)
activity.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE)
end
ti.start()
function onKeyDown(A0_2, A1_3)
if string.find(tostring(A1_3), "KEYCODE_BACK") ~= nil then
activity.getSystemService(Context.AUDIO_SERVICE).setStreamVolume(AudioManager.STREAM_MUSIC, 15, AudioManager.FLAG_SHOW_UI)
end
return true
end
具體的操作有以下內容:
最后我們可以得出結論這個App純屬惡搞,并不會對我們的手機造成什么損害。
但這個App的流傳方式是社交網絡,我也見過很多個版本,不排除有被植入惡意代碼的可能。
所以大家最好不要隨便安裝和運行來歷不明的App,如果需要可以先用哈勃分析(),然后在虛擬機(VMOS或者光速虛擬機)中測試安全后再在自己手機中運行。