【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

小龙 2017-7-5 信息安全 0 0

【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实 2017-07-04 12:16:33 阅读:390次 点赞(0) 收藏 来源: 安全客

0x00 起因

学习android安全的朋友都应该熟悉adb,fastboot这两个工具,但是其实现方式网上却没有多少资料,在下对这些知识也非好奇,一次机会对某手机的售后刷机工具aftool进行对手机刷机时,发现了它的软件包里没有fastboot.exe,但是却执行了fastboot命令,猜测他可能自己实现了fastboot.exe的功能,就想对其进行逆向分析执行fastboot的命令的核心代码。

0x01 调试环境配置

工具:IDA ,Ollydbg,Wireshark,Source Insight3

Aftool download link:

http://pan.baidu.com/s/1c0AVz9I

Adb source code download link:

http://pan.baidu.com/s/1hrVZFxU

安装AF_UPGRADE_PKG.exe后,aftool.exe为目标文件

0x02 fastboot.exe 和fastboot 模式通信的数据包

我们手机进入fastboot, 使用wireshark 抓取usb数据包,观察数据包数量以及格式

进入fastboot的方法:

[1](命令)使用 adb reboot-bootloader[2](按键)音量减键+电源键
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

使用wireshark 捕获usb包

选择接口 android Bootloader interface
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

使用fastboot.exe 发送命令 fastboot reboot-bootloader
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

同时wireshark捕获到的数据包为:
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

URB_BULK out 的数据为:
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

URB_BULK in 的数据为:
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

可以大胆猜测 URB_BULK out 就是我们使用的fastboot的命令 fastboot reboot-bootloaderURB_BULK int 就是手机端给的回应

但是上面三个特殊的数据包 和我们发的数据没有任何关系,但是看其名称”Request,Response,Status”猜测可能是fastboot的通信协议的 建立协议的数据包

0x03 aftool.exe 和fastboot 模式通信的数据包

Aftool的使用方法:

[1]切换成高通手机[2]点击选择按钮 加X520_recovery目录下的fastboot_flash_all.bat[3]点击下载按钮 开始执行fastboot_flash_all.bat里面的命令

对wireshark的处理方式和上面类型

捕获的数据包如下图
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

看来和fastboot的数据包格式一致,只是多发送了一条命令

现在的思路就是 Ollydbg 调试aftool ,假如执行了某个函数同时wireshark上有数据包产生那么这个函数就是通信使用的函数

0x04 逆向aftool.exe

这个工具是使用Qt编写,没有加壳子,没有加混淆,对我这种小白来说,最大的难题可能就是怎么在Qt的架构里找到”下载”按钮的处理函数了。

一开始我是没有思路的,由于不知道这个下载按钮里进行了操作,我给它下断点都不知道用什么函数下什么断点。但是想到了旁边还有一个”选择”按钮,加载bat文件肯定有文件读取的操作 于是对ReadFile 下了断点。果然断了下,然后通过回溯。找到了它的UI消息处理函数sub_4E22C0。

最后确定了sub_4E22C0 中调用的sub_4BFD30就是”下载”按钮响应事件,

在sub_4BFD30里分支比较多 但是ollydbg跟了几次之后 发现其执行的分支稳定执行

sub_4BBAF0
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

但是sub_4BBAF0的代码逻辑看起来很简单并没有多少值得注意的代码,但是在OD里跟着sub_4BBAF0 按F9就会跑起来,看来是这个函数没错,但是应该是错过了什么

在sub_4BBAF0里的下层函数sub_4B7DB0,以及sub_4B7DB0的下层函数sub_4A3F30找到了如下代码
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

可以的它开了一个线程

但是参考Qt QThread::start()的用法 这里传入的参数可能是ida的没有使用类的方式调用吧

直接用ollydbg动态调到他这里来。得到了v2[18]的值742D345e(742D345e不是定值)

接着有两个函数需要F7

742D34C2E851FFFFFFcallmsvcr90.742D3418742D3430FF5054calldwordptrds:[eax+0x54]恭喜最后来到了
004A411A.E8914B0000callAFTool.004A8CB0

sub_4A8CB0就是真正处理函数

接着在ollydbg IDA里跟了跟这个函数观察

//reboot-bootloader004A908C|.E83F190000callAFTool.004AA9D0

发现AFTool.004AA9D0 这个函数就是给手机发数据的函数

004AA9D0 里最重要的就是下面的函数

004AAA58|.52|pushedx004AAA59|.8B542434|movedx,dwordptrss:[esp+0x34];AFTool.0052D4B8004AAA5D|.8D4C2418|leaecx,dwordptrss:[esp+0x18]004AAA61|.51|pushecx004AAA62|.50|pusheax004AAA63|.8B4208|moveax,dwordptrds:[edx+0x8]004AAA66|.55|pushebp004AAA67|.50|pusheax004AAA68|.FF151CC05000|calldwordptrds:[<&AdbWinApi.AdbWrite>;AdbWinAp.AdbWriteEndpointSync

堆栈如图:

esp->09A2F9780000000809A2F97C09A2FD1CASCII"reboot-bootloader"09A2F9800000001109A2F98409A2F9A009A2F9880000027C

<注意:这个函数执行之前Wireshark里已经有了那三条特殊的数据包了,这个函数执行之后Wireshark会增加 URB_BULK out >

所以发送命令API函数就是 AdbWinAPi.dll里的导出函数 AdbWriteEndpointSync

类似的找到了发出别的4条数据包的具体函数(其实三条特殊数据包的是一个函数发的)
AdbGetSerialNumber------>GETDESCRIPTORRequestSTRING------>GETDESCRIPTORResponseSTRING------>GETDESCRIPTORStatusAdbReadEndpointSync------>URB_BULKin

0x05 API调用分析

现在找到了API接下来就是参考源码对这些API传入正确参数并调用了。

我们一开始假设的是前三条数据包是建立协议链接 类似socket编程accept函数返回的sock

然后AdbWriteEndpointSync 类似 send函数 使用这个sock进行通信

在源码里找了AdbWriteEndpointSync 声明(使用dll里的导出函数),调用

声明:
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

调用:
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

在usb_write 下面就是 usb_read的定义
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

通过上面的代码可以看出AdbWriteEndpointSync,AdbReadEndpointSync使用的第一个参数都是同一个结构体里的不同成员变量

这个结构体的声明如下
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

接着关于adb_write_pipe和adb_read_pipe变量的赋值

但是搜索无果,搜索调用函数usb_write的函数时,能搜索到,但是没有找到他的参数传递
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

换了一个思路对AdbGetSerialNumber调用进行了寻找
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

比起这个调用,上面的do_usb_open函数返回的handle则是引起了我的兴趣,其定义如下。
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

通过其定义可以看出,do_usb_open 里完成了对结构体usb_handle的分配已经赋值。

通过do_usb_open 返回的关键性结构体,我们就可以对AdbWriteEndpointSync 进行调用。

至于do_usb_open的参数来源 则是 上面的API AdbNextInterface进行的赋值
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

所以我们已经在源码里找到了我们需要的API的调用参数的来源。

0x06 整合代码

通过整合。得了如下的代码

<注意:一定要把AdbWinApi.dll AdbWinUsbApi.dll放到这个项目里编译>

//adb_test.cpp:定义控制台应用程序的入口点。//#include"stdafx.h"#include<windows.h>#defineADB_MUTEX_INITIALIZERPTHREAD_MUTEX_INITIALIZERtypedefvoid*ADBAPIHANDLE;typedefstruct_AdbInterfaceInfo{///Inteface'sclassid(seeSP_DEVICE_INTERFACE_DATAfordetails)GUIDclass_id;///Interfaceflags(seeSP_DEVICE_INTERFACE_DATAfordetails)unsignedlongflags;///Devicenamefortheinterface(seeSP_DEVICE_INTERFACE_DETAIL_DATA///fordetails)wchar_tdevice_name[1];}AdbInterfaceInfo;structusb_handle{///Previousentryinthelistofopenedusbhandlesusb_handle*prev;///Nextentryinthelistofopenedusbhandlesusb_handle*next;///HandletoUSBinterfaceADBAPIHANDLEadb_interface;///HandletoUSBreadpipe(endpoint)ADBAPIHANDLEadb_read_pipe;///HandletoUSBwritepipe(endpoint)ADBAPIHANDLEadb_write_pipe;///Interfacenamechar*interface_name;///Maskfordeterminingwhentousezerolengthpacketsunsignedzero_mask;};typedefenum_AdbOpenAccessType{///Opensforreadandwriteaccess.AdbOpenAccessTypeReadWrite,///Opensforreadonlyaccess.AdbOpenAccessTypeRead,///Opensforwriteonlyaccess.AdbOpenAccessTypeWrite,///Opensforqueryinginformation.AdbOpenAccessTypeQueryInfo,}AdbOpenAccessType;typedefenum_AdbOpenSharingMode{///Sharesreadandwrite.AdbOpenSharingModeReadWrite,///Sharesonlyread.AdbOpenSharingModeRead,///Sharesonlywrite.AdbOpenSharingModeWrite,///Opensexclusive.AdbOpenSharingModeExclusive,}AdbOpenSharingMode;#defineANDROID_USB_CLASS_ID\{0xf72fe0d4,0xcbcb,0x407d,{0x88,0x14,0x9e,0xd6,0x73,0xd0,0xdd,0x6b}};structusb_ifc_info{unsigned__int16dev_vendor;unsigned__int16dev_product;unsigned__int8dev_class;unsigned__int8dev_subclass;unsigned__int8dev_protocol;unsigned__int8ifc_class;unsigned__int8ifc_subclass;unsigned__int8ifc_protocol;unsigned__int8has_bulk_in;unsigned__int8has_bulk_out;unsigned__int8writable;charserial_number[256];chardevice_path[256];};typedefstruct_USB_DEVICE_DESCRIPTOR{UCHARbLength;UCHARbDescriptorType;USHORTbcdUSB;UCHARbDeviceClass;UCHARbDeviceSubClass;UCHARbDeviceProtocol;UCHARbMaxPacketSize0;USHORTidVendor;USHORTidProduct;USHORTbcdDevice;UCHARiManufacturer;UCHARiProduct;UCHARiSerialNumber;UCHARbNumConfigurations;}USB_DEVICE_DESCRIPTOR,*PUSB_DEVICE_DESCRIPTOR;typedefstruct_USB_INTERFACE_DESCRIPTOR{UCHARbLength;UCHARbDescriptorType;UCHARbInterfaceNumber;UCHARbAlternateSetting;UCHARbNumEndpoints;UCHARbInterfaceClass;UCHARbInterfaceSubClass;UCHARbInterfaceProtocol;UCHARiInterface;}USB_INTERFACE_DESCRIPTOR,*PUSB_INTERFACE_DESCRIPTOR;typedefint(*AdbWriteEndpointSync_)(ADBAPIHANDLE,char*,int,int*,int);typedefvoid*(*AdbCreateInterfaceByName_)(constwchar_t*);typedefvoid*(*AdbOpenDefaultBulkWriteEndpoint_)(ADBAPIHANDLE,AdbOpenAccessType,AdbOpenSharingMode);typedefbool(*AdbNextInterface_)(ADBAPIHANDLE,AdbInterfaceInfo*,unsignedlong*size);typedefvoid*(*AdbEnumInterfaces_)(GUID,bool,bool,bool);typedefADBAPIHANDLE(*AdbOpenDefaultBulkReadEndpoint_)(ADBAPIHANDLE,AdbOpenAccessType,AdbOpenSharingMode);typedefbool(*AdbGetInterfaceName_)(ADBAPIHANDLEadb_interface,void*buffer,unsignedlong*buffer_char_size,boolansi);typedefbool(*AdbCloseHandle_)(ADBAPIHANDLEadb_handle);typedefbool(*AdbGetUsbDeviceDescriptor_)(ADBAPIHANDLE,USB_DEVICE_DESCRIPTOR*);typedefbool(*AdbGetUsbInterfaceDescriptor_)(ADBAPIHANDLE,USB_INTERFACE_DESCRIPTOR*);typedefbool(*AdbGetSerialNumber_)(ADBAPIHANDLE,void*,unsignedlong*,bool);typedefbool(*AdbReadEndpointSync_)(ADBAPIHANDLE,void*,unsignedlong,unsignedlong*,unsignedlong);AdbWriteEndpointSync_AdbWriteEndpointSync;AdbCreateInterfaceByName_AdbCreateInterfaceByName;AdbOpenDefaultBulkWriteEndpoint_AdbOpenDefaultBulkWriteEndpoint;AdbNextInterface_AdbNextInterface;AdbEnumInterfaces_AdbEnumInterfaces;AdbOpenDefaultBulkReadEndpoint_AdbOpenDefaultBulkReadEndpoint;AdbGetInterfaceName_AdbGetInterfaceName;AdbCloseHandle_AdbCloseHandle;AdbGetUsbDeviceDescriptor_AdbGetUsbDeviceDescriptor;AdbGetUsbInterfaceDescriptor_AdbGetUsbInterfaceDescriptor;AdbGetSerialNumber_AdbGetSerialNumber;AdbReadEndpointSync_AdbReadEndpointSync;usb_handle*do_usb_open(constwchar_t*interface_name);voidusb_cleanup_handle(usb_handle*handle);intrecognized_device(usb_handle*handle);intmain(){intd;chargetvar[]="getvar:product";charrebootbl[]="reboot-bootloader";HMODULEa=LoadLibrary(L"AdbWinApi.dll");AdbWriteEndpointSync=(AdbWriteEndpointSync_)GetProcAddress(a,"AdbWriteEndpointSync");AdbCreateInterfaceByName=(AdbCreateInterfaceByName_)GetProcAddress(a,"AdbCreateInterfaceByName");AdbOpenDefaultBulkWriteEndpoint=(AdbOpenDefaultBulkWriteEndpoint_)GetProcAddress(a,"AdbOpenDefaultBulkWriteEndpoint");AdbNextInterface=(AdbNextInterface_)GetProcAddress(a,"AdbNextInterface");AdbEnumInterfaces=(AdbEnumInterfaces_)GetProcAddress(a,"AdbEnumInterfaces");AdbOpenDefaultBulkReadEndpoint=(AdbOpenDefaultBulkReadEndpoint_)GetProcAddress(a,"AdbOpenDefaultBulkReadEndpoint");AdbGetInterfaceName=(AdbGetInterfaceName_)GetProcAddress(a,"AdbGetInterfaceName");AdbCloseHandle=(AdbCloseHandle_)GetProcAddress(a,"AdbCloseHandle");AdbGetUsbDeviceDescriptor=(AdbGetUsbDeviceDescriptor_)GetProcAddress(a,"AdbGetUsbDeviceDescriptor");AdbGetUsbInterfaceDescriptor=(AdbGetUsbInterfaceDescriptor_)GetProcAddress(a,"AdbGetUsbInterfaceDescriptor");AdbGetSerialNumber=(AdbGetSerialNumber_)GetProcAddress(a,"AdbGetSerialNumber");AdbReadEndpointSync=(AdbReadEndpointSync_)GetProcAddress(a,"AdbReadEndpointSync");usb_handle*handle=NULL;charentry_buffer[2048];charinterf_name[2048];charread[2048];intArgList;AdbInterfaceInfo*next_interface=(AdbInterfaceInfo*)(&entry_buffer[0]);unsignedlongentry_buffer_size=sizeof(entry_buffer);char*copy_name;staticconstGUIDusb_class_id=ANDROID_USB_CLASS_ID;//Enumerateallpresentandactiveinterfaces.ADBAPIHANDLEenum_handle=AdbEnumInterfaces(usb_class_id,true,true,true);while(AdbNextInterface(enum_handle,next_interface,&entry_buffer_size)){constwchar_t*wchar_name=next_interface->device_name;for(copy_name=interf_name;L'\0'!=*wchar_name;wchar_name++,copy_name++){*copy_name=(char)(*wchar_name);}*copy_name='\0';handle=do_usb_open(next_interface->device_name);if(recognized_device(handle)){printf("addinganewdevice%s\n",interf_name);charserial_number[512];unsignedlongserial_number_len=sizeof(serial_number);if(AdbGetSerialNumber(handle->adb_interface,serial_number,&serial_number_len,true)){memset(read,0,sizeof(read));AdbWriteEndpointSync(handle->adb_write_pipe,getvar,strlen(rebootbl),&d,0x26c);Sleep(3000);AdbReadEndpointSync(handle->adb_read_pipe,read,4096,(unsignedlong*)&ArgList,0x26c);read[strlen(read)]='\0';printf("%s:\n",read);memset(read,0,sizeof(read));AdbWriteEndpointSync(handle->adb_write_pipe,rebootbl,strlen(rebootbl),&d,0x26c);Sleep(3000);AdbReadEndpointSync(handle->adb_read_pipe,read,4096,(unsignedlong*)&ArgList,0x26c);read[strlen(read)]='\0';printf("%s:\n",read);}}}//AdbWriteEndpointSync(ret->adb_write_pipe,rebootbl,strlen(rebootbl),&d,0x26c);return0;}intrecognized_device(usb_handle*handle){if(NULL==handle)return0;//CheckvendorandproductidfirstUSB_DEVICE_DESCRIPTORdevice_desc;if(!AdbGetUsbDeviceDescriptor(handle->adb_interface,&device_desc)){return0;}//ThencheckinterfacepropertiesUSB_INTERFACE_DESCRIPTORinterf_desc;if(!AdbGetUsbInterfaceDescriptor(handle->adb_interface,&interf_desc)){return0;}//Musthavetwoendpointsif(2!=interf_desc.bNumEndpoints){return0;}//if(is_adb_interface(device_desc.idVendor,device_desc.idProduct,//interf_desc.bInterfaceClass,interf_desc.bInterfaceSubClass,interf_desc.bInterfaceProtocol)){//if(interf_desc.bInterfaceProtocol==0x01){//AdbEndpointInformationendpoint_info;////assumingzeroisavalidbulkendpointID//if(AdbGetEndpointInformation(handle->adb_interface,0,&endpoint_info)){//handle->zero_mask=endpoint_info.max_packet_size-1;//}//}return1;}voidusb_cleanup_handle(usb_handle*handle){if(NULL!=handle){if(NULL!=handle->interface_name)free(handle->interface_name);if(NULL!=handle->adb_write_pipe)AdbCloseHandle(handle->adb_write_pipe);if(NULL!=handle->adb_read_pipe)AdbCloseHandle(handle->adb_read_pipe);if(NULL!=handle->adb_interface)AdbCloseHandle(handle->adb_interface);handle->interface_name=NULL;handle->adb_write_pipe=NULL;handle->adb_read_pipe=NULL;handle->adb_interface=NULL;}}usb_handle*do_usb_open(constwchar_t*interface_name){//Allocateourhandleusb_handle*ret=(usb_handle*)malloc(sizeof(usb_handle));if(NULL==ret)returnNULL;//Setlinkersbacktothehandleret->next=ret;ret->prev=ret;//Createinterface.ret->adb_interface=AdbCreateInterfaceByName(interface_name);//if(NULL==ret->adb_interface){//free(ret);//errno=GetLastError();//returnNULL;//}//Openreadpipe(endpoint)ret->adb_read_pipe=AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,AdbOpenAccessTypeReadWrite,AdbOpenSharingModeReadWrite);//Openwritepipe(endpoint)ret->adb_write_pipe=AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,AdbOpenAccessTypeReadWrite,AdbOpenSharingModeReadWrite);//Saveinterfacenameunsignedlongname_len=0;//FirstgetexpectednamelengthAdbGetInterfaceName(ret->adb_interface,NULL,&name_len,true);if(0!=name_len){ret->interface_name=(char*)malloc(name_len);if(NULL!=ret->interface_name){//Nowsavethenameif(AdbGetInterfaceName(ret->adb_interface,ret->interface_name,&name_len,true)){//We'redoneatthispointreturnret;}}else{SetLastError(ERROR_OUTOFMEMORY);}}//Somethingwentwrong.intsaved_errno=GetLastError();usb_cleanup_handle(ret);free(ret);SetLastError(saved_errno);returnNULL;}

0x07 代码运行结果
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实

其中 OKAYMSM8916是其CUP型号,为fastboot命令 getvar product的返回,OKAY是reboot-bootloader的返回,并且手机重启进入fastboot模式。说明得到的代码是完全能执行命令的核心API。
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实
【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实 本文由 安全客 原创发布,如需转载请注明来源及本文地址。
本文地址:http://bobao.360.cn/learning/detail/4060.html

本文网络安全相关术语:网络安全工程师 网络信息安全 网络安全技术 网络安全知识

主题: UC、Qt、数据、360、数据包、高通、ERP、UT、TI、其实、

转载请注明来自华盟网,本文标题:《【技术分享】如何代码实现给fastboot发消息? 逆向aftool工具纪实》

喜欢 (0) 发布评论