微信自动摇一摇刷一分钱
除夕打开微信摇一摇抢红包,红包雨还没开始时,会显示如下界面:
底部圆形的logo在不停地跳动,点击一下,居然领到了一分钱:
如果不断摇一摇再点击logo,就可以领到很多一分钱。不过手动操作太麻烦了,所以写了个tweak
插件来自动领取。
插件要做的操作大概如下:
- 在摇一摇界面,插件自动调用摇一摇的方法。
- 进入红包详情界面后,插件自动点击图标领钱。
- 领完钱后,插件自动退出红包详情界面,回到摇一摇界面。
- 重复步骤1。
当前的微信版本是6.3.10
,iOS设备是越狱后的iPad mini 2
。
这个插件的功能算是很简单的,下面就说一下编写插件的过程:
一、获取微信的头文件
使用class-dump可以获取微信的头文件。
解压微信.ipa
,将Payload/WeChat.app/WeChat
这个可执行文件拷贝出来,然后在终端执行命令:
1
| class-dump -sSH WeChat -o WeChatHeaders
|
在生成的WeChatHeaders
文件夹里可以看到微信的所有类的头文件:
1 2 3 4 5 6 7 8 9
| . ├── ABNewPersonViewControllerDelegate-Protocol.h ├── ABPeoplePickerNavigationControllerDelegate-Protocol.h ├── ABTestItem.h ├── ABtestCase.h ├── ABtestMgr.h ├── ABtestPoint.h ├── ABtestPointPeriod.h ......
|
二、自动摇一摇
首先进入摇一摇界面:
使用Reveal查看视图控制器的类名:
然后在微信头文件里找到NewYearShakeViewController.h
,搜索关键字shake
,可以搜到一个方法:- (void)OnShake;
。
用电脑打开终端远程连接到iPad,再用Cycript附加微信,调用OnShake
方法:
1 2 3 4 5
| Jobs: ~$ ssh root@remoteip
Jobss-iPad:~ root# cycript -p WeChat
cy# [
|
执行命令后界面果然自动摇一摇了,并且跳到了红包详情界面。
三、自动领RMB
在红包详情界面,用Reveal可以看到logo是一个按钮:
在Cycript中使用以下方法可以获取点击按钮时调用的方法:
1 2 3 4 5 6 7 8 9 10 11
| cy# button = #"<ImagesAnimationButton: 0x1468358f0; baseClass = UIButton; frame = (364 0; 40 40); opaque = NO; layer = <CALayer: 0x174439640>>"
cy# button.allTargets() [NSSet setWithArray:@[#"<NewYearShakeInteractiveLogoView: 0x1468c6d50; frame = (0 930; 768 94); layer = <CALayer: 0x174622e40>>"]]]
cy# target = #"<NewYearShakeInteractiveLogoView: 0x1468c6d50; frame = (0 930; 768 94); layer = <CALayer: 0x174622e40>>"
cy# [button actionsForTarget:target forControlEvent:UIControlEventTouchUpInside] @["onClickLogoButton:"]
|
可以看到,点击按钮时会调用[NewYearShakeInteractiveLogoView onClickLogoButton:]
方法。
可以在NewYearShakeInteractiveLogoView
初始化后调用点击按钮的方法,就可以实现自动领取了。
这个方法需要传入按钮对象作为参数,在NewYearShakeInteractiveLogoView.h
里可以看到按钮是一个成员变量ImagesAnimationButton *m_logoView;
,所以可以通过[self valueForKey:@"m_logoView"]
方法获取按钮对象。
四、自动退出红包详情界面
领到钱后需要退出当前界面,才能继续重新摇一摇。
而点击按钮时会出现金币旋转的动画,然后请求网络领取RMB,领到RMB后再结束动画,也就是说动画执行的时间可能不是固定的。
如果能找到结束动画的方法的话,通过hook这个方法,就可以在动画结束后退出当前界面了。
用Hopper Disassembler
反编译微信的可执行程序,搜索NewYearShakeInteractiveLogoView onClickLogoButton
,按 alt + enter 生成伪代码:
1 2 3 4 5 6 7
| void -[NewYearShakeInteractiveLogoView onClickLogoButton:](void * self, void * _cmd, void * arg2) { r2 = arg2; r0 = self; r1 = @selector(onClickLogoEvent); r0 = loc_1c0d0d4(r0, r1, r2); return; }
|
可以看到调用了onClickLogoEvent
方法,查看该方法的伪代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void -[NewYearShakeInteractiveLogoView onClickLogoEvent](void * self, void * _cmd) { r7 = &arg_4; r4 = self; r1 = r4->m_hasClickLogo; asm{ it ne }; if (r1 != 0x0) { return; } r0 = *objc_ivar_offset_NewYearShakeInteractiveLogoView_m_hasClickLogo; *(int8_t *)(r4 + r0) = 0x1; r0 = *objc_ivar_offset_NewYearShakeInteractiveLogoView_m_logoView; r0 = *(r4 + r0); loc_e0a05c(r0, @selector(setEnabled:), 0x0, 0x1); loc_e0a05c(r4, @selector(setEmptyTipText)); loc_e0a05c(r4, @selector(stopShowAnimation)); loc_e0a05c(r4, @selector(startClickAnimation)); r1 = @selector(callClickLogoHongBao); r0 = r4; Pop(); Pop(); Pop(); r0 = loc_1c0d0d4(r0, r1, 0x0); return; }
|
伪代码里调用了startClickAnimation
方法开始执行动画,那么很可能存在一个停止执行动画的方法。
在NewYearShakeInteractiveLogoView.h
里搜索stop
,可以发现- (void)stopClickAnimation;
方法,基本上就可以确定这是停止动画时调用的方法了。
如果要在view的stopClickAnimation
方法里关闭红包界面的话,就需要通过view获取view所在的视图控制器,可以通过nextResponder
方法来获取。
最后让视图控制器对象调用dismissViewControllerAnimated:completion:
方法来退出红包界面。
五、编写插件
使用Theos新建一个tweak插件,代码非常简单:
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| @interface NewYearShakeViewController : UIViewController - (void)viewDidAppear:(BOOL)animated; - (void)OnShake; @end
@interface NewYearShakeInteractiveLogoView : UIView - (void)initView; - (void)onClickLogoButton; - (void)stopClickAnimation; @end
%hook NewYearShakeViewController
- (void)viewDidAppear:(BOOL)animated { %orig;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self OnShake]; }); }
%end
%hook NewYearShakeInteractiveLogoView
- (void)initView { %orig;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ UIButton *button = [self valueForKey:@"m_logoView"]; [self onClickLogoButton:button]; }); }
- (void)stopClickAnimation { %orig;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ UIViewController *noticeViewController = (UIViewController *)self.nextResponder.nextResponder.nextResponder; [noticeViewController dismissViewControllerAnimated:NO completion:nil]; }); }
%end
|
iPad安装插件后,重新打开微信,微信就会自动领一分钱了:
最后领到了很多一分钱,不知不觉中已经发财了: