抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

除夕打开微信摇一摇抢红包,红包雨还没开始时,会显示如下界面:
This is a picture without description

底部圆形的logo在不停地跳动,点击一下,居然领到了一分钱:
This is a picture without description

如果不断摇一摇再点击logo,就可以领到很多一分钱。不过手动操作太麻烦了,所以写了个tweak插件来自动领取。

插件要做的操作大概如下:

  1. 在摇一摇界面,插件自动调用摇一摇的方法。
  2. 进入红包详情界面后,插件自动点击图标领钱。
  3. 领完钱后,插件自动退出红包详情界面,回到摇一摇界面。
  4. 重复步骤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
......

二、自动摇一摇

首先进入摇一摇界面:
This is a picture without description

使用Reveal查看视图控制器的类名:
This is a picture without description

然后在微信头文件里找到NewYearShakeViewController.h,搜索关键字shake,可以搜到一个方法:- (void)OnShake;

用电脑打开终端远程连接到iPad,再用Cycript附加微信,调用OnShake方法:

1
2
3
4
5
Jobs: ~$ ssh root@remoteip

Jobss-iPad:~ root# cycript -p WeChat

cy# [#0x1457f95b0 OnShake]

执行命令后界面果然自动摇一摇了,并且跳到了红包详情界面。

三、自动领RMB

在红包详情界面,用Reveal可以看到logo是一个按钮:
This is a picture without description

在Cycript中使用以下方法可以获取点击按钮时调用的方法:

1
2
3
4
5
6
7
8
9
10
11
cy# button = #0x1468358f0
#"<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 = #0x1468c6d50
#"<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;

//view初始化一秒后自动点击按钮
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安装插件后,重新打开微信,微信就会自动领一分钱了:

最后领到了很多一分钱,不知不觉中已经发财了:
This is a picture without description

评论