|
当然,基于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的系统,也会因为系统补丁导致类似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
|