您的位置:首页 > 运维架构 > 网站架构

破解需验证码登录网站~ing

2007-04-04 18:10 344 查看
何谓验证码?

验证码就是以图片格式将文本、数字、符号表示出来,在登录网站、发表评论时,同时将这些信息输入,以防止某些程序恶意登录、刷贴等,但也影响了某些情况下的正常程序访问。这些符号人眼很容易识别,但对计算机来说却非常不易,从而达到防范恶意程序的目的。

验证码的原理

验证码无非就是根据某些信息产生符号集,然后将这些符号集转换成图片。早期的验证码基本上都是数字加英文字母,而且生成的图片背景也比较干净,这就为一些OCR软件提供了可乘之机,通过专业的OCR软件就能轻易识别出验证码的文本信息。但从现在的应用来看,不仅背景上添加了许多杂色,而且符号也开始不工整,甚至采用了汉字,大大增加了OCR识别的难度。

实现验证码有两种主要的方式:
1. 访问页面时由jsp,aspx等脚本生成验证码图片,同时将验证码信息写入本地cookies, 可用函数加密,当页面提交时就会在本地判断cookies.code是否与你输入的验证码相等,或者与f(cookies.code)做比较,即生成的验证码是cookies的一个函数值。要破解这种方式,几乎不需要动用OCR,只要正确输入一次验证码,把这个正确的验证码及cookies记录下来,不断地用正确的cookies去替换新cookies,就可以不断的提交页面。

2, session控制。session控制与第1种的不同之处在于,对照码放在一个session变量里,提交时会将你输入的验证码与这个session变量或其函数值做比较,由于session变量是取不到的,所以破解的难度也大大增加。

以下主要针对第2种情况进行分析。

准备工作

先了解验验码的生成原理

在需要验证码的页面放如下代码,即一个输验证码的文本框和一个验证码图片,(注意是由asp脚本生成的)

<input type="text" name="validatecode" size="20"><img src="validatecode.asp"></p>

假如该页要提交到view.asp,

在view.asp中写如下代码:(sas_validatecode是任意命名的,只要与下文validatecode.asp中保持一致即可)

if(Trim(request.form("validatecode"))=Empty or trim(session("sessionname_validatecode"))<>Trim(request.form("validatecode"))) then
response.write("请输入正确验正码")
else
response.write("you are right!" & request.form("validatecode"))
end if

%>

再看一下validatecode.asp的代码:

<%
Option Explicit
Response.Buffer = True
Response.Expires = -1
Response.AddHeader "Pragma","no-cache"
Response.AddHeader "cache-ctrol","no-cache"
Dim RndNum,ImgFileContent
Randomize Timer
RndNum = Cint(7999*Rnd+1000)
Session("sas_ValidateCode") = Cstr(RndNum)
ImgFileContent=NumCode(RndNum)
Response.ContentType = "image/BMP"
Response.BinaryWrite ImgFileContent

Function NumCode(NumS)
Dim NumI,NumJ
Dim AdoM,AdoN
Dim Arr_Img(4),NStr
NStr=Cstr(NumS)
For NumI=0 To 3
Arr_Img(NumI)=Cint(Mid(NStr,NumI+1,1))
Next
Dim Position
Set AdoM=Server.CreateObject("Adodb.Stream")
AdoM.Mode=3
AdoM.Type=1
AdoM.Open
Set AdoN=Server.CreateObject("Adodb.Stream")
AdoN.Mode=3
AdoN.Type=1
AdoN.Open
AdoM.LoadFromFile(Server.Mappath("validatebody.fix"))
AdoN.Write AdoM.Read(1280)
For NumI=0 To 3
AdoM.Position=(9-Arr_Img(NumI))*320
AdoN.Position=NumI*320
AdoN.Write AdoM.Read(320)
Next
AdoM.LoadFromFile(Server.Mappath("validatehead.fix"))
Position=Lenb(AdoM.Read())
AdoM.Position=Position
For NumI=0 To 9 Step 1
For NumJ=0 To 3
AdoN.Position=NumI*32+NumJ*320
AdoM.Position=Position+30*NumJ+NumI*120
AdoM.Write AdoN.Read(30)
Next
Next
AdoM.Position = 0
NumCode = AdoM.Read()
AdoM.Close:Set AdoM=Nothing
AdoN.Close:Set AdoN=Nothing
End Function
%>

这段代码就是随机生成数字,然后去控制两个文件,validatebody.fix和validatehead.fix,它其实是BMP图片的两部分,head是BMP文件的通用头,即前54个字节,body就是验证码的主体了。生成验证码之后将这两部分合在一起生成一个可显示出来的BMP图片。注意看这句话:Response.ContentType = "image/BMP"

下一步的工作需要首先获取这个图片,然后才能OCR,到temporary internet files目录下,找到相应网站对应的文件,仔细查找这个图片,把它拖到“开始-》运行”对话框里可以看到在文件系统中的名字叫validatecode[1].bmp,多刷几次网页,以确认验证码就是这个图片。同时你也会发现这个图片的完整路径,

C:/documents and settings/user/local settings/temporary internet files/content.IE5/OU786VF/validatecode[1].bmp

需要注意的是,content.IE5下面的子目录名称是经常变化的,每刷新一次就会不同。给获取图片增加了一定难度。

但我们还是有办法,遍历content.IE5下的每个文件夹,包括文件,去搜索验证码图片,代码如下:

因为我刷新temporary internet files,因些不能用TIdHTTP组件,它没有表示层,必须使用TCppWebBrowser组件,

CppWebBrowser1->Navigate(WideString("http://192.168.0.3/login.asp"));

Navigate之后,验证码图片就会更新,于是用下面的程序获得该图片

//------------------------------------------------------------------------

TSearchRec sr;
String asFileName,extension;
extension="*.*";
String startpath="C://Documents and Settings//user//Local Settings//Temporary Internet Files//Content.IE5//";
if(!FindFirst(startpath+extension,faAnyFile,sr))
{
do
{
if (sr.Name != "." && sr.Name != "..")
asFileName=FileSearch("validatecode[1].bmp",startpath+sr.Name);
Memo1->Lines->Add(startpath+sr.Name);
if(!asFileName.IsEmpty())
Edit1->Text=OCR(startpath+sr.Name+".bmp",-1]//validatecode[1].bmp",-1);
//Memo1->Lines->Add(sr.Name);
}
while(!FindNext(sr));

}

FindClose(sr);

//---------------------------------------------------------------------------------------------------

把识别的结果存到Edit1里面。OCR(string,int)是一个OCR函数,来自aspriseOCR.dll的demo版。具体调用不再叙述。

然后把识别码信息写到你的Post信息里,用IdHTTP post出去。

TStringStream *ResponseData=new TStringStream("");
TStringList *PostData = new TStringList;
String URL="http://192.168.0.3/view.asp" ;
String PostStr;

PostStr="validatecode="+Edit1->Text;
PostData->Add(PostStr);
try
{
Form1->IdHTTP1->Post(URL,PostData,ResponseData) ;
Form1->Memo1->Clear();
Form1->Memo1->Text=ResponseData->DataString;
}
catch ( ... )
{
// handler for any C++ exception
ShowMessage( "A C++ exception was thrown.,由于网络原因程序中断");

}

//-------程序执行到此处已解决大部分问题,但post动作会新建一个session,(经常会get得到图片和要post的页面还不一致,如本例,get图片需要访问login.asp,却又需要post到view.asp) session变量会被刷新,导致与你OCR出来的验证码不一致,问题就出在这里,等等继续研究解答。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: