通用ShellCode深入剖析前言:
在网上关于ShellCode编写技术的文章已经非常之多,什么理由让我再写这种技术文
章呢?本文是我上一篇溢出技术文章<Windows 2000缓冲区溢出技术原理>的姊妹篇,同样
的在网上我们经常可以看到一些关于ShelCode编写技术的文章,似乎没有为初学者准备的
,在这里我将站在初学者的角度对通用ShellCode进行比较详细的分析,有了上一篇的溢出
理论和本篇的通用ShellCode理论,基本上我们就可以根据一些公布的Window溢出漏洞或
是自己对一些软件系统进行反汇编分析出的溢出漏洞试着编写一些溢出攻击测试程序.
文章首先简单分析了PE文件格式及PE引出表,并给出了一个例程,演示了如何根据PE
相关技术查找引出函数及其地址,随后分析了一种比较通用的获得Kernel32基址的方法,
最后结合理论进行简单的应用,给出了一个通用ShellCode.
本文同样结合我学习时的理解以比较容易理解的方式进行描述,但由于ShellCode的
复杂性,文章主要使用C和Asm来讲解,作者假设你已具有一定的C/Asm混合编程基础以及上
一篇的溢出理论基础,希望本文能让和我一样初学溢出技术的朋友有所提高.
[目录]
1,PE文件结构的简介,及PE引出表的分析.
1.1 PE文件简介
1.2 引出表分析
1.3 使用内联汇编写一个通用的根据DLL基址获得引出函数地址的实用函数
GetFunctionByName
2,通用Kernel32.DLL地址的获得方法.
2.1 结构化异常处理和TEB简介
2.2 使用内联汇编写一个通用的获得Kernel32.DLL函数基址的实用函数
GetKernel32
3,综合运用(一个简单的通用ShellCode)
3.1 综合前面所讲解的技术编写一个添加帐号及开启Telnet的简单ShellCode:
根据第2节所述技术使用我们自己实现的GetFunctionByName获得LoadLibraryA和
GetProcAddress函数地址,再使用这两个函数引入所有我们需要的函数实现期望的
功能.
4,参考资料.
5,关键字.
--------------------------------------------------------------------------------
一,PE文件结构及引出表基础
1,PE文件结构简介
PE(Portable Executable,移植的执行体),是微软Win32环境可执行文件的标准格式
(所谓可执行文件不光是.EXE文件,还包括.DLL/.VXD/.SYS/.VDM等)
PE文件结构(简化):
-----------------
│1,DOS MZ header│
-----------------
│2,DOS stub │
-----------------
│3,PE header │
-----------------
│4,Section table│
-----------------
│5,Section 1 │
-----------------
│6,Section 2 │
-----------------
│ Section ... │
-----------------
│n,Section n │
-----------------
记得在我还没有接确Win32编程时,我曾在Dos下运行过一个Win32可执行文件,程序只输出
了一行"This program cannot be run in DOS mode.",我觉得很有意思,它是怎么识别自
己不在Win32平台下的呢?其实它并没有进行识别,它可能简单到只输入这一行文字就退出
了,可能源码就像下面的C程序这么简单:
#include <stdio.h>
void main(void)
{
printf("This program cannot be run in DOS mode.n");
}
你可能会问"我在写Win32程序时并没有写过这样的语句啊?",其实这是由连接器(linker)
为你构建的一个16位DOS程序,当在16位系统(DOS/Windows 3.x)下运行Win32程序时它才会
被执行用来输出一串字符提示用户"这个程序不能在DOS模式下运行".
我们先来看看DOS MZ header到底是什么东西,下面是它在Winnt.h中的结构描述:
typedef struct _IMAGE_DOS_HEADER { //DOS .EXE header
WORD e_magic; //0x00 Magic number
WORD e_cblp; //0x02 Bytes on last page of file
WORD e_cp; //0x04 Pages in file
WORD e_crlc; //0x06 Relocations
WORD e_cparhdr; //0x08 Size of header in paragraphs
WORD e_minalloc; //0x0a Minimum extra paragraphs needed
WORD e_maxalloc; //0x0c Maximum extra paragraphs needed
WORD e_ss; //0x0e Initial (relative) SS value
WORD e_sp; //0x10 Initial SP value
WORD e_csum; //0x12 Checksum
WORD e_ip; //0x14 Initial IP value
WORD e_cs; //0x16 Initial (relative) CS value
WORD e_lfarlc; //0x18 File address of relocation table
WORD e_ovno; //0x1a Overlay number
WORD e_res[4]; //0x1c Reserved words
WORD e_oemid; //0x24 OEM identifier (for e_oeminfo)
WORD e_oeminfo; //0x26 OEM information; e_oemid specific
WORD e_res2[10]; //0x28 Reserved words
LONG e_lfanew; //0x3c File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
DOS MZ header中包括了一些16位DOS程序的初使化值如果IP(指令指针),cs(代码段寄存
器),需要分配的内存大小,checksum(校验和)等,当DOS准备为可执行文件建立进程时会读取其
中的值来完成初使化工作.
留意到最后一个结构成员了吗?微软的人对它的描述是File address of new exe header
意义是"新的exe文件头部地址",它是一个相对偏移值,我想文件偏移量你一定知道是什么吧!
e_lfanew就是一个文件偏移值,它指向PE header,它对我们来说非常重要.紧跟着DOS MZ header
的是DOS stub它是linker为我们建立的这个16位DOS程序的代码实体部分,就是它输出了
"This program cannot be run in


















