Reprint Please specify source: http://blog.csdn.net/tang9140/article/details/42869269
First of all, this article is purely as a technical study of personal preferences, please do not use for illegal operation surplus take unfair advantage, you understand.
Problem leads
Probably in December 2014, 17, 18th, a large number of 12306 of the brush ticket software has been illegal request or ' use third party ticketing software ' prompt, and Verification code identification error. Later learned that 12306 in order to the malicious ticket software, plug-ins to contain and control, through means to identify the ticket to the software and the user to buy tickets behavior differences.
So here's the problem. , I was curious as to what they had done by what means.
Add, I have done the Java version of the ticket to the software, only for learning purposes, no other purpose. After 12306 plus third-party software detection, my brush ticket software also appeared ' illegal request ' prompt, even login can not go in. And it sparked my thinking.
What is the nature of the ticket-snatching software?
I personally think that the ticket-grabbing software is nothing more than a robot (in fact the so-called robot is a software, here is just a representation) instead of the entity to buy tickets. We all know that the machine reacts quickly, so at the same time to open the premise of the robbery, it must be the machine faster than the physical people, which is why scalpers can buy tickets, and you can't buy the ticket reason. Continue to think about why robots can take the place of real people to buy tickets for a series of operations? This leads to the next question.
A series of actions that a user buys tickets on a browser, from a technical point of view, what is essentially happening?
As we all know, the 12306 Web site provides a Web service based on the B/S architecture and is a service built on top of the HTTP protocol. The HTTP protocol is a typical request-response-mode protocol and is a stateless protocol. In fact, all the actions of the user in the browser, ultimately relying on the browser to send the request to the server, the server received the request after the corresponding business processing and return the results of the response to the browser side, the browser is displayed to the user. More specifically, the browser receives the user's various events (such as mouse click events, keyboard input events), and then sends an HTTP request to the server in the background, while the browser backend receives the response content from the server and presents it as an HTML page.
More generally, for the server, as long as the received request is in accordance with the HTTP protocol will be processed, it does not care whether the request is sent through the browser or the software sent over the ticket (the browser itself is a software, the general operating system comes with a browser). As can be seen from the above analysis, as long as the third-party software to fully simulate the browser to send compliant HTTP requests, the Web server will act as a legitimate request and processing. Then the question comes again, why the brush ticket software will appear "illegal request" hint, this is not with your analysis there is a contradiction? Well, actually, it's not contradictory. Please note that what I just said is "full simulation browser", before as the learning version of the ticket to the software did not strictly follow the browser to send HTTP requests, which also led to 12306 through some technical means to detect illegal requests. So, it leads to our ultimate problem.
12306 How to conduct technical testing, how to distinguish between normal requests and illegal requests?
Before answering this question, let's first understand the HTTP protocol. The HTTP request message is divided into four parts: the request line, the request header, the blank line, the optional request message body, there are eight kinds of request methods, the most common are the two: Get request and POST request. A GET request takes a parameter behind the URL (no body of the message), and the POST request takes the parameter in the body of the message. The request header may contain cookie information and so on. Back to the Chase, 12306. For illegal request detection, there are three aspects to check, that is, request header, Cookie, request parameters.
12306 detection Three aspects:
1. Request Header
When impersonating an HTTP request, you need to be aware of the order of the request headers. After I test, if the login request ' Cookie request header ' is placed behind the ' connection request header ', it will prompt ' illegal request '
2. Cookies
The cookie request header should also note the order, first Jsessionid (the other cookie in the middle) and finally Bigipserverotn,current_captcha_type
3. Request parameters
or the order of the problem, please strictly refer to the browser send request parameters in the order of sending. In addition, 12306 added dynamic key verification when logging in and submitting orders. You need to get to the dynamic JS file URL address, and then access the content of the JS file, extract the key value, and the JS file in the encryption algorithm to the key encryption after the corresponding value value.
Through the above three aspects of detection, you can find some illegal requests. Of course there are third-party software testing, there is anti-detection. Several hours after the introduction of this series of third-party software detection, monitoring and replacement verification codes (I believe there are three different verification codes), some swipe software was cracked. In fact, I think the so-called third-party software testing is a palliative, as if the game in the anti-plug detection, in a strong plug-in developers, it seems completely vulnerable. No matter how many times you add the verification, no matter how you change the validation rules, will be quickly cracked. I think, instead of spending time on how to anti-plug, it is better to provide external plug-in, for reference game practice, 12306 is not as good as the internal provide a key to rob the ticket function, do not need to select the train, select passengers, submit the next single verification code, re-confirm the complex process. Directly in accordance with the user's pre-set rules of a key to rob the ticket (need to ensure that with the internal one-click to rob the ticket function than the external swipe ticket software to grab the ticket to the probability of high), so it is actually some, how do you look at it. Supported by the likes of a
Code word is not easy, source from http://blog.csdn.net/tang9140.
Also attached to the key encryption algorithm Java version of the implementation code, interested students can see
public class Dynamicjsutil {private static String Keystr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01 23456789+/= "; Static class Base32 {private static int delta = 0X9E3779B8; public static String longarraytostring (int[] Data, Boolean includelength) {int length = Data.length; int n = (length-1) << 2; if (includelength) {int m = data[length-1]; if ((M < n-3) | | (M > N)) return null; n = m; } StringBuilder sb = new StringBuilder (""); for (int i = 0; i < length; i++) {int i0 = Data[i] & 0xff; int i8 = Data[i] >>> 8 & 0xFF; int i16 = data[i] >>> & 0xFF; int i24 = data[i] >>> & 0xFF; if (I0! = 0) sb.append ((char) i0); if (i8! = 0) sb.append ((char) i8); if (i16! = 0) sb.append ((char) i16); if (i24! = 0) sb.append ((char) i24); The String result; if (includelength) {result = sb.substring (0, N); } else result = Sb.tostring (); return result; } public static int[] Stringtolongarray (String str, Boolean includelength) {int length = Str.le Ngth (); int arrsize = length% 4 = = 0? LENGTH/4: LENGTH/4 + 1; Int[] result = new Int[arrsize]; for (int i = 0; i < length; i + = 4) {if (i + 4 > length) {int char8 = i + 1 > = length? 0:str.charat (i + 1) << 8; int char16 = i + 2 >= length? 0:str.charat (i + 1) << 16; int Char24 = i + 3 >= length? 0:str.charat (i + 1) << 24; Result[i >> 2] = Str.charat (i) | Char8 | Char16 | Char24; } else result[i >> 2] = Str.charat (i) | Str.charat (i + 1) << 8 | Str.charat (i + 2) << 16 | Str.charat (i + 3) << 24; } if (includelength) {int[] NewArr = new Int[arrsize + 1]; System.arraycopy (result, 0, NEWARR, 0, arrsize); Newarr[arrsize] = length; result = NEWARR; } return result; } public static string encrypt (String str, string key) {if (str = = "") {return ""; } int[] v = Stringtolongarray (str, true); int[] k = Stringtolongarray (key, false); if (K.length < 4) {int[] newArr = new Int[4]; System.arraycopy (k, 0, NEWARR, 0, k.length); K = NewarR } int n = v.length-1; int z = v[n], y = v[0]; int MX, E, p, sum = 0; int q = 6 +/(n + 1); while (0 < q--) {sum = sum + delta & 0xFFFFFFFF; e = Sum >>> 2 & 3; for (p = 0; p < n; p++) {y = v[p + 1]; mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z); z = v[p] = v[p] + mx & 0xffffffff; } y = v[0]; mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z); z = v[n] = v[n] + mx & 0xffffffff; } return Longarraytostring (V, false); }; public static string Encode32 (string input) {input = escape (input); StringBuilder output = new StringBuilder (); int Length = Input.length (); int Chr1, CHR2, CHR3; int enc1, ENC2, enc3, Enc4; int i = 0; do {chr1 = Input.charat (i++); ENC1 = Chr1 >> 2; Output.append (Keystr.charat (ENC1)); if (i < length) {CHR2 = Input.charat (i++); ENC2 = ((Chr1 & 3) << 4) | (CHR2 >> 4); Output.append (Keystr.charat (ENC2)); if (i < length) {CHR3 = Input.charat (i++); Enc3 = ((CHR2 &) << 2) | (CHR3 >> 6); Enc4 = CHR3 & 63; Output.append (Keystr.charat (ENC3)). Append (Keystr.charat (ENC4)); } else {enc3 = ((CHR2 &) << 2) | (0 >> 6); Output.append (Keystr.charat (ENC3)). Append (Keystr.charat (64)); }} else {enc2 = ((CHR1 & 3) << 4) | (0 >> 4); Output.append (Keystr.charat (ENC2)). Append (Keystr.charat (+)). Append (Keystr.charat (64)); }} while (I < length); return output.tostring (); } static string bin216 (string s) {s + = ""; String output = ""; int L = s.length (); for (int i = 0; i < L; i++) {char c = s.charat (i); String temp = integer.tostring (c, 16); Output + = Temp.length () < 2? "0" + temp:temp; } return output; public static string Escape (String src) {char J; StringBuffer tmp = new StringBuffer (Src.length () * 2); for (int i = 0; i < src.length (); i++) {j = Src.charat (i); if (Character.isdigit (j) | | | Character.islowercase (j) | | Character.isuppercase (j)) Tmp.append (j); else if (J < D) {if (j = = ' * ' | | j = = ' @ ' | | j = = '-' | | j = = ' _ ' | | '+' || j = = '. ' | | j = = '/') {tmp.append (j); } else {tmp.append ("%"); if (J < tmp.append) ("0"); Tmp.append (Integer.tostring (J, +). toUpperCase ()); }} else {tmp.append ("%u"); Tmp.append (Integer.tostring (J, 16)); }} return tmp.tostring (); /** * Gets the dynamic encryption value value * @param key * @return */public static string Getrandomparamvalue (String k EY) {return encode32 (dynamicjsutil.bin216 (Base32.encrypt ("1111", key)); }}
About 12306 third-party software detection research