一、前言
看個圖,了解下投票的過程。
提交投票信息
投票頁 ――――――――>投票信息處理頁
反饋投票結果
(請求頁)<―――――――(響應頁)
一般情況下,填寫投票信息,然后點提交按鈕發送到響應頁,這樣來完成一個投票。這過程繁瑣,還不能多次投票。有時,手工投票達不到所期待的效果。
曾幫朋友弄過幾次投票,壇里有朋友也PM說要看看源代碼。投票器應該說沒有一個固定的框架,一些處理方法上需要視響應頁做針對性的改動。
自己寫的源代碼太雜亂,放出來怕丟人。10.1放假窩在家里寫了點心得,與大家分享一下。看過之后,你也可以寫。不當之處請指正。
制作投票器,最關鍵的二樣東西是獲得投票信息和找到響應頁。也就是說通過請求頁訪問(提交)響應頁時,提交了什么信息,并且這個響應頁是什么。找到了這兩樣,投票器完成了一大半。
二、編寫投票器所需要的一些HTTP知識
1、 最好是寫過一些網頁。看某網頁的源文件,可以很快找到哪些是form表單、BUTTON提交按鈕、INPUT文件框等內容。
惡補網站:
http://www.lib.tsinghua.edu.cn/chinese/INTERNET/HTML/Normal/html_design.html
http://www.w3.org/TR/REC-html40/index/elements.html
http://www.w3.org/TR/REC-html32.html
2、了解一個HTTP的消息頭由哪些內容組成。如下是一個表單提交后,向網站發送的消息頭內容:
POST /redsky/temp/whu_tp/vote.asp HTTP/1.1 //定義HTTP是一個POST動作
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
//響應頁可以使用的媒體類型
Referer: http://pmc.whu.edu.cn/redsky/temp/whu_tp/whu_tp.asp //請求頁的網址
Accept-Language: zh-cn //指定的字符集類型
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; mxie; .NET CLR 1.1.4322)
Host: pmc.whu.edu.cn
Content-Length: 46 //提交數據的長度
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: ASPSESSIONIDQSCDRSCC=NHNDPPNDPJJFBBJMLBAOMHOD //提交時所傳送的Cookie值。
voted=25&voted=30&voted=35&Submit=%CD%B6%C6%B1 //提交時,所傳送的數據
惡補網站:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14
小結: WIN form 、WEB FORM兩樣都得精通,這是師傅2002年說的。
三、輔助軟件
查看HTTP消息頭的軟件,專門的軟件有HTTP Watch(
http://www.hanzify.org/index.php?Go=Show::List&ID=4384)或IEWatch,
也可以用 CommView (這些天www.ttdown.com上的軟件沒法下載:-()之類抓包的軟件。
四、手工分析投票過程
先說說手工操作時一個正常的投票過程(以武漢大學的這個投票為例)
http://pmc.whu.edu.cn/redsky/temp/whu_tp/whu_tp.asp
選擇被投票人石云霞(在姓名前面打勾),然后點“投票”,響應頁接收被投票人的姓名并記錄投票數記錄投票人的IP,然后返回投票成功或重復投票的信息。
這一過程很簡單,但我們不知道點投票后,瀏覽器向網頁發送了什么信息。在這里,先別急著用軟件來看,嘗試手工分析,這有助于一些復雜情況的解決。
回到投票的網頁,查看源文件(前面所提到的http基本知識派上用場了),
a)首先找響應頁是什么,也就是接收處理投票信息的網頁。在記事本中按Ctrl+f,查找’<form’字符串。通過搜索,找到這么一行:
<form name="form1" method="post" action="vote.asp">
Form表單的名稱name=form1,方法method=post,動作action=vote.asp 。vote.asp是我們所關心的,這個就是響應頁的地址。
整理地址得到:http://pmc.whu.edu.cn/redsky/temp/whu_tp/vote.asp
b)查找被投票人的信息。被投票人的選擇是通過一個多選框來完成,那么在源文件里查找’<input’字樣。通過搜索,找到了以下內容。
<input type="checkbox" name="voted" value="25">
<a href="whu_tp_more.asp?id=25" class="index" target="_blank">
石云霞</a> <b><font color="#FFFF00" size="2"> </font></b>
<input type="checkbox" name="voted" value="26">
<a href="whu_tp_more.asp?id=26" class="index" target="_blank">
李義天</a> <b><font color="#FFFF00" size="2"> </font></b>
………………………….
從這一大串內容中可以看出,石云霞的編號為25,李義天的編號為26 ,input元素的名稱為voted。 整理一下voted=25這是被投票人的信息。
查找input的時候需要注意,看是否有hidden類型的input元素。隱藏一定數量的input元素,可以起到一定的防范作用。
在源文件里一直看下去,只到</form>為止。在</form>前還有兩個按鈕,
<input type="submit" name="Submit" value="投票">
<input type="reset" name="Submit2" value="重置">
組合一下 submit=投票 submit2=重置(這個內容可以忽略)。
c) 最后整理一下,得到一個完整的網址
http://pmc.whu.edu.cn/redsky/temp/whu_tp/vote.asp?voted=25& submit=投票
在瀏覽器中訪問一下這個地址,看有什么提示??,提示“投票成功“。再次訪問提示“你的IP已經投過一次了^_^”。這說明這個網址就是真正的投票網址。只要不斷地訪問這個網址,就可以達到投票的目的。
小結:沒寫過網頁也沒關系,通過輔助軟件也可以分析出這一網址。
五、軟件分析投票過程
安裝HTTPWATCH后,重啟機器,可以在IE標準按鈕欄中找到它的圖標(沒有的話,從菜單‘查看’->‘瀏覽器欄’中選擇),單點圖標后如圖,IE窗口下半部分顯示出HTTPWATCH的工作窗口。
http://bbs.et8.net/bbs/attachment.php?attachmentid=339392&stc=1
圖中顯示的內容是選擇點擊‘投票’按鈕后,IE與網站之間的數據流。上半部分記錄了IE訪問了哪幾個網頁,下半部分是訪問某個網頁時,具體的數據流。
(HTTPWATCH的使用方法在這里不細講了。)
我們在正常瀏覽網頁時,IE一般的動作都是GET。而投票過程中,IE需要將你的選擇(被投票人的姓名)提交給投票的網址,訪問這個網址時,IE將產生一個POST動作。查看HTTPWATCH的記錄,URL=http: //pmc.whu.edu.cn/redsky/temp/whu_tp/vote.asp時,IE的動作是POST。那么http: //pmc.whu.edu.cn/redsky/temp/whu_tp/vote.asp就是投票的響應頁。這和前面手工分析時找到的響應頁是一致的。
找到了響應頁,接下來找投票的信息,也就是IE提交了什么數據。這里看HTTPWATCH窗口的下半部分。
下半部分是一個TAB PANEL,看重要的幾個標簽。
HEADERS:提交到響應頁的HTTP HEADER的內容。
Cookies:提交時,Cookies的內容。
POST DATA:提交時,IE向響應頁發送的數據。
STREAM:提交時,本地機器與網站之間的傳輸的數據流。
http://bbs.et8.net/bbs/attachment.php?attachmentid=339393&stc=1
顯而易見,POST DATA是我們要找的內容。看到這個標簽,左邊是兩個參數名voted 和submit ,右邊是兩個參數的值,‘25’和‘投票’。整理一下得到:
Voted=25 submit=投票
將這兩個參數值與前面找到的網址整理一下,得到
http://pmc.whu.edu.cn/redsky/temp/whu_tp/vote.asp?voted=25& submit=投票
六、編寫投票器
找到了真正的投票URL,用C#做投票器就簡單了,無非是做到:如何循環地訪問這個網頁。
看下面的這個過程。
………
using System.Net;
………
public int GotoURL( out string message,string url,int timeout,string proxyurl,string keyword,out int rate,bool proxyed)
/*
Message:返回的信息
Url:需要訪問的地址
Timeout:超時時間
Proxyurl:代理的地址
Keyword:判斷投票成功的標志
Rate:訪問url所花費的時間
Proxyed:是否使用代理
*/
{
byte[] gbyte=new byte[1024];
string strInput;
int iret=3;
int i,len=0;
DateTime dtBegin=DateTime.Now;
message="正在訪問中。。。";
try
{
url=@"http://pmc.whu.edu.cn/redsky/temp/whu_tp/vote.asp?voted=25& submit=投票";
WebRequest myWebRequest=WebRequest.Create(url);
myWebRequest.Timeout=timeout;//設置超時時間=15000毫秒
if (proxyed)//是否使用代理功能
{
WebProxy myProxy=new WebProxy();//實例化一個WebProxy類,這個類設置WebRequest的Proxy屬性,這樣可以通過代理來訪問url。
myProxy=(WebProxy)myWebRequest.Proxy;
string proxyAddress= proxyurl;
Uri newUri=new Uri(proxyAddress);
myProxy.Address=newUri;
myWebRequest.Proxy=myProxy;
}
WebResponse myWebResponse=myWebRequest.GetResponse();//實例化一個WebResponse類,用于接收WebRequest的響應內容,依據內容來判斷投票是否成功。
Stream streamResponse=myWebResponse.GetResponseStream();// 實例化一個Stream類,從WebResponse接收數據流。
i=streamResponse.Read(gbyte,len,1024);
len+=i;
while(i!=0)
{
i=streamResponse.Read(gbyte,len,1024);
len+=i;
}
strInput=System.Text.Encoding.GetEncoding("gb2312").GetString(gbyte);
i=strInput.IndexOf("成功");
Console.WriteLine(i);
if (i==-1)
message="訪問成功";
else
message="訪問失敗";// 將數據流轉換成字符串,并從中判斷投票是否成功。
iret=0;
streamResponse.Close();
}
catch (System.Net.WebException we)
{
message="NetError"+we.Message;
}
catch (System.IO.IOException ie)
{
message="IOError"+ie.Message;
}
catch (System.Exception ex)
{
message=ex.Message;
}
TimeSpan ts=DateTime.Now-dtBegin;
rate=(int)ts.TotalMilliseconds; //獲取訪問的時間。
return iret;
}
過程很簡單,就是使用System.Net中的兩個類來訪問網頁。
創建實例:WebRequest myWebRequest=WebRequest.Create(url);
訪問網頁:WebResponse myWebResponse=myWebRequest.GetResponse();
流StreamResponse視響應頁的處理方法,可能沒有任何返回內容。
Stream streamResponse=myWebResponse.GetResponseStream();
考慮到一個IP只能投票一次的限制,過程加了使用代理的功能
WebProxy myProxy=new WebProxy();
這樣即可以當投票器來使用,也可以用于檢測代理的有效性。
接下來的事,就容易多了。找代理,循環調用這個過程。循環速度感覺慢的話,可以用多個線程一起來跑。
小結:直接訪問響應頁就能投票,這是最常見的投票方式。網頁設計人員沒有在響應頁做防范處理,從而為投票器創造了的條件。
防范措施通常有以下幾種:
1、 對HTTP HREADERS里的REFERER做判斷,為空表示沒有訪問過投票頁(提交頁)。這樣繞開請求頁,直接訪問響應頁是無效的。
2、 訪問投票頁時,在headers里的cookies里設置某種標志,提交時,響應頁對這個標志做判斷。沒有這個標志,直接訪問響應頁是無效的。
3、 訪問投票頁時,隨機生成N位數字驗證碼,響應頁對驗證碼做判斷。
4、 生成圖形驗證碼。響應頁對驗證碼做判斷。
第1、2種方法容易處理,研究出規律,設置WebRequest的headers屬性。
第3種方法需要多加個過程,首先訪問投票頁得到驗證碼,然后與其他data組合一同post給響應頁。
第4種無解,和和。不過,還沒發現哪種投票會用上圖形驗證碼這措施。手工投票不僅麻煩,同時也關閉了自己、他人的方便之門。
結言:
不管投票方式如何,投票所需填寫的內容有多復雜,最終它還是要提交給響應頁做處理。多看看http watch。
不會編程也沒關系,找代理軟件,利用代理檢測的功能,投票。