逆向微信Mac客户端:微信情话助手初版

前言

上一篇文章《用了这个,我追到了自己的女神:Mac版QQ半自动发送情话》 发布后,有几个朋友私信问说QQ过时了女神不用了,能不能整个微信的?有别的大神已经开发了微信网页版的自动发消息,可以登录网页版微信的朋友可以去试一试把发送部分改掉就可以了,我因为不能登录网页版微信所以用不了,今天来尝试用逆向Mac微信解决一下这个问题。

最新版的插件直接看这篇文章逆向Mac版微信-情话助手终版(女神邀请我恰饭了~)
最新版的插件直接看这篇文章逆向Mac版微信-情话助手终版(女神邀请我恰饭了~)
最新版的插件直接看这篇文章逆向Mac版微信-情话助手终版(女神邀请我恰饭了~)

想学习逆向过程的可以往下看

开始

工具
  • Xcode(苹果开发工具)
  • IDA (逆向神器,反编译工具 )
  • Class-dump (导出可执行文件的Class Header)

过程

1.Dump 出头文件

首先利用Class-Dump拿到微信的头文件
打开终端执行:

class-dump -H 微信.app的路径 -o 头文件保存路径

执行之后就能获取到很多头文件了
在这里插入图片描述
英文好的都知道消息是Message,我就搜索一下,直接就找到了一个MessageService文件。
在这里插入图片描述
打开发现,发送消息的方法是在这个文件
在这里插入图片描述
有发送文本,发送定位,发送GIF等等方法,我们使用发送文本的方法就可以了。

2.反编译

选择微信APP文件,右键显示包内容,找到图中二进制可执行文件
在这里插入图片描述
扔Hopper Disassembler里边开始反编译,在漫长的等待后得到编译结果。
在这里插入图片描述
配合第一步中的头文件一顿常规查找分析之后,得到以下几个方法:

  • 登录按钮事件: MMLoginOneClickViewController 中的
    -(void)onLoginButtonClicked:(id)arg1;
  • 授权状态查询 WeChat 下的
    -(BOOL)IsAuthOK;
  • 服务层处理中心-获取消息服务 : MMServiceCenter中的
    -(id)getService:(Class)arg1;
  • 发送信息服务: MessageService中的
    -(id)SendTextMessage:(id)arg1 toUsrName:(id)arg2 msgText (id)arg3 atUserList:(id)arg4;
3.hook 微信

注入Mac App 的步骤和注入iOS步骤差不多,会iOS的可以直接跳下去看最后的Hook代码。

  1. 在xcode中新建一个framework项目,取名hookWeChat在这里插入图片描述
  2. 添加一个FQHelper.h 和一个FQHelper.m文件 ,写入runtime 交换对象方法。
    FQHelper.h
    内容如下:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
NS_ASSUME_NONNULL_BEGIN
@interface FQHelper : NSObject
/**
 替换对象方法
 @param originalClass 原始类
 @param originalSelector 原始类的方法
 @param swizzledClass 替换类
 @param swizzledSelector 替换类的方法
 */
void hookMethod(Class originalClass, SEL originalSelector, Class swizzledClass, SEL swizzledSelector);

/**
 替换类方法
 @param originalClass 原始类
 @param originalSelector 原始类的类方法
 @param swizzledClass 替换类
 @param swizzledSelector 替换类的类方法
 */
void hookClassMethod(Class originalClass, SEL originalSelector, Class swizzledClass, SEL swizzledSelector);

@end

FQHelper.m
内容如下:


#import "FQHelper.h"
@implementation FQHelper
/**
 替换对象方法
 */
void hookMethod(Class originalClass, SEL originalSelector, Class swizzledClass, SEL swizzledSelector) {
    Method originalMethod = class_getInstanceMethod(originalClass, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(swizzledClass, swizzledSelector);
    if (originalMethod && swizzledMethod) {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

/**
 替换类方法
 */
void hookClassMethod(Class originalClass, SEL originalSelector, Class swizzledClass, SEL swizzledSelector) {
    Method originalMethod = class_getClassMethod(originalClass, originalSelector);
    Method swizzledMethod = class_getClassMethod(swizzledClass, swizzledSelector);
    if (originalMethod && swizzledMethod) {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

@end
  1. 添加一个Main.mm文件,内容如下:
#import <Foundation/Foundation.h>
#import "Wechat+hook.h"
	static void __attribute__((constructor)) initialize(void) {
    NSLog(@"开始加载");
    //    CBHookClassMethod();
    [NSObject hookWeChat];
}
  1. 添加一个WeChatHeader.h文件,声明刚才找到的那些方法,内容如下:
#import <Cocoa/Cocoa.h>

@interface MMLoginOneClickViewController : NSViewController
- (void)onLoginButtonClicked:(id)arg1;
@end

@interface WeChat : NSObject
- (BOOL)IsAuthOK;
@end

@interface CUtility : NSObject
+ (id)GetCurrentUserName;
@end

@interface MMServiceCenter : NSObject
+ (id)defaultCenter;
- (id)getService:(Class)arg1;
@end

@interface MessageService : NSObject
- (id)SendTextMessage:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4;
@end
  1. hook 代码
    原理就是:替换登录按钮事件,点击登录按钮事件之后,每5秒查询一次授权状态,授权成功的时候发送消息

    Wechat+hook.h

#import <Cocoa/Cocoa.h>
@interface NSObject (WeChatHook)
+ (void)hookWeChat;
@end

Wechat+hook.m

#import "Wechat+hook.h"
#import "WeChatHeader.h"
#import "FQHelper.h"
#import <CommonCrypto/CommonDigest.h>
#import <AppKit/AppKit.h>
#import <objc/runtime.h>

@implementation NSObject (WeChatHook)
+ (void)hookWeChat{
 hookMethod(objc_getClass("MMLoginOneClickViewController"), @selector(onLoginButtonClicked:), [self class], @selector(hook_onLoginButtonClicked:));
    
}
- (void)hook_onLoginButtonClicked:(NSButton *)btn {
    NSLog(@"点击了登录按钮");
    [self hook_onLoginButtonClicked:btn];
    [self getAuthState];
}

- (void)getAuthState{
    WeChat *wechat = [objc_getClass("WeChat") sharedInstance];
    if ([wechat IsAuthOK]) {
        NSLog(@"授权成功");
        dispatch_async(dispatch_get_main_queue(), ^{
            //            获取发送用户
            NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName];
            //            获取发送消息服务
            MessageService *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")];
            NSPasteboard *pb = [NSPasteboard generalPasteboard];
            if ([[pb types] containsObject:NSPasteboardTypeString]) {
                NSString *s = [pb stringForType:NSPasteboardTypeString];
                // do something
                [service SendTextMessage:currentUserName toUsrName:@"你女神的微信号" msgText:s atUserList:nil];
            }
            
        });
    }else{
        NSLog(@"授权失败");
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                [self getAuthState];
            });
        });
    }
}
@end
  1. 自动注入
    在xcode的targets->BuildPhases里添加一个脚本。
    脚本内容:
#!/bin/bash
app_name="WeChat"
framework_name="hookWeChat"
app_bundle_path="/Applications/${app_name}.app/Contents/MacOS"
app_executable_path="${app_bundle_path}/${app_name}"
app_executable_backup_path="${app_executable_path}_backup"
framework_path="${app_bundle_path}/${framework_name}.framework"
# 备份WeChat原始可执行文件
if [ ! -f "$app_executable_backup_path" ]
then
cp "$app_executable_path" "$app_executable_backup_path"
fi

cp -r "${BUILT_PRODUCTS_DIR}/${framework_name}.framework" ${app_bundle_path}
 ./insert_dylib --all-yes "${framework_path}/${framework_name}" "$app_executable_backup_path" "$app_executable_path"

定义好目标app的路径,备份好原有二进制文件。将编译好的framework文件拷贝到目标app目录,用insert_dylib这个工具进行注入。insert_dylib工具我放在demo项目根目录中

7.编辑schema的excutable,选择应用程序里的微信
在这里插入图片描述
8.运行程序,测试一下。
在这里插入图片描述
登录微信后,立即发送成功。运行一次后,已经注入成功,以后打开微信都会发送,剪贴板第一条信息。

使用教程

使用教程大致和QQ差不多,请参考上一篇文章《用了这个,我追到了自己的女神:Mac版QQ半自动发送情话》执行过程:开机自动启动情话执行脚本.app->执行python获取一句情话并启动微信->点击微信登录按钮后->遍历查询是否登录完成->登录完成发送情话
按照上一篇文章步骤,以下只叙述修改点。

  1. 爬取情话- 参考上一篇文章步骤1
  2. 调起QQ改调起微信 - 参考上一篇文章步骤2并做以下修改
os.system("open 'tencent://message/?uin=992436880&Site=&Service=201&sigT=2cf2671557dd'")
改为:
os.system("open /Applications/WeChat.app")
  1. .选择实用工具,运行脚本- 参考上一篇文章步骤3
  2. 写入shell语句 - 参考上一篇文章步骤4 ,因为有授权检测这里不需要加seelp
  3. 设置开机自启 – 参考上一篇文章步骤5
  4. 下载上面的hookWeCha工程:https://github.com/FORMAT-qi/hookWeChat-Mac 修改工程里Wechat+hook.m文件,并填入你女神的微信号,当然,如果你有好几个女神,你可以把发送消息的那句话在下边多复制几遍,只需要修改不同的微信号,就可以同时发送多个女神。
  5. 安装插件 :打开终端,执行 hookWeCha工程中other文件夹里的Install.sh脚本,卸载的话执行Uninstall.sh脚本。例如
sh /Users/jiashiqi/Downloads/hookWeChat-Mac-master/hookWeChat/other/Install.sh 
  1. 然后就配置完了,可以关机开机测试一波了。

结束语

因为是自动发送,爬取完情话最好自己先看一遍,把不合适的话删掉,不然小心女神拉黑你。

看完的朋友麻烦点个关注,点个赞,需要的朋友可以点个收藏。这个教程感觉还是写的麻烦了,写的过程也有了点新的想法,回边再研究研究看看能不能把教程再精简一下,下一篇出一个使用方法更简单的终极版插件。

如有问题可留言解决。

猜你喜欢

转载自blog.csdn.net/weixin_46602773/article/details/105944415