逆向破解三-app简单的插件开发

经过前几篇文章的讲解我们可以在内存中修改代码或者查看一些信息在或者可以把appstore的app破解成ipa文件找到他的可执行文件.但是我们还是不能真正修改app中的内容,这篇文章来解释怎样做一个插件,也就是把代码真正的注入的到app中。

  • 注入代码以及永久性的修改app的内容我们用到最多的是theos,也就是需要安装这个工具来hook别人app的代码来达到自己的目的。

安装签名工具ldid

如果你还没有安装homebrew,那么请先安装homebrew,具体安装homebrew的方法是:请看这个网址:https://brew.sh/
安装好之后 请执行这个命令:

  brew install ldid

这个过程可能比较漫长,因为根据你的mac系统可能你的brew不是最新的,他可能会先更新homebrew,然后才会执行安装ldid,耐心等待。
比如我执行命令安装成功为:


image.png

修改环境变量

  • 修改用户的配置文件
vim ~/.bash_profile

注意:当你也像我这样输入的时候可能是直接显示文件也就是说什么都没有的,这时候你也该感到好奇 为什么我没有这个文件呢,那么你可以执行这个命令来具体查看一下是否有这个文件

find ~ -name "*.bash_profile"

我当时就是这么找的,结果什么都没有。一看傻了,按道理不应该啊,因为至少系统的usr/bin 、bin什么的都是在这里配置的。怀着无限的郁闷与好奇我在网上查了一下,网上也有遇到我这样的问题。他们的意思就是创建一个.bash_profile文件,好吧那就创建一个然后在进行编辑。

touch .bash_profile(注意我的路径),我是在这个 ~ 路径下
image.png

开始编辑

vim ~/.bash_profile 

按住i进行编辑
输入

 export THEOS=~/theos
 export PATH=$THEOS/bin:$PATH

解释 :THEOS就代表~/theos这个路径,$是引用的意思,第二句话的意思是:引用THEOS并且引用之前的PATH,因为我们虽然知道PATH可能包含usr/bin bin 等等的,但是一旦输入的不全呢,所以最稳妥的办法是:就是导入之前的PATH.输入完毕之后按一下esc 然后:wq 保存并退出。这时候的环境是配置好了,但是没有立即生效,所以需要执行一下命令:

source ~/.bash_profile

或者把整个终端全部退出 ,重新执行。

下载theos

下载theos 建议在刚才的文件下,执行这个git命令

git clone --recursive https://github.com/theos/theos.git $THEOS

解释:recursive这个是为了下载theos所关联的库,$THEOS是指下载到这个文件夹下。
下载完成验证是否ok(在home路径下)

echo $PATH

如果你出现了这个


image.png

那说明你安装成功了。
下面我们切换到桌面来开始创建一个工程,将我们需要修改的代码最终写成deb 的库然后装到手机上就可以永久改掉手机的代码。
我的执行结果为:


image.png

工程的创建以及hook代码编写

  • 工程创建
    由上图可知我们选择tweak,这个一般就是我们创建工程 编写插件的。


    image.png

    解释:我们现在要做的是去掉某一个app的广告,上面中有需要输入工程的bundle identifier ,怎样获得他 我在我的简书中cycript中已经告诉大家怎样拿到appid。还有他要求你输入作者名字、还有在springBoard中做什么。不用管直接按回车因为这个就是你电脑默认的。其他的该怎么写就怎么写,我在图片中有注释。

  • 编写代码部分
    我们现在要做的是去掉这个app中的广告。


    image.png

    经过刚才的创建我们已经在桌面上生成了一个工程文件


    image.png

    1.编写Makefile文件
    工程已经帮我们生成了4个文件
    image.png

    找到Makefile 用vim进行编辑,在开始的导入ip地址和端口号,比如我的ip地址和端口号为:


    image.png

    为什么是127.0.0.1呢?因为我的手机是通过usb来进行链接的,并且我把手机ssh的22端口映射到我电脑的mac上的10010,所以才这样输入。具体查看我的越狱环境搭建的简书。顺便说下可以看到了一个命令就是重启springBoard,也就是一会我们执行完代码就会自动重启springBoard。
    2.编写代码
    打开Tweak.xm文件,开始进行编写。这里需要我们找到具体hook的代码,怎么找到呢,首先我们需要对我们的手机要修改的app进行脱壳 ,然后找到他的可执行的文件然后在通过class-dump这个工具找到他的.h文件,然后我们通过工具Reveal找到他具体在哪个类中。怎样解压他的头文件我在逆向破解1中的简书中有说道。下面我们我们通过Reveal找到广告的view
    比如我们找到了这个文件
    image.png

    然后我们通过cycript试一试看看能不能再内存中给他去掉。
    通过执行命令可以看到
    image.png

    image.png

    可以看到 在内存中已经去掉他了。现在我们开始找到这个类 进行hook他。
    我之前的文章已经说过怎么找到他的可执行文件已经用class-dump找到他的头文件(至于这个app我不是通过Clutch来进行获得的,是通过Dumpencrypted 来弄的Clutch没有成功不知道为什么)
    通过找到他的头文件然后在reveal工具查看广告所在的父类。下面开始执行命令。
    首先需要在Makefile文件中配置ip和port端口。比如我的配置的ip和端口是:

// 这两个需要配置
export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=10010
/***********横线下的都不用管,默认就有***********/
include $(THEOS)/makefiles/common.mk
// 默认的你不用管
TWEAK_NAME = ***Tweak
tingTweak_FILES = Tweak.xm

include $(THEOS_MAKE_PATH)/tweak.mk

after-install::
    install.exec "killall -9 SpringBoard"

下面开始写hook的代码,当然你要干其他的事情可以不hook(他的意思是替换什么方法就是runtime中方法的替换)
根据头文件并且我已经用cycript也已经验证过了。现在Tweak.xm进行编辑,打开删除里面的所有代码,然后按照我的这个方式进行书写。

%hook XMSoundPatchPosterView
- (id)initWithFrame:(struct CGRect)arg1
{
    return nil;

}
%end

%hook XMSoundPatchPosterViewTwo
- (id)initWithFrame:(struct CGRect)arg1{

    return nil;
}
%end

他的格式为:

%hook 类名
  要替换的代码
%end

保存 然后我们执行命令 ,记住要在Makefile所在的目录,首先执行命令:

make 

然后在执行打包命令(这个命令其实是编译在打包,如果我们连续执行的话可以不用写make):

make package

在执行安装命令 这样的话就会安装到你的手机上

make install 

下面是我的执行结果


image.png

执行这个命令的时候手机会重启,在点开我们刚才的按个app发现广告没有了。我就不晒图了。

  • 注意点:
    1.执行make的时候可能会出现这个错误


    image.png

    个人建议你的电脑不要安装多个xcode 有一个最新的就行了,你的解决方案是:


    image.png

    还有可能出现这个错误:
    image.png

    你的解决方案是:
    image.png
  1. make package 的错误情况


    image.png

    你的解决方案是:


    image.png

    说明:本人在这块的时候出现的问题不是和这一模一样的但是看着错误信息是类似的,而且并没有在dm.pl这块中找到需要注释的。所以只是在deb.mk中做了修改。结果也解决了问题,如果你执行make package中出现了警告不用管,只要不是错误就行。
  2. make install 一般不会出现错误,只要你的文件中不要写错信息就行了。其他的错误信息你可能要自己查一下google了。自己要有解决问题的能力。

怎样让广告复原

  1. 如果有一天我们想来看这个广告,那么我们只需要在这个目录下:找到当时我们当时装到手机的东西 删除它就可以了,如图:


    image.png

    我们只需要把我箭头指向的那两个删除就可以了。
    2.因为我们是从Cydia中安装的,那么可以在Cydia中找到这个插件来进行删除,这样删除的更彻底也更加的方便。

小练习

1.在微信发现页面添加一组(自动枪红包和退出登录)
其中我们可以在我们的home目录下编写一个脚本,叫make.sh

make clean && make && make package && make install 

到时候我们直接执行我们这个脚本就行了。
目前写的代码如下:



#define DGImageNamePath(path) @"/Library/PreferenceLoader/Preferences/DGWeChat/" #path
#define DGSwicthKey @"DG_SwicthKey"

%hook FindFriendEntryViewController

- (double)tableView:(id)tableView heightForRowAtIndexPath:(id)arg2
{
    if ([arg2 section] == [self numberOfSectionsInTableView:tableView] - 1){
        return 44;
    }else{
        return %orig;
    }


}
- (long long)tableView:(id)tableView numberOfRowsInSection:(long long)section
{
    if (section == [self numberOfSectionsInTableView:tableView] - 1){
        return 2;
    }else{
        return %orig;
    }

}
- (long long)numberOfSectionsInTableView:(id)tableView{

    return %orig + 1;
}
- (id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath{


    if ([indexPath section] == [self numberOfSectionsInTableView:tableView] - 1){

    NSString *cellId = ([indexPath row] == 1) ? @"exitCellId" : @"autoCellId";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
        cell.backgroundColor = [UIColor whiteColor];
        cell.imageView.image = [UIImage imageWithContentsOfFile:DGImageNamePath(skull.png)];
    }
    if ([indexPath row] == 0) {

        cell.textLabel.text = @"自动抢红包";
        UISwitch *switchView = [[UISwitch alloc] init];
        switchView.on = [[NSUserDefaults standardUserDefaults] boolForKey:DGSwicthKey];
        [switchView addTarget:self action:@selector(dg_SwicthChange:) forControlEvents:UIControlEventValueChanged];
        cell.accessoryView = switchView;
        

    }else if ([indexPath row] == 1){

        cell.textLabel.text = @"退出登录";
        
    }
        return cell;
    }else{
        return %orig;
    }
}
// 说明是新的方法不能hook
%new
- (void)dg_SwicthChange:(UISwitch *)switchView{
    
    [[NSUserDefaults standardUserDefaults] setBool:switchView.isOn forKey:DGSwicthKey];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
}
- (void)tableView:(id)tableView didSelectRowAtIndexPath:(id)indexPath
{
    if ([indexPath section] == [self numberOfSectionsInTableView:tableView] - 1){
        if ([indexPath row] == 1){
            // 终止进程
            abort();
        }else if ([indexPath row] == 0){
            [tableView deselectRowAtIndexPath:indexPath animated:YES];  
        }
        return;
    }else{
        %orig;
        return;
    }

}
%end

其实我们也可以把我们配置ip地址和端口的东西放到配置文件中去,也就是.bash_profile文件中
如下:

export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=10010

这样的话就不用每次在Makefile文件中进行配置了。
解释:
1.其中宏定义路径可以按照我代码中这样书写

#define DGImageNamePath(path) @"/Library/PreferenceLoader/Preferences/DGWeChat/" #path

这样的话也是自动拼接。
2.swith中的方法是新方法,那么我们需要在我们的方法前加上%new,比如我代码中是这样使用的:

// 说明是新的方法不能hook
%new
- (void)dg_SwicthChange:(UISwitch *)switchView{
    
    [[NSUserDefaults standardUserDefaults] setBool:switchView.isOn forKey:DGSwicthKey];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
}

3.关于导入图片的问题,我们首先应该在我们的工程文件下新建一个文件,名字叫
layout,他的级别和我们的手机的根目录是同一级别,你也可以认为是手机的根目录,比如我想把图片放到手机的这个目录,那么首先我需要在手机中建一个目录为:


image.png

然后我工程建的目录为:


image.png

到时候我一执行命令那么我的图片就会放到手机的这个目录下,比如我的执行完命令之后为:
image.png

最后我们可以看到微信的界面被我改为:
image.png

一些小的语法

一我们在编写我们这个小插件的时候,有时候我们的代码不能写在一个文件里,我们可能需要建立文件夹将我们的代码文件放到文件夹里。

比如我的代码目录结构是这样的:


image.png

我创建了一个src的文件夹,里面创建了一个Model文件夹。其中Tweak.m文件在src文件夹下,DGPerson在Model文件下。这样的话我们需要修改我们的Makefile文件,也就是引用路径问题。我的Makefile路径修改如下:

export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=10010

include $(THEOS)/makefiles/common.mk

TWEAK_NAME = weChatTweak
weChatTweak_FILES = src/*.xm src/Model/*.m

include $(THEOS_MAKE_PATH)/tweak.mk

after-install::
    install.exec "killall -9 SpringBoard"

其中我们只需要配置weChatTweak_FILES这个路径就好了。可以看到我们配置我们的Tweak.xm文件,其中*号代表的都是所有的,然后我们还需要配置DGPerson文件,其中中间用一个空格隔开,记住是一个空格。然后如果我们在Tweak.m文件中引用person,也需要写上的路径,比如我的引用是这样的:

#import "src/Model/DGPerson.h"
  • 注意:
    1.我们在Makefile中有时候发现你用是会报错误的,我就是我发现我用就会报错,但是有的人用*是没错的不知道为什么。
    2.建议如果你创建了新的文件什么的,建议你ba下面的文件删除,在重新执行执行命令。
    image.png

    其中.theos为隐藏文件夹,怎样看到自己电脑的隐藏文件,自己去百度一下吧。
怎样打包release包,

我们现在的包打的都是debeg包,怎样知道的我们打的包是debug包呢?


image.png

我们可以看到我们打的就是debug包。下面说一下怎么打release包,其实很简单就是在打包的时候将命令改为:

make package debug=0

然后我们依次执行 make clean、make、make package debug=0、make install,最后看一下Cydia为:


image.png

可以看到变为release的,并且包也稍微少了一点。

%ctor:在加载动态库前调用:

一般形式为:

%ctor{
  NSLog(@"asdasdasdasd");
}
%dtor:在程序退出时候调用

一般的形式为:

%dtor{
  NSLog(@"asdasdasdasd");
}
%c(className):生成一个class对象

不用纠结就是logos的语法。

更多的logos的语法见这个网址:http://iphonedevwiki.net/index.php/Logos

推荐阅读更多精彩内容