上个月有人让我帮忙投票,我想要不写个程序给他多刷点得了,虽然这事情有悖原则,就当娱乐了。。

先上图

1.分析

既然是网页投票,那肯定可以伪造HTTP请求来实现刷票。需要分析的就是该网站到底采用了哪些防止刷票的措施。原投票已经停了,我给大家描述一下。

(1).首先,这是公开给所有人的投票,没有必须是其用户的限制。

(2).先按F12查看网络情况,抓取投票的HTTP请求。点投票,截取,发现是Get方式,QuerySting值有一个随机数,一个候选人的编号,还有一个不清楚的值,初步猜测是用Cookie限制的。

(3).投完票再点投票,显示“你已经参与过,每天只能投一次”。

(4).在Chrome浏览器,设置,隐私设置,查看Cookie里,找该网站的Cookies,发现多了一个不清楚的,还有一个存着候选人编号的Cookie。把这俩都删了,再点投票,显示“投票失败”。虽然没投票成功,但是返回信息不一样了,说明肯定和Cookie有关。

(5).直接禁用该网站的Cookie,点投票还是显示“投票失败”。

(6).这时候仔细看了看QueryString那一长传不清楚的值,和Cookie里那个不清楚的值是相同的,投票按钮的事件应是不会变的,那估计页面加载的时候这俩就一起加载了。然后刷新页面,果然这个值变了。

(7).然后只删除存候选人编号的Cookie,保留这个Cookie,再点投票,成功了!

这个网站防刷票的措施比较简陋,只要仔细看看就能发现这个问题。然后我做了第一版。

2.构造HTTP请求

(1).获取SID。先把上面我说的那个一长串不清楚的值叫做SID吧,应该是为了验证Cookie是否起作用。

private string GetSid()
{
string url = "http://www.xxxxxx.com/xxxx/list-510-1.html";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
var res = req.GetResponse() as HttpWebResponse;
string sid= res.Headers.GetValues(5)[0].Split('=')[1];//把Response里第一个Cookie的的值从Headers里取出来。
return sid;
}

(2).根据浏览器抓取的HTTP请求模拟一个HTTP请求

      private HttpWebRequest CreatHttp()
{
Random rnd = new Random();
string rndstr = rnd.NextDouble().ToString();//这是模仿QueryString里那个随机数的,没有估计也不影响结果
string url = "http://www.xxxxxx.com/xxxx/api.php?op=qgtp&id=32&sid=" + sid + "&r=" + rndstr;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
CookieCollection cookies = new CookieCollection();
//添加Cookie
cookies.Add(new Cookie("xxxxaction", sid, "/rail", "www.peoplerail.com"));
cookies.Add(new Cookie("xxxxxxxrand", rndstr, "/rail", "www.peoplerail.com"));
//存的也是随机数,生命周期只有2秒,所以分析的时候没发现,为了仿的逼真就也写上了
req.CookieContainer = new CookieContainer();
req.CookieContainer.Add(cookies);
req.Method = "GET";
req.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36";
req.Timeout = 10000;
req.Referer = "http://www.xxxxxx.com/xxxxxx/index.php?m=content&c=index&a=lists&catid=517&page=6";
req.KeepAlive = true;
req.Headers.Add("x-requested-with", "XMLHttpRequest");
//以上全部按照浏览器里抓取的结果一一对应
return req;
}

(3).刷票,并观察刷票状况。就是将返回的内容里找到票数,更新到TextBox上。

     private void Go()
{
HttpWebRequest req = CreatHttp();
var res = req.GetResponse() as HttpWebResponse;
Stream st = res.GetResponseStream();//读取Response
StreamReader sr = new StreamReader(st);
string result = sr.ReadToEnd().ToString();
try
{
textBox1.Text = result.Split(':')[1].Split('<')[0];//从返回的内容里找出票数
}
catch
{
timer1.Stop();
label2.Text = "刷票暂停";
}
}

(4).设置循环。用For循环发请求的话,嗖一下几百次循环完了,而那边还没反应过来。中间用Sleep()的话,程序有时会陷入假死的状态,不能实时观察到刷票的情况。所以我们就用Winform自带的控件Timer,在页面加载的时候先停了,设置时间间隔,然后在Timer的事件里加上上面的方法就可以了。

  private void Form1_Load(object sender, EventArgs e)
{
timer1.Stop();
timer1.Interval = 1000;
}

3.改进

上面几步完成后试着刷了一下,发现刷太快系统会返回“投票失败,疑似刷票”的提示,又调整了一下间隔时间。可过了两天,突然又不好使了,几番分析,发现是加了IP限制。找代理比较麻烦,所以就用宽带重连的方法不停的换IP吧。每刷一票断线重连一次就可以了。

   public static string Connect(string UserS,string PwdS)
{
string arg = @"rasdial.exe 宽带连接" + " " + UserS + " " + PwdS;
return InvokeCmd(arg);
} public static string Disconnect()
{
string arg = string.Format("rasdial \"{0}\" /disconnect", "宽带连接");
return InvokeCmd(arg);
} private static string InvokeCmd(string cmdArgs)
{
string Tstr = "";
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start(); p.StandardInput.WriteLine(cmdArgs);
p.StandardInput.WriteLine("exit");
Tstr = p.StandardOutput.ReadToEnd();
p.WaitForExit();
p.Close();
return Tstr;
}

网页投票没有完善的防止刷票的措施,只能说是防君子不防小人,要想刷了总能找到空子。

最新文章

  1. JCCLIENT IP GET UDP
  2. Extjs插入图片
  3. ASP------如何使界面布局具有一致外观
  4. [sql server发布订阅]after触发器执行失败造成复制不成功
  5. 如何设置 Windows 开机启动项
  6. linux驱动程序之电源管理之标准linux休眠与唤醒机制分析(一)
  7. jquery实现很简单的DIV拖动
  8. poj 2593 Max Sequence(线性dp)
  9. JavaSE(十)集合之Set
  10. Flask 微信公众号开发
  11. 有效的括号(Java实现)
  12. MySQL创建数据库时指定编码utf8mb4和添加用户
  13. Appium之编写H5应用测试脚本(切换到Webview)
  14. Core Mvc传值ViewData、ViewBag和return view(model)
  15. hive sql求多个字段的最小值和最大值的办法
  16. Python数据类型的可变与不可变
  17. git命令操作的时候,出现中文名显示问题
  18. java.lang.NoClassDefFoundError: org/hibernate/QueryTimeoutException
  19. The compiler compliance specified is 1.5 but a JRE 1.8 is used
  20. 合成的默认构造函数定义为delete的一种情况(针对C++11标准)

热门文章

  1. 【Open Search产品评测】- 来往,7天轻松定制属于自己的搜索引擎
  2. MS SQL SERVER 中的系统表
  3. Linux Centos 7 使用yum安装 mysql5.7 (实验成功)
  4. Linux的SOCKET编程详解
  5. angularJs中上传图片/文件功能:ng-file-upload
  6. 转:eclipse怎样修改包(package)的显示样式、格式 工具/原料
  7. 四舍五入PK银行四舍五入
  8. sql导出查询数据
  9. Javascript中关于数组的认识
  10. ubuntn14.04 32位安装hadoop2.7.2