0x00 Story
One day afternoon, when it is the time for making reservation for next day’s reimbursement, I open the reimbursement platform and type in the reservation info then hit the submit button, but the server returns nothing but blank page and refresh does no help at all, which annoys me a lot and creates a really really bad experience. Since that I can do nothing to improve the server’s code or hardware performance, the only idea that I come up with is to build a ticketing tool, in which I can at lease find a way to submit reservation information instead of a blank page.
0x01 Method
Firstly, I need to record the whole process of web requests during making a reservation. The tool I use here is the Wireshark.
1 2 3 | Wireshark is a free and open-source packet analyzer. It is used for network troubleshooting, analysis, software and communications protocol development, and education. Originally named Ethereal, the project was renamed Wireshark in May 2006 due to trademark issues. ------------------------------ Wikipedia |
The web requests can be divided into 3 parts.
- Login requests to the information center.
- Login requests to the reimbursement platform.
- Reservation requests to book a ticket.
The first request set the cookies provided that the login credentials should be correct.
The second request helps us find the _VIEWSTATE and _VALIDATION.
Furthermore, I need to write the code to reproduce the aforementioned reservation procedure in the ticketing tool, including obtaining the cookies and sending reservation requests.
0x02 Implementation
0x021 Fetch the cookies
The easiest way to obtain the cookies is to reproduce login procedure to reimbursement platform.
Firstly, we need to login to Campus information portal, to reduce work load, I use WebBrowser to obtain portal cookies. Since the cookies is universal and generic on different platforms in HHU, we can use this cookies to login to reimbursement platform, which saves us a lot of work.
Secondly, we need to find the correct _VIEWSTATE and _VALIDATION. These two parameters are easy to find because it is stored in the html source, but these parameters bother me a lot because when I find the parameters in html source, I never foresee that it will change after the browser navigate from home page to ticketing page, which consequently resulted in server 500 code after I posted the data. Hence, there are two steps to find the correct _VIEWSTATE and _VALIDATION: 1. find the _VIEWSTATE and _VALIDATION in home page and save them 2. fetch the html source of ticketing page by post with _VIEWSTATE and _VALIDATION we have in hand, the post data’s FormUrlEncodedContent can be generated by:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | string[] key = new string[4] { "__EVENTTARGET", "__EVENTARGUMENT", "__VIEWSTATE", "__EVENTVALIDATION" }; string[] value = new string[4] { "LinkButton2", "", viewstate, validation }; var encodedContent=ContentBuilder(key, value); /// <summary> /// Build FormUrlEncodedContent from keys and values /// </summary> /// <param name="keys"></param> /// <param name="values"></param> /// <returns></returns> public FormUrlEncodedContent ContentBuilder(string[] keys, string[] values) { if (keys.Length != values.Length) return null; KeyValuePair<string, string>[] kvp = new KeyValuePair<string, string>[keys.Length]; for (int i = 0; i < keys.Length; i++) kvp[i] = new KeyValuePair<string, string>(keys[i], values[i]); return new FormUrlEncodedContent(kvp); } |
Before posting data to platform, there are still some parameters need to obtain, they are uid and uname, uid can be found on the url of ticketing page and uname can be found on the source of ticketing page.
Afterwards, we can construct the post data by following code:
1 2 3 | string[] key = new string[11] { "__EVENTTARGET", "__EVENTARGUMENT", "__LASTFOCUS", "__VIEWSTATE", "__EVENTVALIDATION", "txtIdentityName", "txtBookingDate", "DropAmPm", "DropBookingBranchId", "DropBookingBusinessName", "btnEnter" }; string[] value = new string[11] { "", "", "", viewstate, validation, identity, bookdate, ampm, branch, bussiness, "提 交" }; var encodedContent=ContentBuilder(key, value); |
the identity equals to the uname, bookdate is the date time string of desired data for reimbursement, the ampm is “上午” or “下午”, the branch is “本部校区” or “江宁校区”, the bussiness is “本部校区业务” or “江宁校区业务”.
Lastly, post aforementioned data to the platform, the result will be a html source, to tell whether the reservation is success or not can be judge from the JS alert code in html source.