ios逆向之MobileHooker
CydiaSubstrate是绝大部分tweak常工作的基本,它由MobileHooker、MobileLoader和Safe mode组成。 MobileHooker的作用是替换系统函数,也就是所谓的hook,它主要包含2个函数:
void MSHookMessageEx(Class class,SEL selector,IMP replacement,IMP *result);
void MSHookFunction(void* funciton,void* replacement,void** p_original);
前者作用于object-C函数,后者作用于C和C++函数;
举例说明:
1、用theos创建名为iOSRETargetApp的appliction,创建好后,将RootViewController.m改名为RootViewController.mm,以便支持c++代码;
在RootViewController.mm中增加代码如下:
#import 'XXRootViewController.h'
//创建c++类
class CPPClass
{
public:
void cppFunction(const char*);
};
//c++类方法实现
void CPPClass::cppFunction(const char *arg0){
NSLog(@'----------iOSRE: cppFunction:%s',arg0);
NSString *junk=@'';
NSMutableArray *mulJunks;
int pid;
for (int i=0; i<</span>66; i++) {
u_int32_t randomNumber;
if (i%3==0)
randomNumber=arc4random_uniform(i);
NSProcessInfo *processInfo=[NS ProcessInfo processInfo];
NSString *hostName=processInfo.hostName;
pid=processInfo.processIdentifier;
NSString *globallyUniqueString=processInfo.globallyUniqueString;
NSString *processName=processInfo.processName;
NSArray *junks=@[hostName,globallyUniqueString,processName];
mulJunks=[NSMutableArray arrayWithArray:junks];
junk=[NSString stringWithFormat:@'pid=%d,hostName=%@,UniqueString=%@,processName=%@',pid,mulJunks[0],mulJunks[1],mulJunks[2]];
NSLog(@'junk[%d]=%@',i,junk);
//-----无效代码用来增加函数长度,使其对MSHookFunciton生效
junk=@'';
for (int j=0; j
if (pid % 6==0) {
junk=junks[j%3];
}
}
if (i % 68==1)
NSLog(@'----------this is cppFunction');
}
}
//c函数实现
extern 'C' void cFunction(const char *arg0){
NSLog(@'----------iOSRE: cFunction:%s',arg0);
NSString *junk=@'';
NSMutableArray *mulJunks;
int pid;
for (int i=0; i<</span>66; i++) {
u_int32_t randomNumber;
if (i%3==0)
randomNumber=arc4random_uniform(i);
NSProcessInfo *processInfo=[NSProcessInfo processInfo];
NSString *hostName=processInfo.hostName;
pid=processInfo.processIdentifier;
NSString *globallyUniqueString=processInfo.globallyUniqueString;
NSString *processName=processInfo.processName;
NSArray *junks=@[hostName,globallyUniqueString,processName];
mulJunks=[NSMutableArray arrayWithArray:junks];
junk=[NSString stringWithFormat:@'pid=%d,hostName=%@,UniqueString=%@,processName=%@',pid,mulJunks[0],mulJunks[1],mulJunks[2]];
NSLog(@'junk[%d]=%@',i,junk);
junk=@'';
for (int j=0; j
if (pid % 6==0) {
junk=junks[j%3];
}
}
if (i % 68==1)
NSLog(@'----------this is cFunction');
}
}
//短的c函数(验证短函数能否被hook)
extern 'C' void shortCFunction(const char *arg0){
CPPClass aCppclass;
aCppclass.cppFunction(arg0);
}
@implementation XXRootViewController {
NSMutableArray *_objects;
}
- (void)loadView {
[super loadView];
_objects = [[NSMutableArray alloc] init];
self.title = @'iOSREHookFuncTest';
self.navigationItem.leftBarButtonItem = self.editButtonItem;
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(adonTapped:)] autorelease];
NSLog(@'-------loadView--------');
}
-(void)viewDidLoad{
[super viewDidLoad];
NSLog(@'-------viewDidLoad-------');
//调用c++类方法
CPPClass mycppclass;
mycppclass.cppFunction('1:alled by CPPClass-object in viewDidLoad');
//调用c函数
cFunction('2:call a cFunction in viewDidLoad');
//调用短的c函数
shortCFunction('3:call a Short-cFunction in viewDidLoad');
}
配置好makefile等,然后make package install安装到ios上,然后远程到ios,并执行su mobile -c uicache以刷新桌面,使用刚安装的app图标在桌面上显示。
打开app,在xcode中的device里可以看到运行日志如下:
ios逆向之MobileHookerX
2、接下来用theos编写tweak,hook到上面app中的对应方法中。
用theos新建tweak工程,然后修改tweak.xm代码如下:
#import
void (*old__ZN8CPPClass11cppFunctionEPKc)(void *,const char *);
void new___ZN8CPPClass11cppFunctionEPKc(void *hiddenThis,const char *arg0){
NSLog(@'arg0=%s',arg0);
if (strcmp(arg0,'--------call a Short-cFunction in viewDidLoad')==0)
//表示hook short-cFunction失败,没有进new_shortCFunction
old__ZN8CPPClass11cppFunctionEPKc(hiddenThis,'-----this is a hijacked short C function from new___ZN8CPPClass11cppFunctionEPKc!');
else if (strcmp(arg0,'-----this is a hijacked short C function from new_shortCFunction')==0)
//表示hook short-cFunction成功,执行了new_shortCFunction
old__ZN8CPPClass11cppFunctionEPKc(hiddenThis,arg0);
else
old__ZN8CPPClass11cppFunctionEPKc(hiddenThis,'-----this is a hijacked C++ function from new___ZN8CPPClass11cppFunctionEPKc!');
}
void (*old_cFunction)(const char*);
void new_cFunction(const char *arg0){
old_cFunction('-----this is a hijacked C function from new_cFunction');
}
void (*old_shortCFunction)(const char *);
void new_shortCFunction(const char *arg0){
old_shortCFunction('-----this is a hijacked short C function from new_shortCFunction');
}
%ctor
{
@autoreleasepool
{
MSImageRef image=MSGetImageByName('/Applications/iOSREHookFuncTest.app/iOSREHookFuncTest');
//MSGetImageByName的参数是:Symbol函数实现所在的二进文件全路径
void *__ZN8CPPClass11cppFunctionEPKc=MSFindSymbol(image,'__ZN8CPPClass11cppFunctionEPKc');
//MSFindSymbol查找待hook的Symbol
if(__ZN8CPPClass11cppFunctionEPKc){
NSLog(@'-----iOSRE:Found C++Function!');
MSHookFunction((void *)__ZN8CPPClass11cppFunctionEPKc,(void *)&new___ZN8CPPClass11cppFunctionEPKc,(void **)&old__ZN8CPPClass11cppFunctionEPKc);
//MSHookFunction三个参数分别是:替换的原函数,替换的新函数,及被mobileHooker保存的原函数;
}
else
NSLog(@'-----iOSRE:not Found C++Function');
void *_cFunction=MSFindSymbol(image,'_cFunction');
if(_cFunction){
NSLog(@'-----iOSRE:Found C Function!');
MSHookFunction((void *)_cFunction,(void *)&new_cFunction,(void **)&old_cFunction);
}
else
NSLog(@'-----iOSRE:not Found C Function');
void *_shortCFunction=MSFindSymbol(image,'_shortCFunction');
if(_shortCFunction){
NSLog(@'-----iOSRE:Found short Function!');
MSHookFunction((void *)_shortCFunction,(void *)&new_shortCFunction,(void **)&old_shortCFunction);
}
else
NSLog(@'-----iOSRE:not Found short Function');
}
}
保存后,编译然后安装到ios上,然后再次执行上面的app,可以看到所有方法已经hook成功了:
ios逆向之MobileHooker
需要说明的是“黄书”上说short-CFuction不能hook是错误,实际是可以hook成功的。
另外,为什么在tweak里hook对应的函数名称变成了__ZN8CPPClass11cppFunctionEPKc,_cFunction,_shortCFunction?
这是因为编译器对函数名做了进一步的处理。要知道实际要hook的函数名是什么,只需要将ios目录下的二进制文件(/Applications/iOSREHookFuncTest.app/iOSREHookFuncTest)拖到IDA或hopper中分析即可知道。