sh3llc0de开发测试中dumpbin的使用
当然,基于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,如下:
CODE:
#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();
}
[Copy to clipboard]
这段代码我已经修改过了,在我的机器上运行是没问题的。用VC编译之后执行,会听到主板的“滴---”声,实际上是调用了kernel32.dll里的beep函数。
如代码中给出的:
"\x77\x7A\x83\x7C" //Address \x77\x7A\x83\x7C = SP2
这个代码在XP SP2下才会正常执行,而且就算是SP2的系统,也会因为系统补丁导致类似krnel32.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