依葫芦画瓢hook一个Mac App最后失败的全过程

引言

昨天看完论坛里的五分钟搞不定新版Mac迅雷后成功依葫芦画瓢hook掉了一个Mac程序,今天很有成就感得准备再把Interface Inspector的15天测试干掉,结果屡屡受挫。就自己先写了个小demo测试一下,结果就有了下面这篇帖子……

小demo

一个非常简单的demo,大概就是软件正中一个按钮,点击之后alert(“hi!”)。核心代码如下:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.
}

- (IBAction)sayHi:(NSButton *)sender {
    NSAlert *alert = NSAlert.new;
    alert.messageText = @"hi!";
    alert.alertStyle = NSAlertStyleInformational;
    [alert runModal];
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}


@end

hook过程再现

根据多年想像的编程经验 写了下面这个Logos:

%config(generator=internal)

// You don't need to #include <substrate.h>, it will be done automatically, as will
// the generation of a class list and an automatic constructor.
#import <Foundation/Foundation.h>

%hook ViewController


// Hooking an instance method with an argument.
- (void)sayHi:(id)argument {
    NSAlert *r15 = [[NSAlert alloc] init];
    [r15 setMessageText:@"hello world!"];
    [r15 setAlertStyle:0x1];
    [r15 runModal];
}



// Always make sure you clean up after yourself; Not doing so could have grave consequences!
%end

%ctor {
    NSLog(@"!!!!!!inject success!!!!!!!");
}

想要实现的效果是点击了按钮之后say的不再是“hi!”而是“hello world!”
然后我就凭借我多年的编程经验在终端中输入了如下几个我根本不知道是在干什么的命名:

$THEOS/bin/logos.pl ./Tweak.xm > ~/desktop/target/abc
clang -shared -undefined dynamic_lookup -o ~/Desktop/SayHi/SayHi.app/Contents/MacOS/lib.dylib ~/desktop/target/abc
./optool install -c load -p @executable_path/lib.dylib -t ~/Desktop/SayHi/SayHi.app/Contents/MacOS/SayHi

各位千万不要问我我在干什么,因为我也不知道这是在干什么,总之我就执行了上面一波操作,结果自然是:

依旧是say hi!
当然这就很奇怪是不是,毕竟我注入Interface Inspector至少是直接闪退吧,这个什么都没有发生就很奇怪。所以我认为是我的Logos写错了,于是我修改了demo的代码,如下:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.
}

- (NSString *)hi {
    return @"hi!";
}

- (IBAction)sayHi:(NSButton *)sender {
    NSAlert *alert = [NSAlert.alloc init];
    alert.messageText = [self hi];
    alert.alertStyle = NSAlertStyleInformational;
    [alert runModal];
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}


@end

然后再次编写了一个我觉得再错我的智商估计要告别逆向界的Logos,如下:

%config(generator=internal)

// You don't need to #include <substrate.h>, it will be done automatically, as will
// the generation of a class list and an automatic constructor.
#import <Foundation/Foundation.h>

%hook ViewController


// Hooking an instance method with an argument.
- (NSString *)hi {
	return @"hello world!";
}



// Always make sure you clean up after yourself; Not doing so could have grave consequences!
%end

%ctor {
    NSLog(@"!!!!!!inject success!!!!!!!");
}

然后再次achieve了一个demo程序,再次执行下面的天书命令:

$THEOS/bin/logos.pl ./Tweak.xm > ~/desktop/target/abc
clang -shared -undefined dynamic_lookup -o ~/Desktop/SayHi/SayHi.app/Contents/MacOS/lib.dylib ~/desktop/target/abc
./optool install -c load -p @executable_path/lib.dylib -t ~/Desktop/SayHi/SayHi.app/Contents/MacOS/SayHi

结果当然是什么都没有发生,于是诞生了这个帖子,不知道给位大大能否告诉在下我到底是哪里错了,还有我是否应该就此退出 逆向界

应该

所以我果然是哪里写错了么。。。

我今天在试了一下,发现了一个警告如下:
ld: warning: ignoring file ./sayHi, file was built for unsupported file format ( 0x23 0x6C 0x69 0x6E 0x65 0x20 0x31 0x20 0x22 0x54 0x77 0x65 0x61 0x6B 0x2E 0x78 ) which is not the architecture being linked (x86_64): ./sayHi

这不写了么

是的,但是我刚刚查了很久,完全不知道如何修改啊。大大你在■■迅雷的时候没有遇到这种情况么:sweat:

贴完整步骤

完整步骤

  1. 写了一个小程序

点击按钮弹窗
核心代码:

- (NSString *)hi {
    return @"hi!";
}

- (IBAction)sayHi:(NSButton *)sender {//点击按钮say hi!
    NSAlert *alert = [NSAlert.alloc init];
    alert.messageText = [self hi];
    alert.alertStyle = NSAlertStyleInformational;
    [alert runModal];
}
  1. 打包app
    刚刚打的包
  2. 生成theos模版
  3. 修改Tweak.xm为如下代码
%config(generator=internal)

// You don't need to #include <substrate.h>, it will be done automatically, as will
// the generation of a class list and an automatic constructor.
#import <Foundation/Foundation.h>

%hook ViewController


// Hooking an instance method with an argument.
- (NSString *)hi {
	return @"hello world!";
}



// Always make sure you clean up after yourself; Not doing so could have grave consequences!
%end

%ctor {
    NSLog(@"!!!!!!inject success!!!!!!!");
}
  1. 执行$THEOS/bin/logos.pl ./Tweak.xm > ./abc命令
  2. 执行clang -shared -undefined dynamic_lookup -o ./SayHi.app/Contents/MacOS/lib.dylib ./abc 命令

    提示警告:
ld: warning: ignoring file ./abc, file was built for unsupported file format ( 0x23 0x6C 0x69 0x6E 0x65 0x20 0x31 0x20 0x22 0x2E 0x2F 0x54 0x77 0x65 0x61 0x6B ) which is not the architecture being linked (x86_64): ./abc


7. 执行optool install -c load -p @executable_path/lib.dylib -t ./SayHi.app/Contents/MacOS/SayHi 命令

提示:

Found thin header...
Inserting a LC_LOAD_DYLIB command for architecture: x86_64
Successfully inserted a LC_LOAD_DYLIB command for x86_64
Writing executable to SayHi.app/Contents/MacOS/SayHi...


8. 运行注入后程序,注入失败

16进制的“#line 1 "./Tweak”
正常编译出来dylib肯定不长这样

执行$THEOS/bin/logos.pl ./Tweak.xm > ./abc命令

他的./abc是个源码

是啊就是要logos预处理器把logos转换成源码啊这里

哦我知道了[quote=“wjk930726, post:8, topic:9343”]
执行clang -shared -undefined dynamic_lookup -o ./SayHi.app/Contents/MacOS/lib.dylib ./abc命令
[/quote]
clang根据文件拓展名来判断类型的。你这没后缀clang不认识。
全部改叫abc.mm就可以了

我重新把它改成.mm果然就行了,原来还有这种操作啊,我一直以为*nix系统对后缀名不敏感的。又学到了一招!谢谢大大

总体来说我认为确实是这样。但是clang要依赖这玩意儿来确定目标文件的语言类型啊。
虽然实际上即使你不留后缀也可以加个flag强制clang标记成对应的语言,但这种高端技巧就不在新手贴的讨论范围内了。而且这也不是什么好的编程实践