上一篇文章《用了这个,我追到了自己的女神:Mac版QQ半自动发送情话》 发布后,有几个朋友私信问说QQ过时了女神不用了,能不能整个微信的?有别的大神已经开发了微信网页版的自动发消息,可以登录网页版微信的朋友可以去试一试把发送部分改掉就可以了,我因为不能登录网页版微信所以用不了,今天来尝试用逆向Mac微信解决一下这个问题。
最新版的插件直接看这篇文章逆向Mac版微信-情话助手终版(女神邀请我恰饭了~)
最新版的插件直接看这篇文章逆向Mac版微信-情话助手终版(女神邀请我恰饭了~)
最新版的插件直接看这篇文章逆向Mac版微信-情话助手终版(女神邀请我恰饭了~)
想学习逆向过程的可以往下看
首先利用Class-Dump拿到微信的头文件
打开终端执行:
class-dump -H 微信.app的路径 -o 头文件保存路径
执行之后就能获取到很多头文件了
英文好的都知道消息是Message,我就搜索一下,直接就找到了一个MessageService文件。
打开发现,发送消息的方法是在这个文件
有发送文本,发送定位,发送GIF等等方法,我们使用发送文本的方法就可以了。
选择微信APP文件,右键显示包内容,找到图中二进制可执行文件
扔Hopper Disassembler里边开始反编译,在漫长的等待后得到编译结果。
配合第一步中的头文件一顿常规查找分析之后,得到以下几个方法:
注入Mac App 的步骤和注入iOS步骤差不多,会iOS的可以直接跳下去看最后的Hook代码。
#import
#import
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
#import
#import "Wechat+hook.h"
static void __attribute__((constructor)) initialize(void) {
NSLog(@"开始加载");
// CBHookClassMethod();
[NSObject hookWeChat];
}
#import
@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
hook 代码
原理就是:替换登录按钮事件,点击登录按钮事件之后,每5秒查询一次授权状态,授权成功的时候发送消息
Wechat+hook.h
#import
@interface NSObject (WeChatHook)
+ (void)hookWeChat;
@end
Wechat+hook.m
#import "Wechat+hook.h"
#import "WeChatHeader.h"
#import "FQHelper.h"
#import
#import
#import
@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
#!/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获取一句情话并启动微信->点击微信登录按钮后->遍历查询是否登录完成->登录完成发送情话
按照上一篇文章步骤,以下只叙述修改点。
os.system("open 'tencent://message/?uin=992436880&Site=&Service=201&sigT=2cf2671557dd'")
改为:
os.system("open /Applications/WeChat.app")
sh /Users/jiashiqi/Downloads/hookWeChat-Mac-master/hookWeChat/other/Install.sh
因为是自动发送,爬取完情话最好自己先看一遍,把不合适的话删掉,不然小心女神拉黑你。
看完的朋友麻烦点个关注,点个赞,需要的朋友可以点个收藏。这个教程感觉还是写的麻烦了,写的过程也有了点新的想法,回边再研究研究看看能不能把教程再精简一下,下一篇出一个使用方法更简单的终极版插件。
如有问题可留言解决。