随着网络投票的兴起,刷票工具也应运而生。相关的技术分析也看了不少,正好碰上个机会,用python做了一个基于urllib的简单人肉刷票机。重点在思路分析和练手,所以下面把目标站点的信息都擦了,主要看个思路,不建议大家做坏事哟~
首先浏览一下投票页面,试着投了一票。发现再打开投票链接的时候浏览器就提示“你已参加过投票活动”。不可能靠IP识别用户,基本就是靠cookie了,果然清空一下就能反复投票,也没有发现对其它用户特征的识别限制。不过投票之前要先点击“获取验证码”,获取一个验证码图片进行输入验证,获取过程应该就是JS触发一个GET请求,验证码也都是规整的字母数字,估计随便找个在线OCR能搞定(好吧这里是我天真了),反正先按照套路接下来就是分析投票的HTTP请求,试着用程序模拟了。
各类文章对HTTP请求的分析也很多,就不详细说了,挂上Burpsuit直接看结果:
先看看访问投票页面的响应,有用的信息有几个:

投票首页的返回头部
![]()
投票首页返回部分内容
再看拦截到的请求验证码的过程

请求验证码图片的请求报文头
插曲
到这里,已经能通过模拟获得验证码了,本来打算用个在线OCR识别一下做成全自动,然而在做参数试验的时候,网站对提交应该是有防护预警的,识别到可疑行为之后先是暂停了一下,再开放之后验证码难度飙升,各种扭曲旋转中文字,反正它对单IP的访问频率也有限制,俺们也不是真的要做坏事,这里就搞成人肉模式了,获取验证码之后会弹出图片和程序输入提示,人肉识别输入完成提交。
提交的请求
先吐槽一下,这里的数据提交都还是用GET请求..基本没什么问题

提交投票请求
一路提交完,刷一下页面就可以看到投票成功咯~
最后附上代码,比较简单就没有写注释(好吧我承认还是因为我懒),和上面的过程是一样的~大家不要做坏事哟~
#coding=utf-8
from BeautifulSoup import *
import cStringIO
import urllib
import re
from PIL import Image
import time
import urllib2
url1 = \'http://www.example.com/\'
url2 = \'http://www.example.com/***?activity=***&get=image&c=DesignerInitializedCaptcha&t=\'
while True:
cookie = \'\'
iid = \'\'
page = urllib.urlopen(url1)
for header in page.info().headers:
if \'Set-Cookie\' in header:
cookie += re.findall(r\'Set-Cookie:( \\S*;)\',header)[0]
rnd = re.findall(r\'jac*****=(.*);\',cookie)[0]
soup = BeautifulSoup(page)
tags = soup(\'img\')
for tag in tags:
if tag.get(\'instanceid\', None):
iid = tag.get(\'instanceid\')
req = urllib2.Request((url2 + iid))
req.add_header(\'Host\',\' www.example.com\')
req.add_header(\'Proxy-Connection\',\'keep-alive\')
req.add_header(\'Accept\',\'image/webp,image/*,*/*;q=0.8\')
req.add_header(\'Referer\',\'http://www.example.com/\')
req.add_header(\'User-Agent\',\'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36\')
req.add_header(\'Accept-Encoding\',\'gzip, deflate, sdch\')
req.add_header(\'Accept-Language\',\'zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4\')
req.add_header(\'Cookie\', cookie)
cfile = cStringIO.StringIO(urllib2.urlopen(req).read())
img = Image.open(cfile)
img.show()
cpt = raw_input(\'验证码是多少:\')
data = {\'validate_text\':cpt, \'source\':\'directphone\', \'submittype\':\'1\', \'rn\':\'3525361439.\'+rnd, \'btuserinput\':cpt, \'btcaptchaId\':\'DesignerInitializedCaptcha\', \'btinstanceId\':iid, \'t\':str(int(time.time()*1000)), \'submitdata\':\'1$29|31|32|33\', \'useget\':1}
url3 = \'http://www.example.com/***?curid=7125344&starttime=2016%2F2%2F3%2019%3A32%3A15&\' + urllib.urlencode(data)
req = urllib2.Request(url3)
req.add_header(\'Host\',\' www.example.com\')
req.add_header(\'Proxy-Connection\',\'keep-alive\')
req.add_header(\'Accept\',\'*/*\')
req.add_header(\'X-Requested-With\',\'XMLHttpRequest\')
req.add_header(\'Referer\',\'http://www.example.com/\')
req.add_header(\'User-Agent\',\'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36\')
req.add_header(\'Accept-Encoding\',\'gzip, deflate, sdch\')
req.add_header(\'Accept-Language\',\'zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4\')
req.add_header(\'Cookie\', cookie)
result = urllib2.urlopen(req)
print result.read()
time.sleep(10)