越狱ios恢复微信撤回的图片_ios12未越狱 微信防消息撤回 - CSDN
  • 处女座强迫症最讨厌别人发消息后撤回了,尤其是发的图片还没看清就被撤了,或者还没来得及看的消息就已经被撤回了。最近逆向工程很火,所以我也简单的逆向了一把微信 for Mac & iOS。 为什么不对 iOS 动刀 Mac...

    处女座强迫症最讨厌别人发消息后撤回了,尤其是发的图片还没看清就被撤了,或者还没来得及看的消息就已经被撤回了。最近逆向工程很火,所以我也简单的逆向了一把微信 for Mac & iOS。

    为什么不对 iOS 动刀 Mac 和 iOS 双管齐下

    iOS 上的微信 APP 不一定始终在前台运行着,如果别人在撤回消息时微信在后台甚至手机锁屏、断网,这时很可能没有调用撤回消息的方法,甚至当微信重新返回到前台时,从服务器根本不会接到原来消息的数据,而是只收到了一条『撤回』指令。基于以上猜测,我决定对微信 for Mac 下手,毕竟电脑上的微信只要开着就一直接收消息,Mac 版微信不会跑到后台。

    PS:后来有人说 Web 版微信本来就不会撤回消息。。。可惜我从没用过;发送和撤回消息时 iOS 微信即使没运行,在之后接收服务器消息时依然会接到原消息内容。。。好吧是我高估了微信。。。

    20160701 Update:

    今天在家无聊顺手也吧 iOS 的微信搞定了,只是比 Mac 的稍微麻烦一点罢了。

    脑洞和胆子都要大

    之前看的一些逆向的教程里,感觉前期工作都是装软件配环境,噼里啪啦命令一顿敲,整的挺玄乎,其实都是用人家现成儿的工具做些事情,美其名曰『站在巨人的肩膀上』,这里不再赘述。在我看来第一个真正意义上有难度的事情就是一个字儿:『猜』!

    想要凭 dump 出的头文件里面的一堆函数名类名来猜出想要动手脚的地方,的确是个技术活儿。不仅考验脑洞,有时候还得运气好。把应用程序中的微信拖到 Hopper 中,搜下 “revoke”。这不,我一下子就猜出在哪个方法里面处理撤回消息逻辑的了:

    我凭借直觉,认为 -[MessageService onRevokeMsg:] 就是我们要找的方法。事实也证明我是对的,一次成功!先看看这个方法的伪代码:

    伪代码里面包含着好多层复杂的 if 判断逻辑,想必是这里复杂的业务逻辑让微信的同事无比抓狂,不要怕,我们不想让后面的事情发生,直接来个 return 就万事大吉!按快捷键 『option+A』 或者选择 Hopper 菜单栏的 『Modify -> Assemble Instruction…』来修改第一行汇编语句:

    可能觉得这里直接 return 掉是不是胆子也太大了,其实我还是看了函数里这坨代码的。那么多的 if 判断伴随着的是各种出错场景下的数据上报,真正核心业务逻辑也就是下面这坨:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    r12 = [[MessageData alloc] initWithMsgType:0x2710];
    rax = [r12 isSendFromSelf];
    rsi = @selector(toUsrName);
    if (LOBYTE(rax) != 0x0) {
    rbx = [[r13 toUsrName] retain];
    [r12 setFromUsrName:rbx];
    [rbx release];
    rbx = [[r13 fromUsrName] retain];
    [r12 setToUsrName:rbx];
    }
    else {
    rbx = [[r13 toUsrName] retain];
    [r12 setFromUsrName:rbx];
    [rbx release];
    rbx = [[r13 fromUsrName] retain];
    [r12 setToUsrName:rbx];
    }
    [rbx release];
    [r12 setMsgStatus:0x4];
    [r12 setMsgContent:var_58];
    [r12 setMsgCreateTime:LODWORD([r13 msgCreateTime])];
    [r15 AddLocalMsg:var_50 msgData:r12];
    rbx = [[NSArray arrayWithObject:r13] retain];
    [r15 DelMsg:var_50 msgList:rbx isDelAll:0x0];
    r15 = *objc_release;
    [rbx release];
    [r12 release];

    这段代码先是判断下撤回消息的人是不是自己,然后分情况更新 UI,最后生成并更新数据。既然没有啥重要操作,那就放心地忽略吧哈哈。

    现在需要将修改后的汇编重新生成新的可执行文件。选择 Hopper 菜单里的 『File -> Produce New Executable…』 后点 Yes:

    最后将生成的可执行文件替换到 /Applications/WeChat.app/Contents/MacOS/WeChat

    唯一让我不解的是无需对新的 WeChat 可执行文件进行代码签名微信依然可以正常运行。我是第一次玩逆向,还请前辈大神们指教。做了一系列撤回消息的尝试后,手机上面显示撤回,但 Mac 版微信的消息依然还在。一次猜中,成功!

    iOS 要稍微折腾一些

    前提是有一个已经砸壳的 ipa,要么自己在越狱机中用 dumpdecrypted 砸壳,或者干脆从第三方工具下一个已经砸壳的(也就是给越狱机安装的)。我一开始从同步助手下的有点问题,后来从PP助手下的。

    有了被砸壳的 ipa 就可以继续了,解压后找到里面的 WeChat.app ,注意用 codesign -dvvv WeChat.app 验证下签名。正版的 app 签名是腾讯的。。。

    第一步,猜,嗯,是 -[CMessageMgr onRevokeMsg:] 这个方法。类名换了而已。

    第二步,改汇编代码。这里需要改的是 Thumb 指令集。其实它是较新的 ARM 处理器的一种模式。我们比较关心的是各种指令的含义,尤其是如何从 Thumb 切换回 ARM,没错,就是用 bx

    这有一个Thumb® 16 位指令集快速参考卡

    最后还是跟之前一样替换生成的可执行文件。

    第三步,签名!建议先阅读 代码签名探析,了解下授权机制 (Entitlements) 和配置文件 (Provisioning)。这一步的前提是拥有一个合法证书,个人或企业都可以!

    先随便新建个工程(我的叫 testUIImage,昨晚研究 UIImage 时建的),一定要用证书签名,别选 None。。。target 架构选对(自己手机),编译后生成了个 ipa 文件。我们要的就是它里面的签名信息。

    先用 ldid 工具在桌面上生成个授权文件(Entitlements.plist):

    1
    ldid -e /Users/yangxiaoyu/Library/Developer/Xcode/DerivedData/testUIImage-aoqcifvynorulecqtwqqugleuktf/Build/Products/Debug-iphoneos/testUIImage.app/testUIImage > ~/Desktop/Entitlements.plist

    PS:我是用 homebrew 安装的 ldid

    然后把 testUIImage.app 中的配置文件 (Provisioning) embedded.mobileprovision 复制粘贴到我们的 WeChat.app 中。(右键显示包内容都会吧)

    最后用 codesign 命令对 WeChat.app 签名,注意替换为你自己的证书『常用名称』:

    1
    codesign -f -s "iPhone Developer: xiaoyu yang (XXXXXXXXX)" --entitlements /Users/yangxiaoyu/Desktop/Entitlements.plist /Users/yangxiaoyu/Desktop/微信_v6.3.22/Payload/WeChat.app

    第四步,也是最后一步,打包新的 WeChat.ipa:

    1
    xcrun -sdk iphoneos PackageApplication -v /Users/yangxiaoyu/Desktop/微信_v6.3.22/Payload/WeChat.app  -o ~/Desktop/WeChat.ipa

    现在可以把新的 WeChat.ipa 安装到自己的手机上啦!

    验证了下退出微信杀掉进程后,对方发消息并撤回,进入微信后依然可以收到撤回的消息。excited!

    后记

    其实逆向工程是门很有趣的学问,而任何学问都是入门简单深入难。本例看似容易,其实如果面对更加复杂的环境下,光靠我那点儿可怜的汇编知识肯定是不够的。如果是对 iOS 上的 APP 进行逆向,实则准备工作要麻烦得多。真正掌握了底层的原理和基础知识才是硬道理!

    其实是利用 Security 框架在 app 内部验证签名防止被人修改的,当然在 Mac 上我们最方便的还是用 codesign 命令啦。苹果提供了代码签名服务的文档

    老子终于也当了回标题党!啊哈!

    展开全文
  • OpenSSH(通过越狱手机Cydia安装) Cycript(通过越狱手机Cydia安装) Command Line Tools reveal(查看应用运行界面) hopper(查看二进制文件,用于分析代码) Xcode 苹果开发者证书或企业证书以及配置文件 一台越狱的...

    需要准备的东西
    dumpdecrypted 砸壳用
    yololib 注入需要用到
    class-dump 获取头文件用到,用于分析代码
    iOSOpenDev
    iTools或者pp助手等
    OpenSSH(通过越狱手机Cydia安装)
    Cycript(通过越狱手机Cydia安装)
    Command Line Tools
    reveal(查看应用运行界面)
    hopper(查看二进制文件,用于分析代码)
    Xcode
    苹果开发者证书或企业证书以及配置文件
    一台越狱的iPhone
    微信程序安装包

    一、砸壳

     

     获取砸壳后的文件有两种 :1.自己手动砸壳 2.通过第三方越狱平台下载已经砸壳的微信(如itools  pp助手等)
    

    手动砸壳:

    1.先在越狱软件上安装ssh插件OpenSSH ,命令行下和应用交互的插件Cycript

    2.让越狱手机和mac电脑在同一个局域网下(为了能够通过ssh服务从mac电脑访问手机)

    3.在mac的命令行终端 通过ssh服务登录手机 输入ssh root@192.168.80.212(手机ip)。默认情况下的root密码是alpine。root密码可以自己修改。

    4.在手机上运行微信 , 然后通过获取运行程序的命令加上管道命令 ps -e | grep WeChat 筛选出WeChat的文件路径 并做记录稍后会用到

    我这里得到的路径是 /var/containers/Bundle/Application/D7DA798A-006B-4B9F-AD53-EDF4D52A1BAE/WeChat.app/WeChat(需要自己去获取)

    5.查找到WeChat的Documents路径,输入cycript -p WeChat,进入cycript命令状态

     

    6.输入NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)[0],获得Documents路径 并做记录稍后会用到.(需要微信在运行中,ctrl + d cycript结束命令状态

    这里得到的路径是 /var/mobile/Containers/Data/Application/B3DFAF56-E8EE-4CAD-A56B-884C21C43049/Documents(需要自己去获取)

     

    7.将dumpdecrypted拷贝到WeChat的Documents目录下,用于砸壳。将命令行切回Mac os,使用scp命令将文件拷贝到WeChat的Documents目录下

    输入scp dumpdecrypted.dylib root@192.168.80.212:****Documents目录

    8.重新通过ssh服务登录手机,开始砸壳

    使用命令 DYLD_INSERT_LIBRARIES=/Documents路径dumpdecrypted.dylib 可执行文件路径
     在我的手机(ios9.3.2)上执行以上命令的时候出现了以下错误:
    

    Killed: 9

    查了一下资料说要在mobile模式下运行以上命令,然后我再次执行,出现如下错误
    Failed opening: Permission denied

    八九个月以前 就是这个错误阻挡我前进的 但是我不甘心 经过反复尝试 使用下面的方法砸壳成功

    cd到Documents目录下 以mobile身份执行命令
    DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib WeChat可执行文件目录。 终于成功了


     

    命令会在当前目录下生成砸壳后的的文件 WeChat.decrypted

     

    9.将WeChat.decrypted拷贝到Mac电脑上

    scp root@192.168.80.212:/var/mobile/Containers/Data/Application/B3DFAF56-E8EE-4CAD-A56B-884C21C43049/Documents/WeChat.decrypted ./ (拷贝到当前目录)

     

    检查砸壳是否成功 otool -l WeChat.decrypted | grep -B 2 crypt 。 cryptid 0表示成功 cryptid 1表示未成功 我的手机是5s,arm64中的cryptid是0 代表砸壳成功

    10.将WeChat.app拷贝出来待使用

     

     这里拷贝的时候要使用  scp -r 
    

    scp -r root@192.168.80.212:/var/containers/Bundle/Application/D7DA798A-006B-4B9F-AD53-EDF4D52A1BAE/WeChat.app ./

    二、注入

    一.安装iOSOpenDev

    http://iosopendev.com/download/

    xcode8及以上直接安装会出错 解决办法:
    如果你们也遇到类似的问题,可以尝试下载iOSOpenDev_Patches,然后按照如下步骤:

    1、

    把Specifications1文件夹重命名为Specifications放到/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/

    2、

    把Specifications2文件夹重命名为Specifications放到/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/

    3、

    把usr3重命名为usr放到/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/

    4、

    安装iOSOpenDev

    二、生成dylib文件

     

     新建项目的时候选择Cocoa Touch Library,项目名为 autoGetRedEnv
    

     

    从github中下载autoGetRedEnv工程源码中的CaptainHook.h和autoGetRedEnv.mm拷贝源码,复制到工程中对应文件中,完成后进行编译,即可得到libautoGetRedEnv.dylib文件。.mm文件里面抢红包的方法需要做修改,因为抢红包的方法已经改变。 不再是hook微信的AsyncOnAddMsg: MsgWrap:方法 然后调用打开红包的的方法 那么简单

    新的自动获取红包的方法:

    hook微信的AsyncOnAddMsg: MsgWrap: ,在这个方法中调用接收红包的方法 ReceiverQueryRedEnvelopesRequest

     

    
    CHMethod(2, void, CMessageMgr, AsyncOnAddMsg, id, arg1, MsgWrap, id, arg2) {
        CHSuper(2, CMessageMgr, AsyncOnAddMsg, arg1, MsgWrap, arg2);
        
        NSUInteger m_uiMessageType = [arg2 m_uiMessageType];
        
        id m_nsFromUsr = [arg2 m_nsFromUsr];
        id m_nsContent = [arg2 m_nsContent];
        
        switch(m_uiMessageType) {
                
            case 49: {
                id logicMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("WCRedEnvelopesLogicMgr")];
                id contactManager =[[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("CContactMgr")];
                id selfContact = [contactManager getSelfContact];
                id m_nsUsrName = [selfContact m_nsUsrName];
                
                if ([m_nsFromUsr isEqualToString:m_nsUsrName]) {//不抢自己的红包
                    return;
                }
                
                if ([m_nsContent rangeOfString:@"wxpay://"].location != NSNotFound) {
                    if (!kZTConfig.isAutoGrapEnv) {
                        return;
                    }
                    
                    NSString *nativeUrl = m_nsContent;
                    NSRange rangeStart = [m_nsContent rangeOfString:@"wxpay://c2cbizmessagehandler/hongbao"];
                    if (rangeStart.location != NSNotFound) {
                        NSUInteger locationStart = rangeStart.location;
                        nativeUrl = [nativeUrl substringFromIndex:locationStart];
                    }
                    
                    NSRange rangeEnd = [nativeUrl rangeOfString:@"]]"];
                    if (rangeEnd.location != NSNotFound) {
                        NSUInteger locationEnd = rangeEnd.location;
                        nativeUrl = [nativeUrl substringToIndex:locationEnd];
                    }
                    
                    NSString *naUrl = [nativeUrl substringFromIndex:[@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?" length]];
                    
                    NSArray *parameterPairs =[naUrl componentsSeparatedByString:@"&"];
                    
                    NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithCapacity:[parameterPairs count]];
                    for (NSString *currentPair in parameterPairs) {
                        NSRange range = [currentPair rangeOfString:@"="];
                        if(range.location == NSNotFound)
                            continue;
                        NSString *key = [currentPair substringToIndex:range.location];
                        NSString *value =[currentPair substringFromIndex:range.location + 1];
                        [parameters SafetySetObject:value forKey:key];
                    }
                    
                    //红包参数...
       
                    NSLog(@"dictParam=%@", dictParam);
                    ((void (*)(id, SEL, NSMutableDictionary*))objc_msgSend)(logicMgr, @selector(ReceiverQueryRedEnvelopesRequest:), dictParam);
                    
                    return;
                }
                
                break;
            }
            default:
                break;
        }
    }
    

    再hook OnWCToHongbaoCommonResponse 方法,在这个方法中再去调用 打开红包的方法 OpenRedEnvelopesRequest

     

    CHDeclareClass(WCRedEnvelopesLogicMgr);
    
    CHOptimizedMethod2(self, void, WCRedEnvelopesLogicMgr, OnWCToHongbaoCommonResponse, id, arg1, Request, id, arg2) {
        
        CHSuper2(WCRedEnvelopesLogicMgr, OnWCToHongbaoCommonResponse, arg1, Request, arg2);
        
        if ([ZTUserDefaults boolForKey:kZTAutoGrapEnvKey]) {
            if ([NSStringFromClass([arg1 class]) isEqualToString:@"HongBaoRes"]) {
                NSData *data = [[arg1 retText] buffer];
                
                if (nil != data && 0 < [data length]) {
                    NSError* error = nil;
                    id jsonObj = [NSJSONSerialization JSONObjectWithData:data
                                                                 options:NSJSONReadingAllowFragments
                                                                   error:&error];
                    if (nil != error) {
                        NSLog(@"error %@", [error localizedDescription]);
                    }
                    else if (nil != jsonObj)
                    {
                        if ([NSJSONSerialization isValidJSONObject:jsonObj]) {
                            if ([jsonObj isKindOfClass:[NSDictionary class]]) {
                                id idTemp = jsonObj[@"timingIdentifier"];
                                if (idTemp) {
                                    NSMutableDictionary *params = [[ZTUserDefaults objectForKey:ZTParamKey] mutableCopy];
                                    [ZTUserDefaults setObject:[NSMutableDictionary dictionary] forKey:ZTParamKey];
                                    [params SafetySetObject:idTemp forKey:@"timingIdentifier"]; // "timingIdentifier"字段
                                    
                                    // 防止重复请求
                                    if (params.allKeys.count < 2) {
                                        return;
                                    }
                                    
                                    id logicMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("WCRedEnvelopesLogicMgr")];
                                    //延迟1秒抢红包
                                    dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC);
                                    dispatch_after(delayTime, dispatch_get_main_queue(), ^(void) {
                                        ((void (*)(id, SEL, NSMutableDictionary*))objc_msgSend)(logicMgr, @selector(OpenRedEnvelopesRequest:), params);
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    

    为了减少被封号的几率 在前红包的时候 不要去抢自己的红包 不要重复去抢红包 必要的可以加上抢红包的延时

    修改微信步数

     

    #pragma mark - WCDeviceStepObjectCHDeclareClass(WCDeviceStepObject)////修改步数CHOptimizedMethod(0, self, unsigned long, WCDeviceStepObject, m7StepCount) {    return 6666;
    }
    
    CHOptimizedMethod(0, self, unsigned long, WCDeviceStepObject, hkStepCount) {    return 6666;
    
    }
    
    __attribute__((constructor)) static void entry()
    {
        // 微信步数    CHLoadLateClass(WCDeviceStepObject);    CHHook(0, WCDeviceStepObject, m7StepCount);    CHHook(0, WCDeviceStepObject, hkStepCount);   
    }
    
    

    防止消息撤回 撤回消息的时候会调用onRevokeMsg 方法,我们hook这个方法 让它什么都不做

     

    
    CHDeclareClass(CMessageMgr);
    CHOptimizedMethod(1, self, void, CMessageMgr, onRevokeMsg, id, value1) {   
    }
    
    __attribute__((constructor)) static void entry(){    //加载CMessageMgr类
        CHLoadLateClass(CMessageMgr);
        // 消息防撤回
        CHHook(1, CMessageMgr, onRevokeMsg);  
    }
    
    

    我们还可以在设置界面中加入控制开关哦 微信中的设置页面是 NewSettingViewController 我们可以在里面添加两个cell来控制 抢红包的开关 以及设置步数。在设置页面中的cell类是MMTableViewSectionInfo 通过hopper可以看到里面有很多创建cell的方法 这里我们会用到下面两个方法。对于步数的保存以及红包开关的控制,使用一个单利类来保存

     

    
    //添加抢红包以及修改步数选择
    CHDeclareClass(NewSettingViewController)
    
    CHOptimizedMethod0(self, void, NewSettingViewController, reloadTableData) {
        CHSuper0(NewSettingViewController, reloadTableData);
        MMTableViewInfo *tableInfo = [self valueForKey:@"m_tableViewInfo"];
        MMTableViewSectionInfo *sectionInfo = [objc_getClass("MMTableViewSectionInfo") sectionInfoDefaut];
        
        MMTableViewCellInfo *autoGrapRedEnvCellInfo = [objc_getClass("MMTableViewCellInfo")
                                                       switchCellForSel:@selector(autoGrabEnvSwitchAction:)
                                                       target:kZTConfig
                                                       
                                                       title:@"自动抢红包"
                                                       
                                                       on:kZTConfig.isAutoGrapEnv];
        [sectionInfo addCell:autoGrapRedEnvCellInfo];
        
        MMTableViewCellInfo *setpCell = [objc_getClass("MMTableViewCellInfo") editorCellForSel:@selector(handleStepCount:)
                                                                                        target:kZTConfig
                                                                                           tip:@"请输入步数"
                                                                                         focus:NO
                                                                                          text:[NSString stringWithFormat:@"%ld", (long)kZTConfig.stepCount]];
        [sectionInfo addCell:setpCell];
        
        [tableInfo insertSection:sectionInfo At:0];
        MMTableView *tableView = [tableInfo getTableView];
        [tableView reloadData];
    }
    
    

    编译得到libautoGetRedEnv.dylib文件

    三、注入dylib

     

     1.将WeChat.decrypted  改名为WeChat,然后通过**yoyolib**向**WeChat**注入**dylib**
    

    ****./yololib 目标可执行文件 需注入的dylib。注入成功如下所示****

    059F5C48-C8A2-4706-A373-27A023CFCE3D.png

    三、重新签名打包

    1.  

    新建Entitlements.plist

     

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    <key>application-identifier</key>
    <string>证书id.com.xx.xx</string>
    <key>aps-environment</key>
    <string>production</string>
    <key>com.apple.developer.team-identifier</key>
    <string>证书id</string>
    <key>get-task-allow</key>
    <false/>
    </dict>
    </plist>
    

    当中所需要的信息 可以从以往的项目的app中得到
    /opt/iOSOpenDev/bin/ldid -e ./Demo.app/Demo

    2.下载配置文件

    从开发者网站下载一个与上面plist相匹配的配置文件,并命名为embedded.mobileprovision

    3.将四个文件,放入到之前备份好的WeChat.app文件夹中:
    1.embedded.mobileprovision
    2.libautoGetRedEnv.dylib
    3.注入libautoGetRedEnv.dylib后的WeChat文件
    4.Entitlements.plist

    这里需要注意 .plist文件 embedded.mobileprovision 以及打包需要的证书 这三个需要对应 不然打包会失败,无论尝试多少次 都会失败

    4.重新给微信程序签名
    codesign -f -s 证书名字 目标文件
    具体操作步骤

     

    codesign -f -s "iPhone Developer:xxxxx" WeChat.app/libautoGetRedEnv.dylib
    codesign -f -s "iPhone Developer:xxxxx" WeChat.app/Watch/WeChatWatchNative.app/PlugIns/WeChatWatchNativeExtension.appex
    codesign -f -s "iPhone Developer:xxxxx" WeChat.app/Watch/WeChatWatchNative.app
    codesign -f -s "iPhone Developer:xxxxx" WeChat.app/PlugIns/WeChatShareExtensionNew.appex
    codesign -f -s "iPhone Developer:xxxxx" --entitlements Entitlements.plist WeChat.app
    

    打包成ipa
    给微信重新签名后,我们就可以用xcrun来生成ipa了,具体实现如下:
    xcrun -sdk iphoneos PackageApplication -v WeChat.app -o ~/WeChat.ipa
    如果不想手动那样麻烦的操作的话 还可以使用签名的工具进行签名 我使用的是ios app signer

     

    81E5DCF6-8FCC-4B9E-BDDA-8BA0EF4C8DEB.png

    打包出WeChat.ipa 然后使用itools安装到手机上

     

    展开全文
  • 微信撤回插件,一键安装,仅MAC可用 安装方法:将Install.sh文件拖到终端,然后回车输入密码即可。 卸载方法:将Uninstall.sh文件拖到终端,然后回车。
  • 前言 上次完成了 macOS 版微信小助手,现在终于有(xian)时(de)间(huang)来说说 ...github地址: iOS微信小助手(防撤回、修改微信运动、群管理、好友请求管理) 工具 以下工具的详细使用方法可以查看iOS应用逆向工...

    前言

    上次完成了 macOS 版微信小助手,现在终于有(xian)时(de)间(huang)来说说 iOS 逆向了。本篇主要实现在微信上自动添加好友(即自动验证新的朋友申请),从而熟悉 iOS 逆向分析的过程,可能总结的有点粗糙,如果有不懂的地方欢迎探讨。

    github地址: iOS 版微信小助手(防撤回、修改微信运动、群管理、好友请求管理)

    工具

    以下工具的详细使用方法可以查看iOS应用逆向工程 第2版 第二部分 工具篇。

    macbook 软件

    • theos

      制作 Tweak 的工具

    • hopper disassembler

      用于静态分析

    • usbmuxd

      端口转发,可以让我们通过 usb 连接手机进行 ssh、lldb 调试等。主要使用python-client目录下的文件

    • class-dump

    dump 目标对象的 class 信息的工具.

    • lldb

    调试神器,用过的都说好。默认自带,在/Applications/Xcode.app/Contents/Developer/usr/bin/lldb 中。

    越狱 iPhone 软件

    以下软件在 Cydia 中即可下载(debugserver 除外)

    • OpenSSH

    实现在越狱手机上远程进行 ssh 服务,通过 ssh,即可以通过终端连接 iPhone 进行控制。

    **iOS 工具大部分都需要在 ssh 环境中使用**
    复制代码
    • Cycript

    脚本语言,用于 hook 正在运行的进程,并实时注入代码。

    • ondeviceconsole

    用于在 Terminal 中查看手机的 log

    • debugserver

    用于连接手机进行 lldb 调试的工具。用 Xcode 在手机上进行 app 调试即可在iPhone目录的 /Developer/usr/bin/ 中生成。

    使用 debugserver 需要先进行处理。因为缺少task_for_pid权限,所以调试不了其他的 app。 先通过 ssh 拷贝 debugserver

    scp root@iOSIP:/Developer/usr/bin/debugserver ~/debugserver // iOSIP 为手机的ip地址
    复制代码

    下载 ldident,进行

    ldid - Sent.xml debugserver
    复制代码

    在使用 ssh 拷贝至手机,完成。

    分析

    思路:想要实现自动验证好友请求,则要拿到获取好友请求的方法,以及通过好友请求的方法。hook 获取好友请求的方法,在接收到好友请求的时候,执行添加好友的方法。 而这些主要逻辑在“新的朋友”界面。

    定位好友请求的方法

    UI 分析

    我们知道,根据 MVC 模式,一般的方法实现都是在 ViewController 中的,所以想要拿到好友请求的方法,要先拿到当前界面的控制器。而这时候可以通过 UI 分析获得。

    先打开新的朋友界面。

    使用 usbmuxd 进行端口的转发(若手机不卡,可以跳过这步直接使用 ssh 进行 wifi 远程连接)

    python tcprelay.py -t 22:2222
    复制代码

    再使用 ssh 连接至手机

    ssh root@localhost -p 2222
    // ssh root@192.168.31.94 如果是wifi连接,请查看当前手机的wifi地址。
    复制代码

    查看微信的进程信息

     ps -e |grep WeChat
    复制代码

    Cycript 注入

    cycript -p WeChat // 或者是当前微信的进程号,如下所示
    复制代码

    启动Cycript后,使用以下命令查看当前 UI 布局

    UIApp.keyWindow.recursiveDescription().toString()
    复制代码

    因为知道当前的视图有 tableView,所以找到 tableView 的对象。从上图可以看到该对象的地址为0x18c4be00。 在使用 nextResponder()根据响应者往上找当前的 ViewController。

    找到当前的控制器,为SayHelloViewController

    Log 分析

    使用class-dump dump 出微信的 class 信息。

    class-dump -S -s -H demo.app -o ~/Document/headers/
    // dump 微信app的头文件保存在 ~/Document/headers/ 目录中
    复制代码

    再使用 theos 的 logify 工具,该工具用来注入NSLog来打印方法的入参和出参。(就是在 hook 某个类的所有的方法,并在里面加 log,并导出xm文件)

    logify.pl  ~/Document/headers/SayHelloViewController.h > ~/Desktop/Tweak.xm
    复制代码

    **注意:**一般该Tweak.xm仍然无法执行,需要进行修改:

    • 去掉 .cxx_destruct 方法
    • 将 HBLogDebug 改为 NSLog
    • 去掉所有的 delegate
    • 将所有的参数对象类型改成 id
    • 去掉所有的 weak

    再使用 theos 配置相关文件(具体查看iOS逆向-微信helloWorld), 然后进行make package install 安装至手机。

    重新启动微信进入新的朋友界面。

    在ssh中使用ondeviceconsole打印手机的 log。

    这时用另一个微信号添加自己好友。触发好友请求的方法。可以看到以下的 log

    说明有好友添加请求的时候,会调用 -[SayHelloViewController OnSayHelloDataChange]

    动态分析

    既然已经知道了有好友请求的时候会调用OnSayHelloDataChange,那么我们可以在当前方法中进行处理,然而有个弊端,就是当有好友请求时,微信不在新的朋友界面时,是不会调用该方法的。所以我们应该在更底层的类中(假设为消息管理类)中进行处理,而怎么找到消息管理类呢?按照一般的逻辑,消息管理类中一定有方法触发了OnSayHelloDataChange,这时候就要用到 lldb + hopper 神器来找到相应的消息管理类与其处理方法了。

    lldb 进行手机端调试,hopper 进行静态分析,分析OnSayHelloDataChange方法的信息,找出突破口。

    先用 hopper 打开微信的二进制文件。搜索SayHelloViewController OnSayHelloDataChange方法。 可以看到当前方法在微信中的偏移地址0x14a4824。

    启动debugserver 配合lldb调试

    先打开微信,并使用 usbmuxd 转换端口

    python tcprelay.py -t 1234:1234
    复制代码

    再 ssh 到手机上,开启 debugserver 。

    debugserver *:1234 -a "WeChat"
    复制代码

    使用新的 Terminal 窗口,打开 lldb,连接1234端口,并查看当前微信的进程信息(一般会在所有进程的首行)。 此时会卡住一段时间。

    // 打开lldb
    /Applications/Xcode.app/Contents/Developer/usr/bin/lldb
    // 连接端口调试
    (lldb) process connect connect://localhost:1234
    // 打印所有进程
    (lldb) image list -o -f
    复制代码

    找到微信在当前手机上的进程内存基地址为0x000b2000(这个值不是定值)

    通过以上可以找到 [SayHelloViewController OnSayHelloDataChange]方法在手机上的内存地址。即

    内存地址 = 进程内存基地址 + 方法偏移地址
    复制代码

    使用br打断点查看

     br s -a "0x000b2000 + 0x14a4824"
    复制代码

    接着输入c继续运行,重新使用另一微信账号添加好友,会触发该断点。

    使用bt查看调用栈信息,即哪些方法调用了当前的方法,找到方法的上游。(异步调用的话没办法查看)

    第一个表示当前的方法,可以看到在调用此方法前,该进程总共调用了3个方法。 分别计算出这三个方法在微信中的偏移量。

    将这三个地址在 hopper 中查看(按快捷键g,输入地址),找到了对应的方法为

    // 调用的顺序为从下到上
    [SayHelloViewController OnSayHelloDataChange]
    [SayHelloDataLogic onFriendAssistAddMsg:]
    [FriendAsistSessionMgr OnAddMsgForSpecialSession:MsgList:]
    [CMessageMgr MainThreadNotifyToExt:]
    复制代码

    从以上方法名可以猜测

    [FriendAsistSessionMgr OnAddMsgForSpecialSession:MsgList:]
    复制代码

    是用来接收添加好友消息的函数处理,其中MsgList:后面的参数可能为消息的数组,为了证明我们可以在该方法中打个断点查看下。 使用命令register read读取寄存器地址,并使用po打印该对象。

    看出r3寄存器确实是个数组,同时也得到了消息的对象为CMessageWrap 证明我们是对的。

    ps: 解释下为什么要看r3,因为在 armv7 中,一个方法的调用,一般寄存器都是这么存储的:前四个参数放在r0~r3,剩下的存放在堆栈中。查看堆栈的话使用x/10 $sp 查看前10个堆栈里的对象地址。

    然而FriendAsistSessionMgr这个类可能在新的好友界面进行一些初始化,且放在SayHelloViewController中,而我们想要的是不管在哪个控制器里都可以 hook 住上面的消息数组对象。因此我们往上找,[CMessageMgr MainThreadNotifyToExt:],然而里面并没有我们需要的信息。而根据类名我们推测CMessageMgr是用来管理消息的。有可能是在异步执行了消息数组的获取。

    因此,重复以上步骤,使用 logify 对CMessageMgr进行 Log 分析。最终锁定了 CMessageMgr MessageReturn:MessageInfo:Event:

    定位通过好友请求的方法

    动态分析

    既然找到了接收好友请求的方法,那么是时候找通过好友请求的方法了。 我们知道,通过好友请求的方法,是在新的朋友界面,点击接受的时候触发的。(可以通过 Log 分析,然而这里还有另一个比较快速的方法)

    Cycript 定位

    先通过 Cycript 打印出所有的 UI 层级。 找到接受按钮的对象,(有个技巧,我们知道当前按钮是在某个 cell 下面的,所以定位这个)。

    再通过cycript将该对象的 hidden 动态修改为 1,看是否隐藏。

    #0x186922f0.hidden = 1
    复制代码

    发现按钮不见了,证明我们是对的。这时候需要找到点击按钮的事件。

    而我们知道 UIButton 是继承 UIControl 的,在 Cycript 中, 可以通过allTargetsallControlEvents查看当前UIControl所有的targets与events,再使用actionsForTarget:forControlEvent:从而找到触发的方法。

    看出所触发的方法为[ContactsItemView onRightBtnAction]

    静态分析

    既然拿到了方法名,那我们怎么看他具体的实现呢? 接下来就是大名鼎鼎的 hopper 登场了。 用 hopper 打开微信的二进制文件,并进行汇编与伪代码的转换。 ~~由于汇编读起来比较晦涩,所以还是进行伪代码的转换,这样效率比较快。~~点击该按钮进行转换

    可以得到伪代码

    上图我们看到了

    r10 = self;
    r5 = r10 + *0x33befe8;
    r4 = objc_loadWeakRetained(r5);
    r8 = @selector(onContactsItemViewRightButtonClick:);
    r11 = [r4 respondsToSelector:r8];
    复制代码

    可以得出,r11 = [r5 onContactsItemViewRightButtonClick:btn],而 r5 我们判断为 self 的代理,这个我们也可以通过在之前用 class-dump 的头文件里面搜索onContactsItemViewRightButtonClick,会发现在ContactsItemViewDelegate中。 也就是[ContactsItemView onRightBtnAction]内部调用了[self.delegate onContactsItemViewRightButtonClick:]. 而 ContactsItemViewdelegateSayHelloViewController

    再用 hopper 定位onContactsItemViewRightButtonClick

    看到这里估计会很懵逼不知道从何下手。这时候只要加以推测就可以了。 上图中进行了两个if判断,第一个为

    r10 = @selector(class);
    r2 = loc_1c099bc(@class(CPushContact), r10);
    r1 = @selector(isKindOfClass:);
    r5 = loc_1c099bc(r4, r1, r2);
    loc_1c099d4(r4);
    if ((r5 & 0xff) != 0x0) {
    复制代码

    可以得出其实是执行了 if([r4 isKindOfClass:[CPushContact class]]); 而r4是什么呢?可以肯定是CPushContact对象,不然下面的代码都不执行了。我们可以根据动态分析,通过 lldb 打断点,并查看r3寄存器的对象类型,可以看到该对象为CPushContact对象。因此r4就是CPushContact对象,根据字面意思可以得到就是联系人对象。

    继续看下面的代码,可以看到也进行了一次判断if (((loc_1c099bc(r6, @selector(m_bSuspiciousUser)) & 0xff) != 0x0) && ((loc_1c099bc(r6, @selector(isMMContact)) & 0xff) == 0x0)),看到了MMUIAlertView。推测是弹窗的 view ,推测如果是可疑的用户或者当前申请的好友已经是自己的好友,那就进行弹窗。而另一部分为verifyContactWithOpCode:opcode:,推测该部分为添加好友的方法。 可以通过 Log 分析或者通过 lldb 打断点,会看到都会进入该方法。且参数分别为CPushContact对象与 3。 接着继续分析verifyContactWithOpCode:opcode:方法。主要的部分如下所示。

    通过分析,我们可以得到,确认好友申请,显示构造了CContactVerifyLogic对象。再构造了一个CVerifyContactWrap对象,并设置了相关属性,比如m_nsUsrName m_uiScene m_nsTicket.然后通过添加到数组中,通过CContactVerifyLogic对象的startWithVerifyContactWrap:opCode:parentView:fromChatRoom:方法发送。 代码如下:

    CContactVerifyLogic *verifyLogic = [[CContactVerifyLogic alloc] init];
    CVerifyContactWrap *wrap = [[CVerifyContactWrap alloc] init];
    [wrap setM_nsUsrName:contact.m_nsEncodeUserName];
    [wrap setM_uiScene:contact.m_uiFriendScene];
    [wrap setM_nsTicket:contact.m_nsTicket];
    [wrap setM_nsChatRoomUserName:contact.m_nsChatRoomUserName];
    wrap.m_oVerifyContact = contact;
    
    AutoSetRemarkMgr *mgr = [[MMServiceCenter defaultCenter] getService:[AutoSetRemarkMgr class]];
    id attr = [mgr GetStrangerAttribute:contact AttributeName:1001];
    
    if([attr boolValue]) {
        [wrap setM_uiWCFlag:(wrap.m_uiWCFlag | 1)];
    }
    [verifyLogic startWithVerifyContactWrap:[NSArray arrayWithObject:wrap] opCode:3 parentView:[UIView new] fromChatRoom:NO];
    复制代码

    这样我们就得到了 获取好友请求的方法与添加好友的方法。 而这里还有一个问题,就是添加好友的对象是CPushContact,而获得好友请求的对象的CMessageWrap。这里需要进行转换,而转换的方法也在SayHelloViewController中,可以重复上面的分析方法获得。


    编写Tweak

    通过以上的分析,将代码合并起来

    %hook CMessageMgr
    - (void)MessageReturn:(unsigned int)arg1 MessageInfo:(NSDictionary *)info Event:(unsigned int)arg3 {
        %orig;
        if (arg1 == 332) {   // 收到添加好友消息
            NSString *keyStr = [info objectForKey:@"5"];
            if ([keyStr isEqualToString:@"fmessage"]) {
                NSArray *wrapArray = [info objectForKey:@"27"];
                [self addAutoVerifyWithArray:wrapArray];
            }
        }
    }
    
    %new
    - (void)addAutoVerifyWithArray:(NSArray *)ary {
        [ary enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                CPushContact *contact = [%c(SayHelloDataLogic) getContactFrom:obj];
                if (![contact isMyContact] && [contact.m_nsDes isEqualToString:autoVerifyKeyword]) {
                    CContactVerifyLogic *verifyLogic = [[%c(CContactVerifyLogic) alloc] init];
                    CVerifyContactWrap *wrap = [[%c(CVerifyContactWrap) alloc] init];
                    [wrap setM_nsUsrName:contact.m_nsEncodeUserName];
                    [wrap setM_uiScene:contact.m_uiFriendScene];
                    [wrap setM_nsTicket:contact.m_nsTicket];
                    [wrap setM_nsChatRoomUserName:contact.m_nsChatRoomUserName];
                    wrap.m_oVerifyContact = contact;
    
                    AutoSetRemarkMgr *mgr = [[%c(MMServiceCenter) defaultCenter] getService:%c(AutoSetRemarkMgr)];
                    id attr = [mgr GetStrangerAttribute:contact AttributeName:1001];
    
                    if([attr boolValue]) {
                        [wrap setM_uiWCFlag:(wrap.m_uiWCFlag | 1)];
                    }
                    [verifyLogic startWithVerifyContactWrap:[NSArray arrayWithObject:wrap] opCode:3 parentView:[UIView new] fromChatRoom:NO];
                }
        }];
    }
    复制代码

    总结

    本文为本人根据iOS应用逆向工程 第2版的内容进行分析,由于整个逆向流程有点繁琐,有时候也不是只要分析一次就可以成功的,需要反反复复的进行UI分析、Log分析、lldb 分析。

    参考

    iOS应用逆向工程 第2版
    移动App入侵与逆向破解技术-iOS篇

    转载于:https://juejin.im/post/5a66ca896fb9a01ca8721c48

    展开全文
  • 说明: 相信喜欢逆向工程的小伙伴已经对微信自动抢红包插件有所耳闻了,或者可以说,已经被广泛的传播了,但笔者发现,其实只有两篇是原创的,其余均为疯狂转载.看了下网上对于微信的"喜爱"目前只有抢红包这块,所以为大家...

    说明: 相信喜欢逆向工程的小伙伴已经对微信自动抢红包插件有所耳闻了,或者可以说,已经被广泛的传播了,但笔者发现,其实只有两篇是原创的,其余均为疯狂转载.看了下网上对于微信的"喜爱"目前只有抢红包这块,所以为大家带来另一个实用性技能---修改微信运动参数,妈妈在也不用担心我把手机绑在狗腿上了!

    硬件工具:最好是有一台越狱后的iPhone手机,没有也没有关系,后续补充非越狱环境开发,本文针对于Theos下Tweak编码<本文使用的测试机iPhone 5c和一台没用上的iPhone 5s, ps:别问为什么没用上还提, 因为写到这里,控制不住装逼的念头,好了不开玩笑了!>

    软件工具:已经有高(hao)人为我们写好了开发工具的配置和安装,只是一个软件的安装所以本人没必要踩在前辈的肩膀上继续深造, 教程地址, 稍等,我们还需要安装一个查看微信头文件的宝物:class-dump, 当然了,使用它的前提是需要进行砸壳后的app才可以正确导出头文件,至于怎么砸壳,谷歌肯定能帮到你,目前能谷歌到的我们不做深究,只谈目前没有公开的

                               硬件软件已经准备就绪

    思考功能怎么实现:

    在我们的iOS系统本身, 有一个运动与健康,这里记录了我们每天的步数行为等等, 那么微信运动排行榜在对好友们的步数进行排榜的时候肯定需要去取数据, 那么从哪取呢?毋庸置疑,去运动与健康取,如果我们能在微信取数据的时候进行动态劫持,伪造一个假数据传给微信,那么是不是就大功告成了呢? 答案: if(YES){NSLog(@"是的");}

    观察微信头文件

    使用 class-dump -H WeChat.app -o WeChatHead命令导出微信头文件

    真的是巨多无比,几千个.h

    我们发现在WCDeviceStepObject这个类里面有几个很显眼的属性m7StepCount,hkStepCount 等. 如下:

    关键字"stepCount"的中文是"步数",那么这个是不是我们要劫持并修改的参数呢? 多说无益,试试就知道了.

    创建一个Tweak工程, 如下:

    编写Tweak.xm文件, 如下:

    上图我们返回"98800" 步数以做测试,

    展开全文
  • ios 微信逆向部分

    2018-09-22 14:24:09
    一、砸壳方法(转载...Cycript(Cydia)(在越狱手机的越狱市场下载,安装) adv-cmds(Cydia)(在越狱手机的越狱市场下载,安装) OpenSSH(Cydia) (在越狱手机的越狱市场下载,安装) 具体实现步骤 首先在APP...

    一、砸壳方法(转载注明出处)

    ###准备工作:

    1. 越狱的手机(必须的)
    2. dumpdecrypted (砸壳使用)
    3. class-dump (导出砸壳后的二进制包的头文件)
    4. Cycript(Cydia)(在越狱手机的越狱市场下载,安装)
    5. adv-cmds(Cydia)(在越狱手机的越狱市场下载,安装)
    6. OpenSSH(Cydia) (在越狱手机的越狱市场下载,安装)

    ###具体实现步骤

    首先在APPStore中下载正版的应用

    以QQ为例

    1. 首先确保手机连接和电脑连接的是同一个网段

    2. 用ssh命令连接上手机,密码默认是 alpine

       ssh root@10.2.200.186
    
    1. 关闭所有的后台APP,仅保持QQ后台活跃
    ps -e | grep QQ
    

    (如果这里是其他APP,不清楚具体名字,那么执行这个命令,我这里是知道我破壳的应用叫QQ,所以,直接执行 ps -e | grep QQ)

    ps -e
    

    屏幕快照 2018-07-06 上午11.39.27

    1. 使用cycript命令,找到目标app的Document路径,使用如下命令
    cycript -p QQ
    

    屏幕快照 2018-07-06 上午11.42.59

    键入一下命令

    [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]
    

    拿到地址并且记录下来,后面要用到

    屏幕快照 2018-07-06 上午11.45.50

    control + z退出cy模式

    1. 这里一定要注意,将我们下载好的 dumpdecrypted 编译一下,生成动态库dylib,编译方法是,进入到我们下载好的dumpdecypted目录下

    直接执行make命令

    屏幕快照 2018-07-06 上午11.53.16

    这样会编译一遍dumpdecrypted,生成dylib

    1. 将生成的将dumpdecrypted.dylib拷贝到Documents目录下,执行该命令
    sudo scp dumpdecrypted.dylib root@10.2.200.186:/var/mobile/Containers/Data/Application/531B07B4-3048-4EEF-BB76-25F6F83D1EEC/Documents/
    

    屏幕快照 2018-07-06 上午11.58.25

    1. 开始砸壳,使用以下命令,会在当前目录下生成QQ.decrypted砸壳后的文件。
    DYLD_INSERT_LIBRARIES=/var/mobile/Containers/Data/Application/531B07B4-3048-4EEF-BB76-25F6F83D1EEC/Documents/dumpdecrypted.dylib     /var/mobile/Containers/Bundle/Application/20E39925-5231-4BE3-B483-9D6481BCC715/QQ.app/QQ
    

    成功后有如下结果

    屏幕快照 2018-07-06 下午12.16.06

    1. 将砸壳后的QQ.decrypted文件拷贝到电脑上。
    sudo cp root@10.2.200.186 /var/root/QQ.decrypted
    

    屏幕快照 2018-07-06 下午12.34.17

    (我在这里是拷贝到当前文件夹下,所以后面没有带路径),如拷贝到指定文件夹,后面需要带路径

    你会看到这个文件屏幕快照 2018-07-06 下午12.37.33

    到此,砸壳完成,接下来,操作一下,如何提取头文件

    class-dump最新安装方法

    当Mac升级了OSX 10.11后,配置class-dump的时候,会发现逆向书上推荐的class-dump存放目录**/usr/bin**,class-dump存放不进去,尝试过用sudo 还是不被允许。

    1. 首先打开Terminal,输入mkdir ~/bin,在当前用户根目录下创建一个bin目录

    2. 把下载下来的 dmg 打开,复制文件里面的class-dump到创建的bin目录下。赋予其可执行权限

     chmod +x ~/bin/class-dump
    
    1. 打开bash_profile文件配置环境变量:
    vim ~/.bash_profile
    
    1. 按下 i 键进入编辑状态,在最下方加一行
     export PATH=$HOME/bin/:$PATH
    
    1. 按下esc键,再按shift+: 输入 wq进行保存退出编辑

    6.在Terminal中执行

    source ~/.bash_profile
    

    具体可参见

    https://www.jianshu.com/p/025fa775f3a6

    执行该命令

    class-dump -H QQ.decrypted  -o output/
    

    紧接着,你就会发现,

    屏幕快照 2018-07-06 下午12.50.20

    二、重签名 (以WeChat为例,当然,上面用的是QQ的,原理都一样)

    准备工作:砸壳完成的二进制文件、IPA包、脚本文件、证书、描述文件

    1.解压ipa包
    unzip WeChat.ipa -d WeChat_unzip
    
    2.替换二进制文件
    • 微信砸壳会得到一个WeChat.decrypted文件, 重命名为WeChat,在终端,输入 chmod 777 ,然后把 WeChat拖到终端上按回车 修改下权限。
    sudo chmod 777 WeChat
    
    • 替换砸壳了的WeChat二进制文件

    用WeChat替换Payload/WeChat包内容里的二进制文件

    3.修改Bundle identifier

    ​ 找到WeChat_unzip/Payload/WeChat包内容的info.plist 文件,修改 Bundle identifier,需要与使用的额证书和描述文件相一致

    4.重签名

    ​ 打开终端,cd 进入 文件所在目录,运行

    ​    sh ios_resign_from_app_to_ipa WeChat_unzip "iPhone Distribution: Beijing 1000 Oaks Hu Lian Technology Development (UECH3VPJ68)" embedded.mobileprovision WeChat_resig.ipa
    
    5.签名成功,得到ipa文件

    WX20180706-123822@2x

    三、防撤回+步数统计

    1.获取砸壳后的头文件,如图

    QQ20180706-005234@2x

    2.用编辑器打开搜索关键词message、revoke等,最终锁定CMessageMgr.h文件

    QQ20180706-010232@2x

    经过尝试找到如下方法

    - (void)onRevokeMsg:(id)arg1;
    - (void)DelMsg:(id)arg1 MsgList:(id)arg2 DelAll:(_Bool)arg3;
    

    onRevokeMsg为收到一条撤回通知(此时微信里显示“对方已撤回”)

    DelMsg为删除本地消息,所以我们hook该方法即可换成自己的方法

    ps:注意,只有当收到revoke通知删除本地消失时才替换成自己的方法,其它情况调用父类方法

    微信步数实现步骤

    1.获取步数
    • 通过脱壳后的微信ipa包,获取到工程中的所有头文件,找到其中管理微信运动步数的类为WCDeviceStepObject。
    • 通过几次实验(以及对函数名的猜测)得到了获取步数的函数为m7StepCount。
    • 通过开源的CaptainHook类,利用ObjC的runtime机制,对m7StepCount函数进行method swizzling,也就是用我们自己的实现来替换微信的实现。为了避免改得太假被微信发现,如果修改的不是当天或者改的步数比微信自己计算的还少,就直接调用微信原有的方法。
    2.在设置中加入修改入口

    C61E5B35FDF673D4C6E1D179F95E3498

    • 微信的设置页比较好找,在NewSettingViewController类中。
    • 通过Reveal软件能看到微信设置界面的结构,在MMTableViewSectionInfo中增加一行输入步数的MMTableViewCellInfo,并最后加到MMTableViewInfo中。
    • 重新刷新tableView,就能看到新加的入口了。
    展开全文
  • 点击上方“iOS开发”,选择“置顶公众号”关键时刻,第一时间送达!美国学者埃德加·戴尔(Edgar Dale)1946年提出了“学习金字塔”(Cone of Learni...
  • 微信iOS消息拦截插件教程-Tweak HelloWorld 标签(空格分隔): 越狱开发教程 1、环境准备 准备一台越狱的手机,具体参照上一篇教程 搭建Theos越狱开发环境 2、开发过程 新建一个第三课的目录,新建一个tweak...
  • iOS逆向实战与工具使用(微信添加好友自动确认) 原文链接 源码地址 WeChatPlugin-iOS Mac OS 版微信小助手(远程控制、消息防撤回、自动回复、微信多开) 一、前言 本篇主要实现在微信上自动添加好友,从而熟悉 iOS ...
  • 苏生不惑第145 篇原创文章,将本公众号设为星标,第一时间看最新文章。关于微信之前写过以下文章,有兴趣可以点击查看:那些你可能不知道的微信奇技淫巧那些你可能不知道的网络冷知识奇技淫巧一个...
  • 微信高手必须知道30个技巧    你真的会玩微信吗?那你是最潮的微信玩家吗?虽然现在中老年人使用智能手机、玩微信的越来越多了。  然而,不少老年朋友在手机上花的时间不少,但还是不太会用,不能充分...
  • 强烈推荐一个恢复微信、QQ记录可靠的专业人才给你,他的QQ是10906152 希望能帮到有需要的人 用这个软件可以解决你的问题,北亚苹果手机数据恢复软件-FromByte Recovery for iPhone V1.0 主要针对iPhone...
  • iOS学习视频及资料 即时通讯 直播类 iOS优秀项目开源代码 Native和H5交互 swift学习 ReactiveCocoa学习 3DTouch 折线图 蓝牙 静态库 Runtime运行时 多媒体 图文混排 Github资源大汇总 AutoLayout iOS大全 微信小程序...
  • TimLiu-iOS Swift版本点击这里 Objective-C版本点击这里 欢迎加入QQ群交流: 594119878 更新日期:2018-4-11 About A curated list of iOS objective-C ecosystem. How to Use Simply press command +...
  • 分享一个第三方 UISegmentedControl - iOS - 掘金Github: YUSegment Features 可以显示文字与图片,文字以 NSAttributedString 类的形式展现 支持显示分割线 可以隐藏指示器,或者将指... iOS 可自选切割角的圆角...
  • 关于代码家(干货集中营)共享的所有知识点IOS部分的汇总,后续每周会对其进行更新 iOS [2016年10月12日发布] Cell 弹性效果 [2016年10月12日发布] Xcode 8 快速注释和取消注释插件。 [2016年10月11日发布] 支持下滑...
  • iOS - 收藏集 - 掘金

    2019-04-05 00:34:06
    PPAsyncDrawingKit - 实现了一系列基础 UI 控件的轻量级 ASDK - iOS - 掘金一年 iOS,求职中,上海地区,邮箱:dskcpp@gmail.com PPAsyncDrawingKit ... 33 款驰骋 2017 的 iOS 开源库 - 掘金文/Paweł Białecki译/...
  • 用到的组件iOS学习群:727474737 ios移动开发学习,ios逆向开发教程,iosAR技术教程,iosARKi技术教程,ios开发,iOS安全,iOS逆向分析,越狱插件开发,应用破解/保护,Objective-C/Swift ,反编译 反汇编,加密...
  • 用到的组件1、通过CocoaPods安装项目名称项目信息AFNetworking网络请求组件FMDB本地数据库组件SDWebImage多个缩略图缓存组件UICKeyChainStore存放用户账号密码组件Reachability...iOS 照片浏览控件CTAssetsPicker...
1 2
收藏数 28
精华内容 11
关键字:

越狱ios恢复微信撤回的图片