在非越狱设备上Hook C++的虚函数是否可能?

关于C++中虚函数与普通函数的区别,大家可以参考:《深度探索C++对象模型》。

对于Hook普通的C++函数,与Hook C函数没什么太大区别,主要的区别在于C++有名称改编,原理是在函数入口加入跳转指令。

这块儿在Windows平台上有微软的Detours,也有开源的EasyHook。在Mac平台上有MobileSubstrate,相信做过越狱开发的对这个都比较熟悉。

所有上面列到的工具在Hook C++普通函数时都需要修改Segment __TEXT,而这个段在iOS平台上只读的,具体权限为:RX。因此在非越狱的设备上没法修改函数入口,也就无法Hook。

但是我们是可以Hook Objective-C函数的,虽然Objective-C的运行时提供了一些方法,但是主要的原因在于:针对OC的方法调用需要查询一个数据映射表,将消息转换为真正的C函数调用,而这个映射表是放在可修改的数据段中的。

这点与C++的虚函数有几分类似,下面一起分析下看看是否有可能Hook C++的虚函数。

Demo程序如下:

//
//  main.cpp
//  VTLocation
//
//  Created by Proteas on 14-8-12.
//  Copyright (c) 2014年 Proteas. All rights reserved.
//

#include <stdio.h>

class Base
{
public:
    virtual ~Base() {};
    
public:
    virtual void sayHello() { printf("hello from base\r"); };
};

class Child : public Base
{
public:
    virtual ~Child() {};
public:
    virtual void sayHello() { printf("hello from child\r"); };
};

int main (int argc, const char * argv[])
{
    Child *p = new Child;
    p->sayHello();
    delete p;
    
	return 0;
}

Makefile内容如下:

export DEVELOPER_DIR := $(shell xcode-select --print-path)

SDK_VER_IOS=7.1
SDK_IOS_DEVICE="$(DEVELOPER_DIR)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(SDK_VER_IOS).sdk"
MIN_VER_IOS=-miphoneos-version-min=5.0
ARCH_IOS=-arch armv7
CC_IOS=xcrun -sdk "iphoneos" gcc

all: main.cpp
	$(CC_IOS) -o main main.cpp $(ARCH_IOS) $(MIN_VER_IOS) -isysroot $(SDK_IOS_DEVICE) -I$(SDK_IOS_DEVICE)/usr/include -I. -lc++ -lstdc++
	ldid -S main

clean:
	rm -f main

编译完成后得到可执行程序main。

在得到可执行程序后,我们首先要找到虚函数表所在的区段,因此使用IDA 加载 main 查找虚函数表。


然后我们选择数据段:


因为Demo程序很简单,跳转到数据段后,直接就看到了虚函数表:


直接可以看到虚函数表的各个表项,这里需要注意的是:非纯虚函数还是发生了名称改编。没验证纯虚函数,不过印象中纯虚函数是没有名称改编的,因为微软的COM依赖这一特性。

下面我们使用MachOView加载可执行程序,查看0xC060所载区段的属性。


因为0xC060正好是区段开始的地方,所以正好命中,下面看下这个包含这个Section的Segment的属性:


可以看到这个Segment的属性为:RW,也就是可以改的,因此是可Hook的。

同时基于这个理论:C++的多态特性是运行时特性,运行时本身也是需要修改的,因此也可得到其是可Hook的。






你可能感兴趣的:(ios,C++,虚函数,hook,IDA)