利用C#编写网页投票器程序

一、前言
看个图,了解下投票的过程。
提交投票信息
投票页 ――――――――>投票信息处理页
反馈投票结果
(请求页)<―――――――(响应页)
一般情况下,填写投票信息,然后点提交按钮发送到响应页,这样来完成一个投票。这过程繁琐,还不能多次投票。有时,手工投票达不到所期待的效果。
曾帮朋友弄过几次投票,坛里有朋友也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。
不会编程也没关系,找代理软件,利用代理检测的功能,投票。

posted @ 2010-02-15 08:04  猪悟能  阅读(686)  评论(0编辑  收藏  举报