一个旧的验证码破解程序[附源码]

***************图书推荐*************************************************************************************


21.7 元

26.9 元

38.3 元

23.9 元

71.3 元

16.6 元

*********************************************************************************************************************

来源:Sban .Net  http://www.cnblogs.com/sban/archive/2007/12/06/985038.html

验证码多URL演示破解-安装版.rar
这个是制作的安装版。用于演示用。
验证码多URL演示破解-源码(DotNet2).rar
这个便是上面安装版的源码。
这两个附件首发于博客园sban保证博客园的版本没有病毒,请勿在其它地址下载。

这个小软件,是我06年初的时候写的,时隔两年了。那时急用,也没考虑什么面向对象,设计模式,垃圾处理等,暇疵甚多。今天把它拿出来,旨在抛砖引玉,与大家共同探讨一下C#的图文识别。

演示中的验证码的URL有的已不能用。大部分验证码图像都简单,破解尚且容易。倘若能够破解google或yahoo的验证码,那才是高手。

    这是当时写的演示软件说明,其中有些话有些过了。

◇ 本软件为验证码破解示例软件. 纯绿色,可完全卸载,不含任何插件、恶意代码。
◇ 支持不同色彩,不同大小,不同个数,不同亮度. 
◇ 支持不同格式,不同形式,不同方法. 
◇ 由于是针对大众验证码的演示软件,准确率以及破解速度远不及针对单一验证码的破解. 
◇ 关于设置URI等参数的功能,由于对于不同的验证码参数是不定的,需要调试得出,所以没有列出. ◇ 凡是小软件,应力求功能简单,效率与实用性才能提高.一个无所不能的软件也就是一个什么也不能的软件.

    
    好了,且看源码。

    源码中有一个Access数据库[suncode06.mdb]。


    这个表用于存储验证码的地址及破解配置信息。其中,maxLt与minLt是躁点取舍范围。nCode是验证码的个数。


    如图所示,这个表便存储了验证码的图片信息。

    这个小软件破解验证码的原理,是记忆性破解。读取验证码图片,分成一个个小图片,如果库中有记录,则返回它的验证码字符;如果不存在,则插入新记录。对于没有记忆过的验证码图片,它是识别不出来的。这个破解方法只可用于验证码字符范围固定的验证码。对于不固定范围的,如QQ的注册验证则不能破解。

    
    其中,所有破解代码都在Form1中,form2可以不看。
    在Form1中,首先init读取当前要破解的验证码的url及破解参数:


    private void init(int id)
    
{
        textBox1.Enabled 
= false;
        button2.Enabled 
= false;

        
//
        cmdUncode.CommandText = "select * from [uri] where [id] = @id";
        cmdUncode.Connection 
= conUncode;
        cmdUncode.Parameters.Clear();

        cmdUncode.Parameters.Add(
"@id", OleDbType.Integer);
        cmdUncode.Parameters[
"@id"].Value = id;

        closeDtr();
        dtrUncode 
= cmdUncode.ExecuteReader();

        
if (dtrUncode.Read())
        
{
            uri 
= dtrUncode["uri"].ToString();
            nCode 
= Convert.ToInt16(dtrUncode["nCode"]);
            maxLight 
= Convert.ToDouble(dtrUncode["maxLt"]);
            minLight 
= Convert.ToDouble(dtrUncode["minLt"]);
            iEdge 
= Convert.ToInt16(dtrUncode["iEdge"]);
            compairLimit 
= Convert.ToInt16(dtrUncode["iLmt"]);
            remark 
= dtrUncode["remark"].ToString();
        }



        
//uriID = 5;
        
//uri = "http://customer.realname.alibaba.com.cn/cap_image.php";
        
//nCode = 5;
        
//maxLight = 0.85;
        
//minLight = 0.55;
        
//iEdge = 1;
        
//compairLimit = 12;
        
//remark = "http://customer.realname.alibaba.com.cn/newapply/newwhois.htm";



        linkLabel1.Text 
=  remark;
        dtrUncode.Close();

        
//
        X0 = new int[1 + nCode*2];
        Y0 
= new int[1 + nCode * 2];

        
//
        Bitmap0 = new Bitmap[3 + nCode];

        CharRlt 
= new Char[nCode];

        
for (int i = 0; i < nCode; i++)
        
{
            CharRlt[i] 
= ' ';
        }

        textBox1.Enabled 
= false;
        button2.Enabled 
= false;
    }

    当用户点击破解的时候,首先在 GetBitmapOriginal(ref Bitmap0[0])中取出原始图像:

    public Bitmap GetBitmapOriginal(ref Bitmap oriBmp)
    
{
        WebRequest webRqst 
= WebRequest.Create(uri);
        WebResponse webRpns 
= webRqst.GetResponse();

        Stream0 
= webRpns.GetResponseStream();
        oriBmp 
= new Bitmap(Stream0);

        
return oriBmp;
    }

    取出原始图像后,在 GetXYOfEightPoint()中取出验证码图像中每一个小图像的临界点,这将在下一步的裁图中用到:

    private bool GetXYOfEightPoint()
    
{
        
int m_countX = 1;
        
int m_countY = 1;


        
bool IsBound = false;
        
for (X0[0= 0; X0[0< Bitmap0[1].Size.Width; X0[0]++)
        
{
            IsBound 
= false;
            
for (Y0[0= 0; Y0[0< Bitmap0[1].Size.Height; Y0[0]++)
            
{
                
if (Bitmap0[1].GetPixel(X0[0], Y0[0]).GetBrightness() == 0)
                
{
                    IsBound 
= true;
                    
continue;
                }

            }


            
if (m_countX <= nCode*2)
            
{
                
if ((m_countX % 2== 0)
                
{
                    
if (!IsBound)
                    
{
                        X0[m_countX] 
= X0[0- 1;
                        m_countX
++;
                    }


                }

                
else
                
{
                    
if (IsBound)
                    
{
                        X0[m_countX] 
= X0[0];
                        m_countX
++;
                    }


                }

            }

            
//


            
        }



        
if (m_countX < nCode*2)
        
{
            
//label1.Text = m_countX.ToString();
            return false;
        }


        
//

        
for (Y0[0]=0; Y0[0]<(nCode*2); Y0[0]++)
        
{
            
if ((Y0[0]%2== 0)
            
{
                Y0[Y0[
0+ 1= Bitmap0[1].Size.Height;
            }

            
else
            
{
                Y0[Y0[
0+ 1= 0;
            }

        }


        
//

        
for (Y0[0= 0; Y0[0< Bitmap0[1].Size.Height; Y0[0]++)
        
{
            
//
            for (int i = 0; i < nCode * 2; i = i + 2)
            
{
                
//
                for (X0[0= X0[i + 1]; X0[0< X0[i + 2]; X0[0]++)
                
{
                    
if (Bitmap0[1].GetPixel(X0[0], Y0[0]).GetBrightness() == 0)
                    
{
                        
if (Y0[i + 1> Y0[0]) Y0[i + 1= Y0[0];
                        
if (Y0[i + 2< Y0[0]) Y0[i + 2= Y0[0];
                        m_countY
++;
                    }

                }

                
//

            }


        }


        
if (m_countY < nCode*2)
        
{
            
return false;
        }

        
return true;

    }


    这时候这个图像还是有躁点的,在裁图之前,必须把躁点去掉。这一步在 GetBlankWhiteBitmap()中完成:

    private Bitmap GetBlankWhiteBitmap()
    
{
        
int m_w, m_h;
        Color m_clr 
= new Color();
        m_w 
= Bitmap0[0].Size.Width;
        m_h 
= Bitmap0[0].Size.Height;

        
if (m_w > Bitmap0[0].Size.Width) m_w--;
        
if (m_h > Bitmap0[0].Size.Height) m_h--;

        Rectangle0 
= new Rectangle(new Point(00), new Size(m_w - iEdge, m_h - iEdge));

        Bitmap0[
1= Bitmap0[0].Clone(Rectangle0, PixelFormat0);
        
for (X0[0= 0; X0[0< Bitmap0[1].Size.Width; X0[0]++)
        
{
            
for (Y0[0= 0; Y0[0< Bitmap0[1].Size.Height; Y0[0]++)
            
{
                m_clr 
= Bitmap0[1].GetPixel(X0[0], Y0[0]);

                
if (m_clr.GetBrightness() <= minLight || m_clr.GetBrightness() >= maxLight)
                
{
                    Bitmap0[
1].SetPixel(X0[0], Y0[0], Color.White);
                }

                
else
                
{
                    Bitmap0[
1].SetPixel(X0[0], Y0[0], Color.Black);
                }

            }

        }


        
return Bitmap0[1];
    }

    
随后在 GetSngBmp ()中拆出一个个小图像。有了临界点,又去了躁点,拆图已是相当容易。

    private void GetSngBmp()
    
{
        
for (int i = 0; i < nCode; i++)
        
{
            Rectangle0 
= new Rectangle(X0[i * 2 + 1], Y0[i * 2 + 1], X0[(i + 1* 2- X0[i * 2 + 1+ 1, Y0[(i + 1* 2- Y0[i * 2 + 1+ 1);
            Bitmap0[
3 + i] = Bitmap0[1].Clone(Rectangle0, PixelFormat0);
        }

    }


    最后在GetCharRlt()计算验证码字符,如果库中没有,则提示输入并存储,并进入下一个验证码字符破解。


    public void GetCharRlt()
    
{
        
bool blnFinish = false;
        
bool HaveThisBitmap = false;
        
string m_codes = "";

        
if(DtSCode.Tables[uriID.ToString()] == null){

            StrSql 
= "select * from [" + uriID.ToString() + "Code" + "]";

            cmdUncode.CommandText 
= StrSql;
            cmdUncode.Connection 
= conUncode;

            dadUncode.SelectCommand 
= cmdUncode;


            dadUncode.Fill(DtSCode, uriID.ToString());
        }

        
        
for (int I=0; I<nCode; I++)
        
{
            
if (CharRlt[I].ToString() == " ")
            
{
                HaveThisBitmap 
= false;
                
foreach(DataTable DT in DtSCode.Tables){
                    
foreach (DataRow DR in DT.Rows)
                    
{

                        MemoryStream0 
= new MemoryStream();
                        MemoryStream0.Position 
= 0;
                        MemoryStream0 
= new MemoryStream((byte[])DR["img"]);
                        Bitmap0[
2= new Bitmap(MemoryStream0);


                        
if (CompareBitmap(Bitmap0[I + 3], Bitmap0[2]))
                        
{
                            HaveThisBitmap 
= true;
                            CharRlt[I] 
= Convert.ToChar(DR["chr"]);
                            
continue;
                        }

                    }

                    
if (HaveThisBitmap)
                    
{
                        
continue;
                    }

                }

                
//
                
//
                
//
                if (HaveThisBitmap)
                
{
                    textBox1.Enabled 
= false;
                    button2.Enabled 
= false;
                    
                }

                
else
                
{
                    MessageBox.Show(
"Input a char correspond to " + (I + 1).ToString() + " code");
                    label1.Text 
= "Input a char correspond to " + (I + 1).ToString() + " code";
                    textBox1.Enabled 
= true;
                    button2.Enabled 
= true;
                    textBox1.Focus();
                    I 
= nCode + 1;
                    
break;
                }

            }


        }


        blnFinish 
= true;
        
for (int m_fi = 0; m_fi < nCode; m_fi++)
        
{
            
if (CharRlt[m_fi].ToString() == " ")
            
{
                blnFinish 
= false;
                
break;
            }


        }

        
if (blnFinish)
        
{
            
for (int i = 0; i < nCode; i++)
            
{
                m_codes 
+= CharRlt[i].ToString();
            }

            MessageBox.Show(m_codes, 
"code");
            label1.Text 
= "The codes is " + m_codes;
            button1.Enabled 
= true;
            button1.Focus();
        }


    }


    代码质量不高,坏味实足,各位多多包涵。
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值