QQ 機器人源代碼 之盜號:
QQ機器人源代碼_CrazyCoder_CN.rar
分析QQ協議具體數據包,最簡單的辦法,是Http接口下手,於是把我以前寫的Ajax給拆了,在把所謂的qq接口研究成果給鼓搗在一起,然后去 Webqq(http://Webqq.qq.com)上大搶一遍,那家伙,天昏地暗,相當的&(&(。
代碼我是用script寫的:
異步Ajax會話類
1//異步Ajax會話類
2if(typeof(AjaxSession) == 'undefined')
3var AjaxSession = function(){
4
5 //創建會話
6 this.CreateSession = function()
7 {
8 if (window.ActiveXObject){ // IE
9 try{
10 return new ActiveXObject('Microsoft.xmlHTTP');
11 }catch(e){}
12
13 try{
14 return new ActiveXObject('Msxml2.xmlHTTP');
15 }catch(ee){}
16 }else{ //Mozilla, Safari
17 var s = new xmlHttpRequest();
18 if (s.readyState == null) {
19 s.readyState = 1;
20 s.addEventListener("load", function () {
21 s.readyState = 4;
22 if (typeof(s.onreadystatechange) == "function")
23 s.onreadystatechange();
24 }, false);
25 }
26
27 return s;
28 }
29
30 return null;
31 }
32
33 //進行請求
34 this.Request = function(url, params, callback)
35 {
36
37 var s = this.CreateSession();
38 if(null == s)
39 alert("對不起,您的瀏覽器不支持某些特性。");
40 else
41 s.abort();
42
43 var isAsync = typeof(callback) == 'function';
44 var method = !params ? "GET" : "POST";
45
46 if(isAsync) s.onreadystatechange = function()
47 {
48 try{
49 alert(s.status);
50 if ((4 == s.readyState) && (200 == s.status || 304 == s.status))
51 callback(this.Response(s));
52 else
53 alert("請求錯誤,錯誤原因:" + s.statusText);
54 }catch(e){}
55 }
56
57 s.open(method, url, isAsync);
58 s.setRequestHeader("Connection","Keep-Alive");
59 s.setRequestHeader("Content-Type","text/html; charset=gb2312");
60 //s.setRequestHeader("Content-Type","text/plain; charset=UTF-8");
61
62 if(method == "POST")
63 {
64 s.setRequestHeader("Content-Length",params.length)
65 s.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
66
67 }
68
69 alert(params);
70 s.send(params);
71
72
73 if(!isAsync)
74 return this.Response(s);
75 }
76
77 //返回應答信息 瘋狂代碼
78 this.Response = function(s)
79 {
80 if(s.status == 200 || 304 == s.status)
81 {
82 if(s.responsexml != null && s.responsexml.xml != null && s.responsexml.xml != '')
83 return s.responsexml;
84 else
85 return s.responseText;
86 }
87 }
88
89 //對字符串進行編碼
90 this.UncCoding = function(s)
91 {
92 var utput = '';
93 for(var i = 0 ;i< s.length;i++){
94 output = output + '%' + s.charCodeAt(i);
95 }
96
97 return output;
98 }
99
100 //獲取xml結構 傲博知識庫
101 this.GetDom = function(s){
102 var doc = new ActiveXObject('Microsoft.xmlDOM');
103 doc.async = false;
104 doc.loadxml(s) ;
105 return doc;
106 }
107
108 return this;
109}
//QQ會話類
1//會話類
2if(typeof(QQSession) == 'undefined')
3var QQSession = function(){
4 this.UIN = 0;
5 this.md5PasswordStr = "";
6 this.WebQQUrl = "http://tqq.tencent.com:8000/";
7 this.qs = null;
8 this.isLogin = false;
9 this.SeqIndex = null;
10
11 //用戶登陸
12 this.Login = function(uin,passwd,vcode,qs){
13 var m5 = new md5();
14 this.UIN = uin;
15 this.md5PasswordStr = m5.calcmd5(passwd);
16 var CmdStr = "VER=1.0&CMD=1&SEQ=" + this.GetNewSEQ() + "&UIN=" + uin + "&PS=" + this.md5PasswordStr + "&STATUS=10&VCODE=" + vcode + "&QQSESSION=" + qs ;
17
18 //if(!this.qs)
19 // this.qs = new AjaxSession();
20 window.frames["proxy"].request(this.WebQQUrl,CmdStr);
21 //this.qs.Request(this.WebQQUrl,CmdStr,this.ShowMsg);
22
23 //document.getElementById("ssl_login").callback = this.ShowMsg;
24 //document.getElementById("ssl_login").src = "https://Webqq-proxy.qq.com/Webqq/l?"+ CmdStr;
25 }
26
27 //用戶信息
28 this.GetInfo = function(){
29 var CmdStr = "VER=1.0&CMD=10&SEQ=" + this.GetNewSEQ() + "&UIN=" + this.UIN + "&FUIN=" + this.UIN;
30 this.qs.Request(this.WebQQUrl,CmdStr,this.ShowMsg);
31 //window.frames["proxy"].request(this.WebQQUrl,CmdStr);
32 }
33
34 //獲取好友列表
35 this.GetList = function(){
36 var CmdStr = "VER=1.0&CMD=2&SEQ=" + this.GetNewSEQ() + "&UIN=" + this.UIN + "&NPOS=0";
37 this.qs.Request(this.WebQQUrl,CmdStr,this.ShowMsg);
38 }
39
40 //獲得新的SEQ CrazyCoder.cn
41 this.GetNewSEQ = function(){
42 if(!this.SeqIndex){
43 var d = new Date();
44 this.SeqIndex = d.getTime()
45 }
46
47 this.SeqIndex ++;
48 return this.SeqIndex;
49 }
50
51 this.ShowMsg = function(s){
52 alert(s);
53 }
54
55 return this;
56}
我在那用天真的眼神,盼望着能從這個地方掏出點東西來。可偏偏我這個比較倒霉的孩子,碰到了極其復雜的網絡問題(家窮人丑,只好用手機上網,速度回到上世紀90年代),掏了半天啥也沒弄到,返回的盡是12152錯誤。
去翻MSDN時,遇到幾個頭疼的單詞(鄙人英語着實差勁,單詞量屈指可數),很習慣的就去開金山詞霸。等等,金山詞霸能把別的窗口的信息給拽出來,為什么我就不能。於是我就拋棄了前面的工作,從QQ對話窗口下手。nndx,偶就不信了,偶還滅不了你。
說干就干,那就先勾吧,.net好象是干不了這事,但是winapi還是能干這活的。win32編程嘛,不就幾個消息循環(—(—……*(—
WinApi調用
1using System;
2using System.Drawing;
3using System.Runtime.InteropServices;
4
5namespace TQQ
6{
7 /**//// <summary>
8 /// WinApi調用
9 /// </summary>
10 public class WinApi
11 {
12 /**//// <summary>
13 /// 根據鼠標位置獲取窗體
14 /// </summary>
15 /// <param name="lpPoint"></param>
16 /// <returns></returns>
17 [DllImport("user32.dll")]
18 public static extern IntPtr WindowFromPoint(Point lpPoint);
19
20 /**//// <summary>
21 /// 獲取鼠標位置
22 /// </summary>
23 /// <param name="lpPoint"></param>
24 /// <returns></returns>
25 [DllImport("user32.dll")]
26 public static extern int GetCursorPos(out Point lpPoint);
27
28 /**//// <summary>
29 /// 獲取鼠標位置下的窗體
30 /// </summary>
31 /// <returns></returns>
32 public static IntPtr GetLocalWindow()
33 {
34 Point point;
35 GetCursorPos(out point);
36 return WindowFromPoint(point);
37 }
38
39 /**//// <summary>
40 /// 申請內存空間
41 /// </summary>
42 /// <param name="hProcess"></param>
43 /// <param name="lpAddress"></param>
44 /// <param name="dwSize"></param>
45 /// <param name="flAllocationType"></param>
46 /// <param name="flProtect"></param>
47 /// <returns></returns>
48 [ DllImport( "Kernel32.dll" )]
49 public static extern Int32 VirtualAllocEx(IntPtr hProcess,Int32 lpAddress,Int32 dwSize,Int16 flAllocationType,Int16 flProtect);
50
51 /**//// <summary>
52 /// 讀取內存空間
53 /// </summary>
54 /// <param name="hProcess"></param>
55 /// <param name="lpBaseAddress"></param>
56 /// <param name="lpBuffer"></param>
57 /// <param name="nSize"></param>
58 /// <param name="lpNumberOfBytesWritten"></param>
59 /// <returns></returns>
60 [ DllImport( "Kernel32.dll" )]
61 public static extern int ReadProcessMemory(IntPtr hProcess, Int32 lpBaseAddress,byte[] lpBuffer,long nSize,long lpNumberOfBytesWritten);
62
63 /**//// <summary>
64 /// 寫內存空間
65 /// </summary>
66 /// <param name="hProcess"></param>
67 /// <param name="lpBaseAddress"></param>
68 /// <param name="lpBuffer"></param>
69 /// <param name="nSize"></param>
70 /// <param name="lpNumberOfBytesWritten"></param>
71 /// <returns></returns>
72 [ DllImport( "Kernel32.dll" )]
73 public static extern int WriteProcessMemory(IntPtr hProcess, Int32 lpBaseAddress,byte[] lpBuffer,long nSize,long lpNumberOfBytesWritten);
74
75 /**//// <summary>
76 /// 根據類/標題查找窗口
77 /// </summary>
78 /// <param name="lpClassName"></param>
79 /// <param name="lpWindowName"></param>
80 /// <returns></returns>
81 [DllImport("User32.dll",EntryPoint="FindWindow")]
82 public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
83
84 /**//// <summary>
85 /// 獲取窗口子對象
86 /// </summary>
87 /// <param name="hwndParent"></param>
88 /// <param name="hwndChildAfter"></param>
89 /// <param name="lpszClass"></param>
90 /// <param name="lpszWindow"></param>
91 /// <returns></returns>
92 [DllImport("user32.dll",EntryPoint="FindWindowEx")]
93 public static extern IntPtr FindWindowEx(IntPtr hwndParent,IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
94
95 /**//// <summary>
96 /// 發送windows消息
97 /// </summary>
98 /// <param name="hWnd"></param>
99 /// <param name="Msg"></param>
100 /// <param name="wParam"></param>
101 /// <param name="lParam"></param>
102 /// <returns></returns>
103 [DllImport("User32.dll")]
104 public static extern IntPtr SendMessage(IntPtr hWnd,int Msg,IntPtr wParam,IntPtr lParam);
105
106 /**//// <summary>
107 /// 發送windows消息
108 /// </summary>
109 /// <param name="hWnd"></param>
110 /// <param name="Msg"></param>
111 /// <param name="wParam"></param>
112 /// <param name="lParam"></param>
113 /// <returns></returns>
114 [DllImport("User32.dll",EntryPoint="SendMessage")]
115 public static extern int SendMessage(IntPtr hWnd,int Msg, IntPtr wParam, string lParam);
116
117 /**//// <summary>
118 /// 發送windows消息
119 /// </summary>
120 /// <param name="hwnd"></param>
121 /// <param name="wMsg"></param>
122 /// <param name="wParam"></param>
123 /// <param name="lParam"></param>
124 /// <returns></returns>
125 [DllImport("user32.dll", CharSet = CharSet.Auto)]
126 public static extern int SendMessage( IntPtr hwnd, int wMsg, int wParam,string lParam);
127
128 /**//// <summary>
129 /// 發送windows消息
130 /// </summary>
131 /// <param name="hwnd"></param>
132 /// <param name="wMsg"></param>
133 /// <param name="wParam"></param>
134 /// <param name="lParam"></param>
135 /// <returns></returns>
136 [DllImport("user32.dll", CharSet = CharSet.Auto)]
137 public static extern int SendMessage( IntPtr hwnd, int wMsg, int wParam,int lParam);
138
139 /**//// <summary>
140 /// 發送windows消息
141 /// </summary>
142 /// <param name="hwnd"></param>
143 /// <param name="wMsg"></param>
144 /// <param name="wParam"></param>
145 /// <param name="lParam"></param>
146 /// <returns></returns>
147 [DllImport("user32.dll", CharSet = CharSet.Auto)]
148 public static extern int SendMessage( IntPtr hwnd, int wMsg, int wParam,System.Text.StringBuilder lParam);
149
150 public const int WM_GETTEXT = 0x000D;
151 public const int WM_GETTEXTLENGTH = 0x000E;
152 public const int WM_SETTEXT = 0x000C;
153 public const int WM_CLICK = 0x00F5;
154 public const int WM_CHAR = 0x0102;
155 public const int EM_SETSEL = 0x00B1;
156 public const int EM_REPLACESEL = 0x00C2;
157
158 }
159}QQ鈎子
1/**//// <summary>
2 /// QQ鈎子
3 /// </summary>
4 public class QQHooks
5 {
6 /**//// <summary>
7 /// 發送消息
8 /// </summary>
9 /// <param name="windowName">窗口標題</param>
10 /// <param name="strMsg">消息內容</param>
11 public static void SendMsg(string windowName,string strMsg)
12 {
13 string lpszParentClass = "#32770"; //整個窗口的類名
14 string lpszParentWindow = windowName; //窗口標題
15 IntPtr ip = WinApi.FindWindow(lpszParentClass,lpszParentWindow);
16 IntPtr EdithParentWnd = WinApi.FindWindowEx(ip,new IntPtr(0),"#32770","");
17 IntPtr EdithWnd = WinApi.FindWindowEx(EdithParentWnd,new IntPtr(0),"AfxWnd42","");
18
19 string lpszClass_Text = "RICHEDIT"; //消息輸入窗口
20 string lpszName_Text = ""; //消息輸入窗口
21 IntPtr THandle = WinApi.FindWindowEx(EdithWnd,new IntPtr(0),lpszClass_Text,lpszName_Text);
22
23 StringBuilder sb = new StringBuilder(strMsg);
24 WinApi.SendMessage(THandle,WinApi.EM_SETSEL,-1,-1);//
25 WinApi.SendMessage(THandle,WinApi.EM_REPLACESEL,0,sb);
26
27 string lpszClass_Submit = "Button"; //需要查找的Button的類名
28 string lpszName_Submit = "發送(&S)"; //需要查找的Button的標題
29 IntPtr TButtonHandle = WinApi.FindWindowEx(EdithParentWnd,new IntPtr(0),lpszClass_Submit,lpszName_Submit);
30 WinApi.SendMessage(TButtonHandle,WinApi.WM_CLICK,new IntPtr(0),"");//發送消息到目標控件使它執行click事件
31 }
32
33 /**//// <summary>
34 /// 獲取消息
35 /// </summary>
36 /// <param name="windowName">窗口標題</param>
37 /// <returns></returns>
38 public static string GetMsg(string windowName)
39 {
40 string lpszParentClass = "#32770"; //整個窗口的類名
41 string lpszParentWindow = windowName; //窗口標題
42 IntPtr ip = WinApi.FindWindow(lpszParentClass,lpszParentWindow);
43 IntPtr EdithWnd = WinApi.FindWindowEx(ip,new IntPtr(0),"#32770","");
44
45 string lpszClass_Text = "RichEdit20A"; //查找歷史記錄類
46 string lpszName_Text = ""; //查找歷史記錄類的標題
47 IntPtr THandle = WinApi.FindWindowEx(EdithWnd,new IntPtr(0),lpszClass_Text,lpszName_Text);
48
49 StringBuilder sb = new StringBuilder(300000);
50 WinApi.SendMessage(THandle,WinApi.WM_GETTEXT,255,sb);//發送消息到目標控件
51 WinApi.SendMessage(THandle,WinApi.WM_SETTEXT,0,"");
52 return sb.ToString();
53 }
54 }
東西到手了,傳話筒的工作基本上算是完成了,接下來就讓它顯示出來:
1 /**//// <summary>
2 /// 時鍾事件
3 /// </summary>
4 /// <param name="sender"></param>
5 /// <param name="e"></param>
6 private void tmGetMsg_Tick(object sender, System.EventArgs e)
7 {
8 //群1里的消息
9 string strMsg = QQHooks.GetMsg(txtGroupWinName1.Text);
10 string str = "";
11
12 if(!string.Empty.Equals(strMsg))
13 {
14 ArrayList msgList = ParseMsg.Parse(strMsg);
15
16 foreach(QQMsg msg in msgList)
17 {
18 if("253822559" == msg.Number.ToString())continue;
19
20 if(string.Empty.Equals(msg.Msg.Trim()))
21 str = string.Format("{0}在群1里做了個表情\r\n",msg.Name,msg.Msg);
22 else
23 str = string.Format("{0}在群1里說:\r\n{1}\r\n",msg.Name,msg.Msg);
24
25 lbGroupMsgList1.Items.Add(str);
26 //save msg
27
28 //發送消息
29 QQHooks.SendMsg(txtGroupWinName2.Text,str);
30 QQHooks.SendMsg(txtGroupWinName3.Text,str);
31
32 }
33 }
34 }
這里的txtGroupWinName1是讓輸入qq窗口標題。以前用asm32做程序的時候就覺的微軟夠BT的,要是每個窗口編譯的時候就給限制個GUID多好—()—*)((—
至此大功算是告成了,完美交差。拿着這東東,改天狠狠的宰我師兄幾頓.
(07-01-04)續:
要的人太多了,我還是主動把東西傳上來吧,要不然有騙 email地址之嫌
源代碼和相關資料下載:/Files/sukyboor/Q.rar
附,說明:先介紹一下http方法:
1,qq接口.txt
是我在網絡上找的一篇“C#編寫QQ接口軟件--QQ協議篇” 里面有QQhttp協議訪問的詳細的介紹,協議標准是v1.1。但是經過我是沒調通,好象是http://tqq.tencent.com:8000被封了,你有沒有好的運氣我就不知道了。tx的Webqq用的端口是http://Webqq-proxy.qq.com:8080/這個就是慢點,用還是能用的。
2,Maxthon_Appin 文件夾下面有2個文件QQTest.txt ,GetQQSession.txt。maxthon有個簡易收集面板你可以動態的去調試腳本.用maxthon打開http://Webqq.qq.com后裝入qqtest.txt你會發現訪問過程的一舉一動都在你的監視之中。Log.txt就是這么來的。GetQQSession.txt操作同上,用於獲取一個新的sessionid
3,log.txt是監視http://Webqq.qq.com的訪問過程后得來的.你可以參考qq接口.txt看。不過tx的Webqq用的是v1.0的接口,但大體上是相似的,相信聰明的你是可以看懂的。
4,Webqq文件夾下放着http://Webqq.qq.com被我下到本地的頁面。有興趣的可以去看看里面的腳本,尤其是js\Web_cmd.js雖然寫的比我還爛,但還是值得一看。
5,WQQ文件夾下放着我寫的測試頁面。不過我家的破電腦調不通。如果你運氣好的話,在這個基礎上繼續干吧。不過別忘記了,到時候把做好的東西發給我一份(sukyboor·163.com)。
好了,下面說說鈎子方法
項目在TQQ文件夾下面,注釋寫的挺詳細的,自己看吧。
就提醒4點,
1 是app.config里面的qqnum一定要配置成你的qq號,否則你就等着別人罵你sx吧。
2 主窗口上的幾個輸入框一定要配置成群聊窗口的標題,否則它啥也干不了
3 別告訴我你還用qq2005
4 消息被轉發以后在窗口里是看不到的,得點聊天記錄按紐以后才能看的見