逆向编程 Logos基本使用

使用 Cycript 的时候,安装了 Monkey Dev, 用 Monkey Dev 新建的工程后,文件夹 xxxDylib 下有一个 Logos 的文件夹,该文件夹下有一个后缀为 .xm 的文件,.xm 文件中所使用的就是 Logos 语法。
如果点击 .xm 文件无法显示其中代码,Xcode 做如下更改即可。

逆向编程 Logos基本使用_第1张图片
image

1、什么是 Logos?

Logos 是一种语法,该语法其实是CydiaSubstruct 框架提供的一组宏定义。便于开发者使用宏进行 HOOK 操作。语法简单,功能强大且稳定。

2、Logos 语法说明

Logos的官网。

文件后缀名为 .xm 代表支持 Logos 语法、CC++,如果后缀名为 .x 代表支持 Logos 语法和 C

1、%hook

你要 Hook 哪个类。 %hook 后面接类名:%hook ViewController%end 结束,中间放的是需要 Hook 的方法

%hook ViewController

- (void)hookMethod {

} 

%end

2、%group

用于分组,比如在不同 iOS 系统版本上使用不同分组的代码,兼容性就会更好。

%group group1

%hook ViewController

- (void)hookMethod {
   NSLog(@"第一组Hook");
}

%end

%end

%group group2

%hook ViewController

- (void)hookMethod {
   NSLog(@"第二组Hook");
}

%end

%end

3、%init

初始化一个组。

%init(group1)
%init(group2)

4、%ctor

构造函数,如果有上述分组可以在这个方法里面去判断。

%ctor{
    NSString *version = [UIDevice currentDevice].systemVersion;
    if (version.floatValue >= 8.0) {
        %init(group1)
    } else {
        %init(group2)
    }
}

5、%dtor

析构函数。

%dtor {
    //释放一些东西...
}

6、%log

输出方法的一些详细信息,就类似于 LLDBframe variable

7、%orig

Hook到一个方法后,保持原来的方法的调用,如果该方法有返回值,也能接收返回值。

8、%new

动态添加方法

%new
- (void)addMethod {
    //一些方法实现...
}

%new
+ (void)classMethod {
    //一些方法实现...
}

9、%c

如果是添加了一个类方法,就需要使用类对象是调用,%c(类名) 就可以获取类对象。

3、Logos 语法使用

Xcode 新建一个普通工程命名为 LogosLoginText ,然后在 ViewController.m 中写入如下代码:

//
//  ViewController.m
//  LogosLoginText
//
//  Created by ABC on 2019/11/9.
//  Copyright © 2019 ABC. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self postWithUID:@"ABC" pwd:@"123456"];
}

- (void) postWithUID:(NSString *)uid pwd:(NSString *)pwd {

    if ([uid isEqualToString:@"ABC"] && [pwd isEqualToString:@"123456"]) {

        //登录成功
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"登录成功" message:nil preferredStyle:(UIAlertControllerStyleAlert)];

        UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:nil];
        [alertController addAction:okAction];

        [self presentViewController:alertController animated:YES completion:nil];

    } else {

        //登录失败
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"登录失败" message:nil preferredStyle:(UIAlertControllerStyleAlert)];

        UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:nil];
        [alertController addAction:okAction];

        [self presentViewController:alertController animated:YES completion:nil];
    }
}

@end

上方代码就是简单的一个判断,目的是在使用 Logos 语法 Hook 的时候,改变了相应的值,会提示错误,以便于知道 Hook 到改方法并修改值成功了。

添加完了上述代码,真机编译一下就可以了,这里只是为了拿到生成的 LogosLoginText.app 包,以便于使用 Monkey Dev 重签而已,就相当于模拟其他 App

编译成功后找到 Xcode 工程里 Products 文件下的 LogosLoginText.appShow in Finder 拷贝出来。

新建 Monkey 工程,然后重签 LogosLoginText.app 成功后,使用 class-dump 导出LogosLoginText.MachO 的头文件,这样准备工作就完成了。

打开 LogosLoginText 的头文件,就是假装打开了其他 App 的头文件,然后分析一下:

逆向编程 Logos基本使用_第2张图片
image

假装看到了登录方法 - (void)postWithUID:(id)arg1 pwd:(id)arg2; 然后我们对这个方法进行 Hook,然后在注入库 MonkeyLoginDylib.libMonkeyLoginDylib.xm 中写要注入的代码。

// See http://iphonedevwiki.net/index.php/Logos

#import 

%hook ViewController

%hook ViewController

- (void)postWithUID:(id)arg1 pwd:(id)arg2 {
   NSLog(@"Hook到了登录");
}

%end

然后点击屏幕,发现控制台打印了:Hook到了登录,并没有弹出 AlertView 证明该方法被 Hook 成功了。

如果需要版本判断,就需要分组了。使用 %group%init 和 % ctor 了。

%group group1

%hook ViewController

- (void)postWithUID:(id)arg1 pwd:(id)arg2 {
   NSLog(@"第一组Hook到了登录");
}

%end

%end

%group group2

%hook ViewController

- (void)postWithUID:(id)arg1 pwd:(id)arg2 {
   NSLog(@"第二组Hook到了登录");
}

%end

%end

%ctor{
    NSString *version = [UIDevice currentDevice].systemVersion;
    if (version.floatValue >= 8.0) {
        %init(group1)
    } else {
        %init(group2)
    }
}

注意:组一定会有的,如果没有写组,那么Logos 会默认生成一个组 _ungrouped 并自己调用构造函数和 init 方法创建。

尝试输出一下当前方法的详细信息 %log,添加后运行一下,查看结果发现,输出了参数详细的值和方法的指针地址。

%hook ViewController

- (void)postWithUID:(id)arg1 pwd:(id)arg2 {
    %log;
    NSLog(@"Hook到了登录");
}

%end

image

因为 Hook 了这个方法导致,该方法没有执行原有的,现在通过 %orig 保持原来的调用。添加完成后重新运行,点击屏幕显示了 AlertView

%hook ViewController

- (void)postWithUID:(id)arg1 pwd:(id)arg2 {
    %log;
    %orig;
    NSLog(@"Hook到了登录");
}

%end

因为 - (void)postWithUID:(id)arg1 pwd:(id)arg2 是有参数的,所以可以通过 %orig 更改值:%orig(@"AAA",@"111111"),再出重新运行就发现,AlertView 提示登录失败了。

%hook ViewController

- (void)postWithUID:(id)arg1 pwd:(id)arg2 {
    %log;
    %orig(@"AAA",@"11111");
    NSLog(@"Hook到了登录");
}

%end

逆向编程 Logos基本使用_第3张图片
image

现在给 - (void)postWithUID:(id)arg1 pwd:(id)arg2 需要调用一个动态添加的方法 testMethod 就需要用到 %new 了。

当使用 [self testMethod] 会提示找不到 ViewController ,在逆向中如果找不到这个类,只需要将这个类和新添加的方法声明一下就可以,仅仅是为了让编译器编译能通过。

如果使用原来类里方法过多,可以把 class-dump 导出的头文件直接拖入 Logos文件夹下,在这个头文件里声明一下动态添加的方法名称。

代码如下:

@interface ViewController

- (void)testMethod;

@end

%hook ViewController

%new
- (void)testMethod {
    NSLog(@"调用了我动态添加的方法");
}

- (void)postWithUID:(id)arg1 pwd:(id)arg2 {
    %log;
    %orig(@"AAA",@"11111");
    NSLog(@"Hook到了登录");
    [self testMethod];
}

%end

重启运行,点击屏幕,控制台就打印了刚才添加方法中的 NSLog

image

上方的代码使用的是实例方法,需要添加一个类方法,然后可以使用 %c(类名) 直接调用类方法。

@interface ViewController

- (void)testMethod;

@end

%hook ViewController

%new
- (void)testMethod {
    NSLog(@"调用了我动态添加的方法");
}

%new
+ (void)classMethod {
    NSLog(@"调用了我动态添加的类方法");
}

- (void)postWithUID:(id)arg1 pwd:(id)arg2 {
    %log;
    %orig(@"AAA",@"11111");
    NSLog(@"Hook到了登录");
    [self testMethod];
    [%c(ViewController) classMethod];
}

%end

以上就是 Logos 的介绍和基本用法了

来自:有梦想的程序员
链接:https://www.jianshu.com/p/8405693fea08

你可能感兴趣的:(逆向编程 Logos基本使用)