iOS逆向工程

IPhone一起玩越狱 -(十七)- tweak 反反反插入

2018-06-29  本文已影响35人  struggle3g

引言

tweak: 在越狱环境,我要去修改,玩玩某个App,需要做的就是用theos创建一个tweak的项目,然后去修改App
反tweak: 当我知道tweak去将动态库临时插入进程从而修改我的App的时候,这么搞那可不行万一怀孕了呐?,插入进程需要的DYLD的宏的环境变量DYLD_INSTER_LIBRARIES,查看dyld的源代码,我知道了在MachO文件中添加一个section其中segmentname、sectionname分别为__RESTRICT、__restrict从而达到我要的防治进程使用DYLD临时插入动态库
反反tweak: 前几天玩的好好的App,突然之间tweak插入进程插不进去,我擦,这怎么回事? 经过反复搜索,各种途径的努力,原来App在项目打包的时候,在MachO文件中添加了一个section其中segmentname、sectionname分别为__RESTRICT、__restrict,那么我只要修改MachO文件中的这个section,使它的segmentname、sectionname任意字段修改不等于__RESTRICT、__restrict,那么我的目的就达到了,然后我还是可以爆你。

反反反 tweak

负面情绪+10086
mmp的,我听说在某dia、某手又有爆我的App,你说气不气,你TM修改我的MachO文件,你这是犯规擦
既然你做初一,也别怪我做十五。
你既然修改我的MachO文件,那么我每次运行App的时候我会检测我的MachO文件中的section,它是否包含segmentname、sectionname分别为__RESTRICT、__restrict,如果没有这个section就直接闪退,哥么你想干哈?

分析

static bool hasRestrictedSegment(const macho_header* mh)
{
    const uint32_t cmd_count = mh->ncmds;
    const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
    const struct load_command* cmd = cmds;
    for (uint32_t i = 0; i < cmd_count; ++i) {
        switch (cmd->cmd) {
            case LC_SEGMENT_COMMAND:
            {
                const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
                
                //dyld::log("seg name: %s\n", seg->segname);
                if (strcmp(seg->segname, "__RESTRICT") == 0) {
                    const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
                    const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
                    for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                        if (strcmp(sect->sectname, "__restrict") == 0)
                            return true;
                    }
                }
            }
                break;
        }
        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
    }
    
    return false;
}

dyld的源码 dyld.cpp
根据上述代码,我们可以判断MachO文件中是否有我们提到的section。
我们调用这个方法,需要一个参数macho_header* mh

在系统的头文件,#import <mach-o/loader.h>存在 macho_headermach_header_64

struct mach_header {
    uint32_t    magic;      /* mach magic number identifier */
    cpu_type_t  cputype;    /* cpu specifier */
    cpu_subtype_t   cpusubtype; /* machine specifier */
    uint32_t    filetype;   /* type of file */
    uint32_t    ncmds;      /* number of load commands */
    uint32_t    sizeofcmds; /* the size of all the load commands */
    uint32_t    flags;      /* flags */
};

struct mach_header_64 {
    uint32_t    magic;      /* mach magic number identifier */
    cpu_type_t  cputype;    /* cpu specifier */
    cpu_subtype_t   cpusubtype; /* machine specifier */
    uint32_t    filetype;   /* type of file */
    uint32_t    ncmds;      /* number of load commands */
    uint32_t    sizeofcmds; /* the size of all the load commands */
    uint32_t    flags;      /* flags */
    uint32_t    reserved;   /* reserved */
};

在#import <mach-o/dyld.h> 存在一段代码

//可以直接拿到`mach_header`
extern const struct mach_header*   _dyld_get_image_header(uint32_t image_index) 
//uint32_t image_index 是的角标MachO、dylib等的前面的标示
//lldb调试的时候  image list 
//MachO的索引是0

防护代码在你的App中调用

// ARM and x86_64 are the only architecture that use cpu-sub-types
#define CPU_SUBTYPES_SUPPORTED  ((__arm__ || __arm64__ || __x86_64__) && !TARGET_IPHONE_SIMULATOR)

#if __LP64__
#define macho_header             mach_header_64
#define LC_SEGMENT_COMMAND       LC_SEGMENT_64
#define macho_segment_command    segment_command_64
#define macho_section            section_64
#else
#define macho_header             mach_header
#define LC_SEGMENT_COMMAND       LC_SEGMENT
#define macho_segment_command    segment_command
#define macho_section            section
#endif




+ (void)load{
    //dyld启动app最先加载的是自己的MachO  通过lldb:image list
    const struct macho_header *header = (const struct macho_header *)_dyld_get_image_header(0);

    if(hasRestrictedSegment(header)){
        NSLog(@"反tweak正常");
    }else{
        NSLog(@"兄弟是不是找事?");
        exit(0);
        
    }
    
}

static bool hasRestrictedSegment(const struct macho_header* mh)
{
    const uint32_t cmd_count = mh->ncmds;
    const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(struct macho_header));
    const struct load_command* cmd = cmds;
    for (uint32_t i = 0; i < cmd_count; ++i) {
        switch (cmd->cmd) {
            case LC_SEGMENT_COMMAND:
            {
                const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
                
                printf("seg name: %s\n", seg->segname);
                if (strcmp(seg->segname, "__RESTRICT") == 0) {
                    const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
                    const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
                    for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                        if (strcmp(sect->sectname, "__restrict") == 0)
                            return true;
                    }
                }
            }
                break;
        }
        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
    }
    
    return false;
}

以上

上一篇下一篇

猜你喜欢

热点阅读