iOS逆向实战三:修改微信钱包零钱

实现效果.gif

网上多数修改零钱是通过cycript修改,这种和reveal修改界面没什么区别,断开数据线或退出当前界面就没有了。要做到动态修改,就要分析来源,找出零钱是用了那个model的字段,然后写出tweak。
先吐槽下微信的代码,臃肿多又乱,新手不建议直接逆向微信。

1.先分析钱包和零钱界面,找到viewController

1.1 ssh root@localhost -p 2222(如果不是usb调试,请ssh到手机ip)->cycript -p WeChat->把keyWindow recursiveDescription写入文件

recursiveDescription写入文件有两个好处:一可避免cycript控制台显示不全,二避免cycript中文显示编码。

查找viewController-1

1.2 打开keyWindow.txt,直接搜索零钱,拿到零钱label地址0x18f79890

搜索零钱

1.3通过nextResponder来找到当前的viewController

nextResponder查找当前viewController

"<WCBizMainViewController: 0x17c16200>"就是当前viewController,可通过[#0x17c16200 setTitle:@"My Wallet"]修改标题来验证,也可以直接搜索你的余额,直接修改余额的值,这里就自行验证了。同理可得出零钱页面的WCPayBalanceDetailViewController。


搜索余额

以上的结论是: WCBizMainViewController是钱包界面的viewController, WCPayBalanceDetailViewController是零钱界面的viewController。

2.分析WCBizMainViewController和WCPayBalanceDetailViewController

2.1 class-dump WeChat拿到头文件

我只直接把需要的头文件拖入XCode,方便分析


头文件拖入XCode

2.2 先浏览下WCBizMainViewController的头文件

其中有两个refreshView的方法吸引了我。而且还是带参数的


WCBizMainViewController头文件分析

2.3先分析refreshViewWithMallControlData方法,找出(id)arg1是什么

2.3.1 LLDB调试
WeChat当前的偏移地址

0x00002000就是WeChat偏移的地址

2.3.2 使用IDA找到refreshViewWithMallControlData函数偏移的地址
搜索refreshViewWithMallControlData

搜索refreshViewWithMallControlData结果
2.3.3 设置断点并打印参数

r0是当前控制器,r1是当前函数,r2是函数的第一个参数

打印arg1参数

WCMallControlData是refreshViewWithMallControlData的参数

2.3.4分析WCMallControlData数据
2.3.4.1打开WCMallControlData.h

WCMallControlData.h

一眼看去,变量不是很多,但每个变量表示什么?
打开微信进入钱包页->cycript -p WeChat->choose(WCMallControlData),一个一个变量查看吧,或者觉得那个变量是符合的,打印出来。
cycript -p WeChat

打印第二个时候的显示了很多,看着像是配置信息,把\U转成中文。
这个可以放在.py中转换,需要用\u替换\U,否则python也解析不了。
python转换中文

把.py拖入终端
.py文件拖入终端

看到信用卡还款、微粒贷借钱、手机充值、理财通就知道这是腾讯服务这块了。还有icon_link,可以打开看看能不能对应上。

2.3.4.2分析WCPayControlData.h文件

WCPayControlData是refreshViewWithPayControlData的参数,可以用2.3的方法分析得出。我就不再赘述了。


WCPayControlData.h

一看头文件,500多行,我是晕的,一个一个打印,得到后年马月吗,我是个懒人,当然还是要找方便的方法。再吐槽下,model全放一起,是为了管理方便吗?反正我没这么写过。

2.3.4.3 runtime打印WCPayControlData属性

为了省事和长久考虑,我决定尝试用runtime打印属性。下面是我的在网上找的方法,细节不赘述。遍历属性返回一个字典,然后写入手机路径/var/mobile/%@.txt

#import "NSObject+SimplePropertyLog.h"
#import <objc/runtime.h>

@implementation NSObject (SimplePropertyLog)

- (void)writeToFileWithClass{
    //声明一个字典
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    
    //得到当前class的所有属性
    uint count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    
    //循环并用KVC得到每个属性的值
    for(int i = 0; i<count; i++) {
        objc_property_t property = properties[i];
        NSString *name = @(property_getName(property));
        id value = [self valueForKey:name]?:@"nil";//默认值为nil字符串
        [dictionary setObject:value forKey:name];//装载到字典里
    }
    
    //释放
    free(properties);
    
    NSString * allClassMessage = [NSString stringWithFormat:@"%@",dictionary];
    NSString * writePath = [NSString stringWithFormat:@"/var/mobile/%@.txt",NSStringFromClass([self class])];
    [allClassMessage writeToFile:writePath atomically:NO encoding:4 error:NULL];
}

@end
runtime打印WCPayControlData结果
2.3.4.4 结果分析

去除nil,去除0,剩下的分析就简单的多。我们可以按名称来排优先级.也发现一个规律,微信支付都是WCPay开头。如果你英文还可以,能看到WCPayLoanEntryInfo应该是贷款的,m_payApplyNewCardInfo支付信用卡的,

{
eCardControlData = "<WCPayECardControlData: 0x1798acb0>";
honeyPayData = "<WCPayHoneyPayControlData: 0x177e9320>";
"m_arrBindedCard" = (
"<WCPayBindCardInfo: 0x17b257f0>",
"<WCPayBindCardInfo: 0x17921180>",
"<WCPayBindCardInfo: 0x179017e0>",
"<WCPayBindCardInfo: 0x17b6ed40>",
"<WCPayBindCardInfo: 0x179efb60>"
);
"m_f2fControlData" = "<WCPayF2FControlData: 0x177eead0>";
"m_loanEntryInfo" = "<WCPayLoanEntryInfo: 0x179f0b30>";
"m_payApplyNewCardInfo" = "<WCPayBindCardListApplyNewCardInfo: 0x17814030>";
"m_payMenuArrayInfo" = "<WCPayPayMenuArrayInfo: 0x17a27a20>";
"m_structBalanceInfo" = "<WCPayBalanceInfo: 0x17789380>";
"m_structLqtInfo" = "<WCPayLQTInfo: 0x17b21800>";
"m_structSwitchInfo" = "<WCPaySwitchInfo: 0x176eca20>";
"m_structUserInfo" = "<WCPayUserInfo: 0x17a36eb0>";
securityData = "<WCPaySecurityControlData: 0x17756770>";
transferMoneyData = "<WCPayTransferMoneyData: 0x17b7e3e0>";
}

同样的方法,我分析了WCPayLQTInfo应该是零钱通,WCPayBalanceInfo就是我要找的余额。

WCPayBalanceInfo字段分析

3.tweak编写

1.分析完了,就需要写tweak代码了。tweak的语法还是有点奇怪,和真正的OC还是有很多的不同,例如我Category中弹出UIAlertView就显示不出来。
2.其次model的属性需求声明,字段和.h model属性保持一致。勾住对应的类和方法就ok了。

@interface WCPayLqtCellInfo:NSObject
@property(retain, nonatomic) NSString *lqt_wording;
@end

@interface WCPayUserInfo:NSObject
@property(retain, nonatomic) WCPayLqtCellInfo *lqtCellInfo;
@end

//余额支付
@interface WCPayBalanceInfo:NSObject
@property(nonatomic) unsigned long long m_uiAvailableBalance;
@property(nonatomic) unsigned long long m_uiFetchBalance; // @synthesize m_uiFetchBalance;
@property(nonatomic) unsigned long long m_uiTotalBalance;
@end

@interface WCPayControlData:NSObject
@property(retain, nonatomic) WCPayTransferMoneyData *transferMoneyData; 
@property(retain, nonatomic) WCPayUserInfo *m_structUserInfo;
@property(retain, nonatomic) WCPaySwitchInfo *m_structSwitchInfo;
@property(retain, nonatomic) WCPayLQTInfo *m_structLqtInfo;
@property(retain, nonatomic) WCPayBalanceInfo *m_structBalanceInfo;
@property(retain, nonatomic) WCPayBindCardListApplyNewCardInfo *m_payApplyNewCardInfo;
@property(retain, nonatomic) WCPayPayMenuArrayInfo *m_payMenuArrayInfo;
@property(retain, nonatomic) WCPayLoanEntryInfo *m_loanEntryInfo;
@property(retain, nonatomic) WCPayF2FControlData *m_f2fControlData;
@property(retain, nonatomic) WCPayHoneyPayControlData *honeyPayData;
@end


@interface WCBizMainViewController:UIViewController

@end


static long long canUsingMoney = 80000000;

%hook WCBizMainViewController

- (void)viewWillAppear:(BOOL)arg1{
    %orig;
    self.title = @"My Wallet";
}

- (void)refreshViewWithPayControlData:(WCPayControlData *)arg1
{
    [arg1 writeToFileWithClass];
    arg1.m_structBalanceInfo.m_uiAvailableBalance = canUsingMoney;
    arg1.m_structBalanceInfo.m_uiTotalBalance = canUsingMoney;
    arg1.m_structBalanceInfo.m_uiFetchBalance = canUsingMoney;
    %orig;
}

%end

//微信
%hook WCPayBalanceDetailViewController

- (void)refreshViewWithData:(WCPayControlData *)arg1{
    arg1.m_structBalanceInfo.m_uiAvailableBalance = canUsingMoney;
    arg1.m_structBalanceInfo.m_uiTotalBalance = canUsingMoney;
    arg1.m_structBalanceInfo.m_uiFetchBalance = canUsingMoney;

    arg1.m_structUserInfo.lqtCellInfo.lqt_wording = @"¥1000000000";
    
    NSLog(@"WeChat:refreshViewWithData: %s,%@,",object_getClassName(arg1),arg1);
    %orig;
}

%end

总结:

1.分析完了,看似没什么难度,好像一切水到渠成,然而中间的磕磕碰碰只有自己能体会。费了一星期的时间,哈哈。分析的过程是痛苦的,就像在没有光的黑夜里行走,你不知道路在何方,当你得出结果时,就像黎明的曙光,一切都是值得的。
2.文中的方法不一定就是最优解,读者可自行考虑是否可以再优化。例如查看属性除了cycript -p和runtime打印,能不能再做优化,或者有更好的方式。
3.有任何问题欢迎留言交流。

iOS逆向实战一:实现按下home键截屏,如何使用hook的对象属性
iOS逆向实战二:微信聊天界面实现飘气球效果
iOS逆向实战三:修改微信钱包零钱
iOS逆向实战四:去优酷广告

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容