@leptune
2018-09-12T02:16:48.000000Z
字数 9194
阅读 394
chrome插件
可以定时、批量、自动发送信息给好友、群,可以获取微信聊天消息的应用程序,即成为微信机器人。
现在网上流传的微信机器人都是利用web微信的接口来实现的,利用模拟登录web微信,来获取微信接口调用凭证和cookie信息,以实现微信机器人。但这个方式有个弊端,就是很容易被微信查封。因为微信可以通过检测web微信端的cookie和一些接口请求、数据特征、cookie特征等,来辨别该接口是否是web微信调用的,还是微信机器人调用的。
所以,最安全的方式,是利用chrome插件可以注入js的方法,往web微信端注入js,在js中调用微信的各种接口,进行最大限度伪装自己是web微信调用的接口,从而避免被封!
若不用开发者工具栏,而直接用js来模拟微信登录的话,会变得异常艰难。
首先,需要获取各种必须的参数,有些必须研究web微信js源码,才能知道是怎么获取的参数。
其次,即使各种参数都获取到了,也模拟登录成功了,但依然有可能被微信察觉,毕竟不是web微信发起的登录。
最后,用js模拟登录,实现会过于复杂,一旦微信更改登录机制,那也意味着插件要改动非常多!
而如果是利用开发者工具栏的chrome插件,不用去费劲脑筋去模拟登录微信,不用去研究怎么获取微信调用凭证,不用去思考怎么获取微信登录cookie。利用开发者工具栏的chrome插件,有个非常有用的api,就是可以监听网页的所有请求。利用这点,当web微信登录成功后,监听web微信发起的获取联系人接口、群列表接口、发送信息接口、获取最新信息接口等,然后模拟这些接口,发起微信请求,即可伪装成web微信,来发起这些请求,避免被微信查封!!!



{"manifest_version": 2,"name": "微信机器人","description": "chrome微信机器人","version": "1.0","browser_action": {"default_icon": "img/icon.png"},"devtools_page": "devtools.html","background": {"scripts": ["js/jquery-2.0.3.js", "js/background.js"]},"content_scripts": [{"matches": ["https://wx2.qq.com/*","https://wx.qq.com/*"],"js": ["js/jquery-2.0.3.js", "js/content.js"]}],"permissions": ["activeTab","tabs","https://login.weixin.qq.com/*","https://wx2.qq.com/*","http://www.wx-robot.com/*","https://wx.qq.com/*"]}
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/devtools.js" charset="utf-8" type="text/javascript"></script></head><body></body></html>
chrome.extension.sendRequest({tabId: chrome.devtools.inspectedWindow.tabId, action: 'dev_start', msg: 'devtools js start'});// dev域用于toolbar的网络监听chrome.devtools.network.onRequestFinished.addListener(function (request) {// 转发所有微信请求到background页面if (request.request.url.indexOf('wx2.qq.com') != -1 || request.request.url.indexOf('wx.qq.com') != -1) {request.getContent(function (body) {chrome.extension.sendRequest({tabId: chrome.devtools.inspectedWindow.tabId,action: 'request',request: request,body: body,});});}return true;});
console.log('backgroud js start');// 监听来自content-script的消息chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {// console.log('收到content-js消息');switch (request.action) {case 'request':// console.log(request);if (request.data.type == 'post') {$.post(request.data.url, request.data.data, function (data) {// console.log('post res:', data);sendResponse(data);});} else {$.get(request.data.url, function (data) {// console.log('get res:', data);sendResponse(data);});}break;}return true;});// 接收来自dev页面的消息chrome.extension.onRequest.addListener(function (request) {// 直接转发给content页面// console.log(request)chrome.tabs.sendRequest(request.tabId, request);});
console.log('content js start');var initGlobals = {friendsInfo: {},friends: {},groupsInfo: {},groups: {},myInfo: {},my: {},sendBase: {},notFirst: true,};var otherGlobals = {adminUser: {},};String.prototype.trimChars = function (c) {var re = new RegExp("^[" + c + "]+|[" + c + "]+$", "g");return this.replace(re, "");}function init_globals() {initGlobals = {friendsInfo: {},friends: {},groupsInfo: {},groups: {},myInfo: {},my: {},sendBase: {},notFirst: true,};}function typeOf(obj) {return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();}function isEmpty(value) {if (!value) {return true;}if ('array' == typeOf(value) || 'string' == typeOf(value)) {return !value.length;}if('object' == typeOf(value)){for(var key in value) {if(Object.prototype.hasOwnProperty.call(value, key)) {return false;}}return true;}return false;}function getNullKeys() {var nullKeys = [];for (var key in initGlobals) {if (isEmpty(initGlobals[key])) {nullKeys.push(key);}}return nullKeys;}function login() {$('body').append('\<div class="wx-robot-top">\<style>\.wx-robot-zzc {position: fixed; top: 0; right: 0; bottom: 0; left: 0; background-color: rgba(0,0,0,.8); z-index:9998}\.wx-robot-wrap {width: 100%;text-align: center;position: absolute;top: 20%;background: none;z-index: 9999;}\.wx-robot-div {width: 60%; text-align: center; background: #f1f1f1; padding: 31px; margin: 0 auto;}\.wx-robot-btn-user {width: 30%; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555; background-color: #fff; border: 1px solid #ccc; border-radius: 4px;}\.wx-robot-btn-pwd {width: 30%; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555; background-color: #fff; border: 1px solid #ccc; border-radius: 4px;}\.wx-robot-btn-login {width: 19%; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555; background-color: #fff; border: 1px solid #ccc; border-radius: 4px;}\.wx-robot-btn-login:hover {color: #333; background-color: #e6e6e6; border-color: #adadad; }\</style>\<div class="wx-robot-wrap">\<div class="wx-robot-div">\<h1>微信机器人后台管理系统</h1>\<br/>\<div class="my-wx-robot">\<input class="wx-robot-btn-user" name="robot_user" type="text" placeholder="用户名">\<input class="wx-robot-btn-pwd" name="robot_pwd" type="password" placeholder="密码">\<input class="wx-robot-btn-login" type="button" value="登录">\</div>\</div>\</div>\<div class="wx-robot-zzc"></div>\</div>\');}function setInitGlobas(key, value) {// console.log('get initGlobals.'+key);initGlobals[key] = value;//发送消息content层var nullKeys = getNullKeys();if (!nullKeys.length) {console.log('all finished!');initGlobals.notFirst = false; // 确保初始化程序只运行一次myRequest({url: 'http://www.wx-robot.com/index/chrome/isLogin',callback: function(data) { //检测是否已经登录后台// console.log(data);if (data.errcode) {login();} else {otherGlobals.adminUser = data.data;console.log('开始监听任务...');listenTask();}},});} else {if (nullKeys.length > 1) console.log('nullKeys: ', nullKeys);}}function do_request(request) {var reqData = request.request.request;if (-1 != reqData.url.indexOf('&me=me')) { // 避开循环监听return;}// 获取群联系人(不能直接用监听返回的数据,因为中文会乱码)if (-1 != reqData.url.indexOf('wx2.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact')) {var tmpData = JSON.parse(reqData.postData.text);if (!isEmpty(tmpData) && !isEmpty(tmpData.BaseRequest)) {setInitGlobas('sendBase', tmpData.BaseRequest);}$.post(reqData.url+'&me=me', JSON.stringify(JSON.parse(reqData.postData.text)), function (data) {setInitGlobas('groupsInfo', JSON.parse(data));var tmpData = {};initGlobals.groupsInfo.ContactList.forEach(function(e){tmpData[e.NickName] = e.UserName;});setInitGlobas('groups', tmpData);});}if (-1 != reqData.url.indexOf('wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact')) {// 获取联系人(不能直接用监听返回的数据,因为中文会乱码)$.get(reqData.url+'&me=me', function (data) {setInitGlobas('friendsInfo', JSON.parse(data));var tmpData = {};initGlobals.friendsInfo.MemberList.forEach(function(e){tmpData[e.NickName] = e.UserName;});setInitGlobas('friends', tmpData);});}if (-1 != reqData.url.indexOf('wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit')) {var tmpData = JSON.parse(request.body);if (!isEmpty(tmpData) && !isEmpty(tmpData.User)) {setInitGlobas('myInfo', tmpData);setInitGlobas('my', tmpData.User);}}if (-1 != reqData.url.indexOf('wx2.qq.com/cgi-bin/mmwebwx-bin/webwxlogout')) {// 重新初始化init_globals();}}function myRequest(param) {chrome.runtime.sendMessage({action: 'request',data: param,}, function(response) {if (param.callback) {param.callback(response);}});}function sendmsg(data, task_id) {if (!data.nickname && !data.username) {return;}var Msg = {Type: 1,Content: "0",FromUserName: "0",ToUserName: "0",LocalID: "0",ClientMsgId: "0"};var username = data.username;if (!username) {if (!data.isGroup && initGlobals.friends[data.nickname]) {username = initGlobals.friends[data.nickname];} else if (data.isGroup && initGlobals.groups[data.nickname]) {username = initGlobals.groups[data.nickname];}}if (!username) {console.log('没有该用户: ', data.nickname);return;}Msg.Content = data.msg;Msg.ToUserName = username;Msg.FromUserName = initGlobals.my.UserName;var clientMsgId = new Date().getTime() + (Math.random() + "").substring(2, 6);Msg.LocalID = clientMsgId;Msg.ClientMsgId = clientMsgId;$.post("https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&me=me", JSON.stringify({BaseRequest: initGlobals.sendBase, Msg: Msg, Scene: 0}), function (data) {data = JSON.parse(data);// console.log(data);if (data.BaseResponse.Ret) {console.log('发送消息失败: ', data.BaseResponse.ErrMsg);return;}console.log('发送消息成功!');if (task_id) {myRequest({url: 'http://www.wx-robot.com/index/chrome/execReport?is_success=1&task_id='+task_id, callback: function (data) {console.log(data);}});}});}var clickFlag = 0;function loginSuccess() {alert('成功,可以关掉开发者工具栏了!');$('.wx-robot-top').remove();// 保持在线(function heartBit() {//模拟点击if(clickFlag == 0) {clickFlag = 1;$('.web_wechat_tab_chat').click();}else {clickFlag = 0;$('.web_wechat_tab_friends').click();}sendmsg({username: 'filehelper',msg: "保持在线:" + new Date(),});setTimeout(heartBit, 20*1000);})();}// 循环等待服务器的任务function listenTask() {myRequest({url: 'http://www.wx-robot.com/index/chrome/listen',callback: function(data) {// console.log(data);if (!data.errcode) {console.log('get task: ', data);data = data.data;switch (data.action) {case 'sendmsg':sendmsg(data.data, data.id);break;}}setTimeout(listenTask, 1000);},});}$(document).on('click', '.wx-robot-btn-login', function(event) {myRequest({url: 'http://www.wx-robot.com/index/chrome/login',type: 'post',data: {user: $('.wx-robot-btn-user').val(),pwd: $('.wx-robot-btn-pwd').val(),},callback: function(data) {// console.log('login data:', data);if (!data.errcode) {otherGlobals.adminUser = data.data;loginSuccess();listenTask();} else {alert('用户名或密码错误!');}},});});// 接收来自background页面的消息chrome.extension.onRequest.addListener(function(request) {// console.log('收到background消息');switch (request.action) {case 'dev_start':console.log('devtools js start');break;case 'request':do_request(request);break;}return true;});