从海量PE样本中挖掘伪造图标类恶意程序

大家好,我本次分享的内容是从海量PE样本中挖掘伪造图标类恶意程序。

众所周知,很多恶意程序会将自己的图标伪装成常见的word图标、文件夹图标以及一些常用程序的图标。比如文件夹exe病毒会伪装成文件夹图标,以及最近一段时间爆发的WannaRen 勒索病毒就会释放出everything软件的图标来迷惑用户去点击。所以,我就萌发了从海量PE样本中提取图标来挖掘伪造图标类恶意程序的想法。

对于单个PE样本,很容易提取其图标,一种常见的方法就是使用Resource Hacker。但对于大量的样本,我们应该怎么提取呢?

对于使用Python的研究人员来讲,有多种方法可以用来提取PE文件的图标。

第一种方法是使用windows提供的API函数,ExtractIconEx函数可以从exe、dll PE文件中获得图标的句柄,拿到PE文件的图标句柄后,使用GetDC函数,该函数可以获得指定窗口或整个屏幕显示设备上下文(Divice Context,DC)的句柄,实现截图画图,并将其保存为bmp位图。在Python中,我们可以通过调用win32gui中的ExtractIconEx方法(需要安装pywin32)提取图标,然后使用win32ui模块中GetDC相关的截图画图函数生成图片。

代码如下:

import win32ui
import win32gui
def main():
    large, small = win32gui.ExtractIconEx("tests\WeChat.exe",0)
    win32gui.DestroyIcon(small[0])
    hdc = win32ui.CreateDCFromHandle( win32gui.GetDC(0) )
    hbmp = win32ui.CreateBitmap()
    hbmp.CreateCompatibleBitmap( hdc, 32, 32 )
    hdc = hdc.CreateCompatibleDC()
    hdc.SelectObject( hbmp )
    hdc.DrawIcon( (0,0), large[0] )
    hbmp.SaveBitmapFile( hdc, "save.bmp"if __name__ == '__main__':
    main()

其中,因为ExtractIconEx函数返回一个大图标(3232)和一个小图标(3232)的句柄,我们只需要大图标的句柄,所以需要将小图标进行销毁。CreateDCFromHandle从句柄中得到设备上下文,之后,创建32*32大小的兼容位图,再将兼容位图句柄设置到兼容内存设备DC上,然后绘图并保存为save.bmp。

若想保存为png等格式,可以在调用ExtractIconEx后,使用PyQt,将其保存为png图片格式。

这个方法方便简单,但是存在一个缺点,就是ExtractIconEx方法仅仅返回3232和1616的大小两个图标的句柄。然而很多时候PE样本的图标并不仅仅是这两个大小,所以需要一个更好的方法来提取更多的图标。

另外一个方法是使用一些开源的项目,比如https://github.com/firodj/extract-icon-py,该项目基于Python的pefile模块,之后再使用pillow模块进行画图,保存为png格式。其中用到的pefile模块是Python中专门用来解析PE文件的库。该模块的功能十分强大,我们有必要对其进行了解。首先通过一个demo来了解一下使用方法:

import pefile
PEfile_Path = r"C:\test.exe"
pe = pefile.PE(PEfile_Path)

for importeddll in pe.DIRECTORY_ENTRY_IMPORT:
print importeddll.dll

即可输出该PE文件的导入表。关于PE文件格式的更多内容请参阅《windows PE权威指南》。

通过上述方法我们可以成功获取到PE文件的图标,那么我们怎么知道它是不是伪装成一些常见软件的图标呢?我们通过肉眼很容易分辨他是不是伪装成常用软件的图标了,但对于程序来说,可能就没那么容易了。通过分析我们人的思维过程:首先我们已经熟知了一些常见软件的图标,然后再与当前PE文件的图标进行对比,如果两者十分相似就认为当前PE文件是伪装成了常用软件的图标。与之类比,我们的程序也分为两个步骤,

第一步,提取并存储一些常见软件的图标。

第二步,将当前PE文件的图标与常见软件图标进行相似度对比,如果相似度较高,则认为当前PE文件伪装成了常用软件的图标。

首先,我们开始提取并存储一些常见软件的图标,最常见的图标是windows系统自带的图标,这些图标我们应该怎么获取呢?这些图标全部都存在一个文件中,那就是shell32.dll,所以我们只需要将这个dll文件的所有图标提出来即可获得系统自带的图标。之后可再自行搜集一些可能会被伪装的软件图标。

第二步,将两个图片进行对比,计算两者的相似度。有很多算法可以计算两者相似度,网上也有很多教程,这里我们采用将图像的相似度计算转化为直方图的距离计算的算法:

from PIL import Image

# 转换图片的大小,并使用convert()方法将其转为RGB颜色模式,
# 常见的modes 有 “L” (luminance) 表示灰度图像, “RGB” 表示真彩色图像, and “CMYK” 表示出版图像。

def make_regalur_image(img, size = (64, 64)):

return img.resize(size).convert('RGB')

def hist_similar(lh, rh):

assert len(lh) == len(rh)

print sum(1 - (0 if l == r else float(abs(l - r))/max(l, r)) for l, r in zip(lh, rh))/len(lh)

def calc_similar(li, ri):
return hist_similar(li.histogram(), ri.histogram())

def calc_similar_by_path(lf, rf):
li, ri = make_regalur_image(Image.open(lf)), make_regalur_image(Image.open(rf))
return calc_similar(li, ri)

if __name__ == '__main__':
    calc_similar_by_path('1.JPG','2.JPG')

首先,我们有必要把所有的图片都统一到特别的规格,在这里我选择是的64*64的分辨率,之后计算两者直方图的距离。具体的原理可查阅参考文献4。

通过这种方式我们即可得到两个图标的相似度,经过小规模测试,假如一个PE文件图标伪装成了常用软件的图标,两者相似度为100%。

经过测试,这种方法的速度不够快,因为涉及大量的IO操作,所以,为了能够大批量提取样本,对于这种IO密集型的操作,非常适合采用多线程的方法。通过使用Python的threading模块和Queue模块即可完成此任务,同时,我们通过使用生产者消费者模型,利用生产者不断的生成要提取的PE文件路径,将其放入队列中,使用消费者从队列中不断的取出PE文件路径,再利用上述方法提取图标,计算相似度,进而实现多线程加速。

参考资料:

msdn文档

windows黑客编程技术详解

https://www.codeproject.com/Articles/9303/Get-icons-from-Exe-or-DLL-the-PE-way

https://blog.csdn.net/gumanren/article/details/83810210

https://blog.csdn.net/gzlaiyonghao/article/details/2325027?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-9&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-9

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值