*[作者]:gz1X <gz1x(at)tom(dot)com>
*[来自]:中国黑客联盟
当然,基于MSF(Metasploit Framework)的shellcode开发简单的已经几乎用不着你自己去了解编程上的东西(细节请参考本人编写的MSF中文手册),但是对于初学而又喜欢探索底层的人来说,自己动手编程也是件不错的事情。嗯...本文面向像我一样在系统探索上的初学者,如果您是这方面的高手,这篇文章让您见笑了。
首先,了解一下dumpbin。
这个工具在微软的几乎所有的tool kits里都有,像VS,MASM...
在VS里没找到dumpbin?好吧,把路径切换到../WINDOWS/System32/,尝试以下命令:
link.exe /dump /headers /exports kernel32.dll >E:/log
记事本打开E盘下的log文件,看到了什么...实际效果和:
dumpbin /headers /exports kernel32.dll >E:/log
是一样的。
稍微解释一下dumpbin的参数.
把dumpbin放进一个环境变量指向的路径里(方便随时随地启动dumpbin),命令行输入dumpbin:
Microsoft (R) COFF Binary File Dumper Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
usage: DUMPBIN [options] [files]
options:
/ALL
/ARCH
/ARCHIVEMEMBERS
/DEPENDENTS
/DIRECTIVES
/DISASM
/EXPORTS
/FPO
/HEADERS
/IMPORTS
/LINENUMBERS
/LINKERMEMBER[:{1|2}]
/LOADCONFIG
/OUT:filename
/PDATA
/RAWDATA[:{NONE|BYTES|SHORTS|LONGS}[,#]]
/RELOCATIONS
/SECTION:name
/SUMMARY
/SYMBOLS
挑我们需要的,/HEADERS,/EXPORTS,/OUT,其他的参数可以参考微软的MSDN,地址如下:
http://msdn2.microsoft.com/zh-cn/library/c1h23y6c(VS.80).aspx
/HEADERS显示文件头和每节的头,这里有个比较重要的信息就是文件在内存中的加载地址,也就是OPTIONAL HEADER VALUES里的Image Base;/EXPORTS显示从可执行文件或 DLL 导出的所有定义,这里我们需要的是函数的相对偏移地址;/OUT指定输出的 filename。默认情况下,DUMPBIN 将信息显示到标准输出(DOS窗口中),一般我不太喜欢用这个参数,我用管道>代替,而且如果是追加信息的话可以用>>。
然后,我们实际运用一把,随便到网上抓个shellcode,如下:
#include <stdio.h>
unsigned char beepsp[] =
"/x55/x89/xE5/x83/xEC/x18/xC7/x45/xFC"
"/x77/x7A/x83/x7C" //Address /x77/x7A/x83/x7C = SP2
"/xC7/x44/x24/x04"
"/xD0/x03" //Length /xD0/x03 = 2000 (2 seconds)
"/x00/x00/xC7/x04/x24"
"/x01/x0E" //Frequency /x01/x0E = 3585
"/x00/x00/x8B/x45/xFC/xFF/xD0/xC9/xC3";
int main()
{
void (*function)();
*(long*)&function = (long)beepsp;
function();
}
这段代码我已经修改过了,在我的机器上运行是没问题的。用VC编译之后执行,会听到主板的“滴---”声,实际上是调用了kernel32.dll里的beep函数。
如代码中给出的:
"/x77/x7A/x83/x7C" //Address /x77/x7A/x83/x7C = SP2
这个代码在XP SP2下才会正常执行,而且就算是SP2的系统,也会因为系统补丁导致类似kernel32.dll等这些系统dll在内存中的加载地址的不同,这样Address /x77/x7A/x83/x7C (实际上是7C837A77,注意小端排列)也就指向了错误的地方。
那么,怎么取得自己机器上的合理地址呢?
首先,用dumpbin取得dll的加载地址,比如要引用kernel32.dll中的beep函数,我们需要先得到kernel32.dll在本机内存中的加载地址,方法如下:
C:/Documents and Settings/Administrator>cd C:/WINDOWS/System32
C:/WINDOWS/system32>dumpbin /headers kernel32.dll > E:/log.txt
打开log.txt,找到如下信息:
OPTIONAL HEADER VALUES
7C800000 image base
这里,7C800000就是kernel32.dll的本机加载地址。
知道了基址,我们就要查找beep函数在kernel32.dll内存映射的什么地方,方法如下:
C:/WINDOWS/system32>dumpbin /exports kernel32.dll >> E:/log.txt
我们在Dump of file kernel32.dll里查找函数beep:
28 1B 00019805 BasepCheckWinSaferRestrictions
29 1C 00037A77 Beep
30 1D 0006FC7B BeginUpdateResourceA
其中,00037A77就是beep函数相对于基址的偏移地址,我们把两个地址相加,即得到beep函数在内存中的真实地址:
7C800000 + 00037A77 =7C837A77
以小端排列,得到:/x77/x7A/x83/x7C
这样在shellcode里修改:
"/x77/x7A/x83/x7C" //Address /x77/x7A/x83/x7C = SP2
即可正常运行测试程序。
思路就这样简单,如果是kernel基址的通用获取,就需要其他技术了,超出本文范围,不做讨论。
Have Fun!
附:
1.kernel32.dll
C:/WINDOWS/system32>dumpbin /headers /exports kernel32.dll > E:/kernel_log.txt
2.ntdll.dll
C:/WINDOWS/system32>dumpbin /headers /exports ntdll.dll > E:/ntdll_log.txt
3.msvcrt.dll
C:/WINDOWS/system32>dumpbin /headers /exports msvcrt.dll > E:/msvcrt_log.txt
4.ws2_32.dll (网络编程)
C:/WINDOWS/system32>dumpbin /headers /exports ws2_32.dll > E:/ws2_log.txt