追查某个bug,需要查看这个函数的返回值:

1
2
3
4
5
6
7
8
9
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
sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
auto ctx = mAccess->getCallingContext();

sp<IBinder> out;
Service* service = nullptr;
if (auto it = mNameToService.find(name); it != mNameToService.end()) {
service = &(it->second);

if (!service->allowIsolated) {
uid_t appid = multiuser_get_app_id(ctx.uid);
bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;

if (isIsolated) {
LOG(ERROR) << "Invalid service name: " << name << " isIsolated!";
return nullptr;
}
}
out = service->binder;
}

if (!mAccess->canFind(ctx, name)) {
LOG(ERROR) << "Invalid service name: " << name << " mAccess->canFind fail!";
return nullptr;
}

if (!out && startIfNotFound) {
tryStartService(name);
}

if (out) {
// Setting this guarantee each time we hand out a binder ensures that the client-checking
// loop knows about the event even if the client immediately drops the service
service->guaranteeClient = true;
}
LOG(ERROR) << "service name: "<< name << "address" << static_cast<void*>(out.get());
return out;
}

可以看到,返回的类型是sp,使用IDA从反汇编代码看:

1
2
3
4
5
.text:00000000000072A0 ; void __usercall android::ServiceManager::tryGetService(_QWORD **a1@<X0>, std::string *a2@<X1>, char a3@<W2>, __int64 *a4@<X8>)
.text:00000000000072A0 EXPORT _ZN7android14ServiceManager13tryGetServiceERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb
.text:00000000000072A0 _ZN7android14ServiceManager13tryGetServiceERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb
.text:00000000000072A0 ; CODE XREF: android::ServiceManager::getService(std::string const&,android::sp<android::IBinder> *)+30↑p
.text:00000000000072A0 ; android::ServiceManager::checkService(std::string const&,android::sp<android::IBinder> *)+30↓p

签名被编译器优化成了void类型,返回值改成了参数 __int64 *a4@< X8 >, IDA已经标识了是通过寄存器X8来传输。

因此,在frida 查看返回值的时候,不能直接看onLeave里的参数,这个就是寄存器X0的值。

需要在onEnter的时候,先把寄存器X8保存到临时变量,再在onLeave的时候,读取X8所指向的内容,才是真实的返回值。

1
2
3
4
5
6
7
8
9
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
function readStdString(str){
var isTiny = (str.readU8 & 1) === 0;
if (isTiny){
return str.add(1).readUtf8String();
}
return str.add(2 * Process.pointerSize).readPointer().readUtf8String();
}
function hook_android_checkService()
{
var base_addr = Module.findBaseAddress("servicemanager");
if(base_addr)
{
var offset = 0x72A0;//从export导出表,没法找到这个函数,但是可以通过地址偏移直接获取。
var fooAddr = base_addr.add(offset);
if(fooAddr)
{
var tml_x8=0;
Interceptor.attach(fooAddr, {
onEnter: function (args) {
console.log('Calling checkServic '," X8 ",this.context.x8);
tml_x8 = this.context.x8;
var name = readStdString(args[1]);
console.log("checkServic: " + name);
console.log('Call Stack:');
//console.log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n'));
},
onLeave: function (returnResult) {
var rtnval = tml_x8;
console.log(" returnResult",returnResult,"return " , rtnval,Memory.readPointer(rtnval));
}
});
}
}
}
setImmediate(hook_android_checkService, 0)

比如服务carrier_config成功找到,返回的地址是0xb4000076047d2000, frida也成功获取,当传入无效的服务名称时,返回的是0

1
2
3
4
5
6
7
8
9
 
checkServic: carrier_config
Call Stack:
returnResult 0x7814c666c4 return 0x7fde3e1640 0xb4000076047d2000

checkServic: installd111
Call Stack:
returnResult 0x7814c666c4 return 0x7fde3e1640 0x0
Calling checkServic 0x65255512a0 X8 0x7fde3e1640