最近安卓手机有个恶搞程序“一份礼物”登上热搜.
该app的效果是打开之后手机便会以最大音量循环播放“我要o泡”音乐,并且无法调小音量,无法退出程序,甚至无法关机,让中招者瞬间“社会性死亡”。
解决方法其实很简单,就是打开任务管理清掉该app后台,或者卸载该app。
某乎上也对这个app进行了激烈的讨论,我看到一些人有对这个app做了逆向,但都很片面,甚至有些不懂装懂的光看权限和一些包名就断定这个app做了什么什么坏事,下面还有很多不明真相的群众跟风对这个app进行诋毁。我们就来详细地对这个app进行逆向分析。
我拿到的样本应该是最近流传最广的一个"我要o泡"版本。
首先我们把apk扔到哈勃分析:
分析是失败的,原因是这个apk的tagetSdk版本较高,哈勃内置的安卓虚拟机版本只有4.0,我们反编译改下tagetSdkversion重打包就可以了:
行为分析:
分析结果表明这个app是没有风险的,也没有任何越权的行为。
接下来我们进行人工逆向分析:
载入jadx看下AndroidManifest.xml:
得知该样本包名是com.lc.nb,版本名是“凉城fork by Keven"
这里可以看出该APP应该是androlua编写的,androlua我在很久之前有研究过,主要代码都为lua语言,这里先不管,我们从程序入口点开始分析程序启动后都做了些什么。
启动Activity是com.androlua.Welcome
跟进去看onCreate方法
这里代码意思就是更改了界面的背景图片,大概就是实现程序启动图的效果,然后启动了Main.class这个Activity。
继续跟进Main.class:
这里启动了一个StatService,我看了下这个Service是百度统计的Service,大概是androlua开发者用来统计用户的,由于这个app没有申请联网权限,所以没什么作用了。
其他代码都没有什么实质性的作用。
我们再来看看app的Application类都做了些什么。Application类也是安卓APP运行时实例化的主要类。
这个app的类Application是com.androlua.LuaApplication
我们首先看com.androlua.LuaApplication的onCreate方法:
这里jadx中反编译失败了,我们可以看smali分析,这段代码主要作用就是在SD卡创建AndroLua目录,也没有其他作用。
我们再找找其地方,这里可以看到Main继承的LuaActivity类,所以LuaActivity类中初始化方法也会被执行,我们跟进去看看。
同样定位到onCreate:
这里里执行了很多文件载入和函数调用操作,
其中主要方法有LloadFile和runFunc,都是native里的方法:
他载入的init.lua和main.lua都是asstes里面的文件,我们打开看看:
全是乱码,没有文件头,明显是被加密了。
所以native方法里LloadFile之后肯定有解密。我们用ida载入他的libluajava.so:
一直跟进去:
到这里luaL_loadbufferx:
这里很明显是个解密方法了,我们可以参考这一代码,使用C语言编写一个简单的解密工具:
#include #include #include 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;}
编译这一代码为decrypt.exe,并拷贝到assets文件夹下,执行以下命令来解密init.lua和main.lua
decrypt init.lua
decrypt main.lua
解密后的文件为init.luac与main.luac,发现其仍然不是Lua代码,而是编译后的luac文件。
我们还需要对其进行反编译。
使用unluac可以对luac文件进行反编译,执行以下指令
java -jar unluac.jar init.luac > init-decomp.lua
java -jar unluac.jar main.luac > main-decomp.lua
通过反编译,我们可以得到真正的Lua代码文件init-decomp.lua和main-decomp.lua。
查看init-decomp.lua,代码的用途是声明应用基本信息
local L0_0appname = "一份礼物"appver = "凉城fork by Keven"appcode = "10"appsdk = "15"packagename = "com.lc.nb"debugmode = trueL0_0 = { "", "WRITE_EXTERNAL_STORAGE"}user_permission = L0_0
执行具体功能的代码位于main-decomp.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 = 10function 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)endti.start()function onKeyDown(A0_2, A1_3)if string.find(tostring(A1_3), "KEYCODE_BACK") ~= nil thenactivity.getSystemService(Context.AUDIO_SERVICE).setStreamVolume(AudioManager.STREAM_MUSIC, 15, AudioManager.FLAG_SHOW_UI)endreturn trueend
具体的操作有以下内容:
循环播放音频文件mc.mp3
将系统音量调至最大
隐藏系统导航栏,并进入沉浸模式(全屏)
每10tick,重复以上步骤使得无法主动调低音量
劫持返回键
最后我们可以得出结论这个App纯属恶搞,并不会对我们的手机造成什么损害。
但这个App的流传方式是社交网络,我也见过很多个版本,不排除有被植入恶意代码的可能。
所以大家最好不要随便安装和运行来历不明的App,如果需要可以先用哈勃分析(habo.qq.com),然后在虚拟机(VMOS或者光速虚拟机)中测试安全后再在自己手机中运行。