Windows栈溢出利用
常见提权方法

常见提权方法1. 用户提权:用户提权是指普通用户通过某种方式获取管理员权限或超级用户权限的行为。
常见的用户提权方法包括:利用弱密码、使用系统漏洞、利用特权提升程序等。
详细描述:用户提权是黑客经常使用的一种手段,通过获取管理员权限,黑客可以执行更高级别的操作,如修改系统配置、访问敏感文件等。
利用弱密码是最常见的用户提权方法之一。
黑客可以使用密码破解工具或暴力破解技术尝试猜解用户密码,一旦成功登录系统,就可以获取管理员权限。
系统漏洞也是用户提权的常见方法之一。
黑客可以通过渗透测试或漏洞扫描等方式发现系统中的漏洞,然后利用这些漏洞获取管理员权限。
某个系统可能存在一个未修补的漏洞,黑客可以利用这个漏洞上传特制的脚本,从而获得系统的控制权。
黑客还可以利用特权提升程序来提权。
这些程序的功能是在受限的用户权限下执行特权操作,如创建新用户、修改用户组等。
黑客可以通过执行这些特权提升程序来获取管理员权限,从而获得系统的完全控制权。
2. 命令注入:命令注入是指黑客通过在输入框或URL参数中注入恶意命令,从而执行非授权的操作。
常见的命令注入方法包括:通过修改URL参数、利用操作系统命令执行漏洞等。
详细描述:命令注入是一种常见的网络攻击手法,黑客通过在输入框或URL参数中注入恶意命令,从而执行非授权的操作。
黑客可以在一个搜索框中输入特定的字符串,以执行系统命令,或是通过改变URL参数来获取系统权限。
命令注入通常利用了操作系统的命令执行漏洞。
当用户传递的输入被直接用于构造系统命令时,如果没有正确进行输入验证和过滤,黑客就可以通过构造恶意输入来执行非授权的操作。
这种攻击方式在许多Web应用程序中非常常见,如论坛、博客等。
为了防止命令注入攻击,开发者应该始终对用户输入进行适当的验证和过滤。
可以使用特定的字符过滤器来禁止或转义危险的字符,或是通过使用参数化查询和预编译语句等方式防止SQL注入。
3. 文件包含漏洞:文件包含漏洞是指黑客通过利用应用程序中的文件包含功能来执行恶意代码。
堆栈溢出攻击原理

堆栈溢出攻击原理eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU 上的通用寄存器的名称,是32位的寄存器。
如果用C语言来解释,可以把这些寄存器当作变量看待。
比方说:add eax,-2 ; //可以认为是给变量eax加上-2这样的一个值。
这些32位寄存器有多种用途,但每一个都有“专长”,有各自的特别之处。
EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。
EBX是"基地址"(base)寄存器, 在内存寻址时存放基地址。
ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
EDX则总是被用来放整数除法产生的余数。
ESI/EDI分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码:push ebp ;保存当前ebpmov ebp,esp ;EBP设为当前堆栈指针sub esp, xxx ;预留xxx字节给函数临时变量....这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作mov esp,ebp/pop ebp/ret 即可.ESP专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。
在32位平台上,ESP每次减少4字节。
esp:寄存器存放当前线程的栈顶指针ebp:寄存器存放当前线程的栈底指针eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。
栈溢出利用

栈溢出利用
栈溢出是一种常见的计算机安全漏洞。
当程序执行时向栈中不断压入数据,如果数据过多、过大,超出了栈的存储空间,就会导致栈溢出。
攻击者可以利用栈溢出漏洞,向栈中注入恶意代码,从而控制程序的执行流程,达到攻击的目的。
具体来说,攻击者可以构造一段特定的输入,向程序输入这段输入后,就会导致栈溢出。
然后,攻击者可以通过注入恶意代码,改变程序原本的行为,或者执行攻击者想要的操作,比如获取敏感信息、提权等操作。
为了防止栈溢出攻击,程序员可以采取一些措施,比如使用编译器提供的一些安全选项,使用安全的编程方法,避免使用不安全的函数等。
缓冲区溢出保护机制——Windows

缓冲区溢出保护机制——Windows缓冲区溢出保护机制WindowsGS安全编译选项Visual Studio 2003及以后版本的Visual Studio中默认启⽤了这个安全编译选项。
GS编译选项为每个函数增加了⼀些额外的数据和操作:1、在所有函数调⽤发⽣时,向栈帧内压⼊⼀个额外的随机DWORD,这个随机数被称作“canary”,⽤IDA反汇编时,⼜被称作“Security Cookie”。
2、canary位于EBP之前,系统还会在.data的内存区域中存放⼀个canary的副本。
3、当栈中发⽣溢出时,canary将被⾸先淹没,之后才是EBP和返回地址。
4、在函数返回之前,系统将执⾏⼀个额外的安全验证操作,称作Security Check。
5、在Security Check过程中,系统将⽐较栈帧中原先存放的canary和.data中副本的值,若两者不同,则说明栈中发⽣了溢出,系统将进⼊异常处理流程,函数不会正常返回。
canary产⽣的细节:系统以.data节的第⼀个双字作为Cookie的种⼦,或称为原始Cookie。
在程序每次运⾏时Cookie的种⼦都不相同,具有很强的随机性在栈帧初始化以后系统⽤ESP异或种⼦,作为当前函数的Cookie,以此作为不同函数的区别,并增强Cookie的随机性在函数返回前,⽤ESP还原出Cookie种⼦分析Security Cookie具有很强的随机性,在函数运⾏时猜解⼏乎是不可能的。
但是,额外的数据和操作造成了系统性能的下降,为了将对性能的影响降到最⼩,编译器在编译程序的时候并不是对所有的函数都应⽤GS,以下情况不会应⽤GS:函数不包含缓冲区函数被定义为具有变量参数列表函数使⽤⽆保护的关键字标记函数在第⼀个语句中包含内嵌汇编代码缓冲区不是8字节类型且⼤⼩不⼤于4个字节绕过GS1、利⽤未保护内存可通过缓冲区不⼤于4字节的栈溢出直接绕过GS。
2、覆盖虚函数程序只有在函数返回时才去检查canary,在此之前并没有任何措施,所以我们可以利⽤C++虚函数在程序检查canary之前劫持程序流程。
实验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),其它项按默认配置进行。
初学Windows堆栈溢出

逆向分析可以知道,程序给缓冲区分配了16字节,也就是说,我们发送1234567812345678那么程序就正常返回。因为堆栈是四字节对集,所以我们发送20字符,ebp将会被覆盖,比如我们在1234567812345678后面加上AAaa,那么执行后,EBP将被溢出覆盖为61614141。现在来看一下是否真的EBP的值被改写:
Copycode
sub_401053 procnear ;CODEXREF:_main+E7
.text:00401053
.text:00401053var_10 =byteptr-10h
.text:00401053arg_0 =dwordptr8;strcpy函数接收字符的缓冲区参数
正如图所示,EBP已经被我们更改。这个时候,我们要做的,就在再多发送4个字符,让溢出的数据覆盖EIP。覆盖EIP有什么用?首先要知道EIP指向下一条要执行的指令的地址。也就是说,我们改写了EIP,比如发送1234567812345678AAaa1234,那么,EIP讲会被改写成0x34333231.如图:
mov@stAddr.sin_addr,eax
mov @stAddr.sin_family,AF_INET;设置IP格式
invokebind,hSocket,addr@stAddr,sizeof@stAddr;绑定这个套接字
invoke connect,hSocket,addr@stAddr,sizeof@stAddr;根据套接字信息连接服务器
db0FFH,0D0H
.data?
hSocketSOCKET ?
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
堆栈溢出

标题: 堆栈溢出系列讲座(1)本文以及以下同系列各文为ipxodi根据alphe one, Taeho Oh 的英文资料所译及整理,你可以任意复制和分发。
序言:通过堆栈溢出来获得root权限是目前使用的相当普遍的一项黑客技术。
事实上这是一个黑客在系统本地已经拥有了一个基本账号后的首选攻击方式。
他也被广泛应用于远程攻击。
通过对daemon进程的堆栈溢出来实现远程获得rootshell的技术,已经被很多实例实现。
在windows系统中,同样存在着堆栈溢出的问题。
而且,随着internet的普及,win系列平台上的internet服务程序越来越多,低水平的win程序就成为你系统上的致命伤。
因为它们同样会被远程堆栈溢出,而且,由于win系统使用者和管理者普遍缺乏安全防范的意识,一台win系统上的堆栈溢出,如果被恶意利用,将导致整个机器被敌人所控制。
进而,可能导致整个局域网落入敌人之手。
本系列讲座将系统的介绍堆栈溢出的机制,原理,应用,以及防范的措施。
希望通过我的讲座,大家可以了解和掌握这项技术。
而且,会自己去寻找堆栈溢出漏洞,以提高系统安全。
堆栈溢出系列讲座入门篇本讲的预备知识:首先你应该了解intel汇编语言,熟悉寄存器的组成和功能。
你必须有堆栈和存储分配方面的基础知识,有关这方面的计算机书籍很多,我将只是简单阐述原理,着重在应用。
其次,你应该了解linux,本讲中我们的例子将在linux上开发。
1:首先复习一下基础知识。
从物理上讲,堆栈是就是一段连续分配的内存空间。
在一个程序中,会声明各种变量。
静态全局变量是位于数据段并且在程序开始运行的时候被加载。
而程序的动态的局部变量则分配在堆栈里面。
从操作上来讲,堆栈是一个先入后出的队列。
他的生长方向与内存的生长方向正好相反。
我们规定内存的生长方向为向上,则栈的生长方向为向下。
压栈的操作push=ESP-4,出栈的操作是pop=ESP+4.换句话说,堆栈中老的值,其内存地址,反而比新的值要大。
栈溢出stackoverflow的原因及解决办法

栈溢出stackoverflow的原因及解决办法栈溢出(stackoverflow)的原因及解决办法作者:不要以为你赢了最近在做⼀个程序(VC6.0),功能⼤概有⽹络通信、数据库、绘图等。
测试的时候程序⼀运⾏到某个函数就出现此错误,查了很多地⽅,试了很多解决办法,终于把问题解决了,写个⽇志提醒⼀下⾃⼰,也希望作为⼀个普遍解决办法让⼤家少费⼯夫(其他编译器也会出现同样的问题)。
⼤家都知道,Windows程序的内存机制⼤概是这样的,全局变量(局部的静态变量本质也属于此范围)存储于堆内存,该段内存较⼤,⼀般不会溢出;函数地址、函数参数、局部变量等信息存储于栈内存,VC6中栈内存默认⼤⼩为1M,对于当前⽇益扩⼤的程序规模⽽⾔,稍有不慎就可能出问题。
(动态申请的内存即new出来的内存不在栈中)即如果函数这样写:voidtest_stack_overflow(){char*chdata=new[2*1024*1024];delete[]chdata;}是不会出现这个错误的,⽽这样写则不⾏:voidtest_stack_overflow(){charchdata[2*1024*1024];}⼤多数情况下都会出现内存溢出的错误,不信在vc6中随便做个程序,调⽤⼀下这个函数试式。
出现栈内存溢出的常见原因有2个:1>函数调⽤层次过深,每调⽤⼀次,函数的参数、局部变量等信息就压⼀次栈。
2>局部静态变量体积太⼤第⼀种情况不太常见,因为很多情况下我们都⽤其他⽅法来代替递归调⽤(反正我是这么做的),所以只要不出现⽆限制的调⽤都应该是没有问题的,起码深度⼏⼗层我想是没问题的,这个我没试过但我想没有谁会把调⽤深度作那么多。
检查是否是此原因的⽅法为,在引起溢出的那个函数处设⼀个断点,然后执⾏程序使其停在断点处,然后按下快捷键Alt+7调出callstack窗⼝,在窗⼝中可以看到函数调⽤的层次关系。
第⼆种情况⽐较常见了,我就是犯了这个错误,我在函数⾥定义了⼀个局部变量,是⼀个类对象,该类中有⼀个⼤数组,⼤概是1.5M。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Windows 栈溢出分析摘要众所周知,缓冲区溢出是目前最为常见的漏洞利用方式,特别是栈溢出,原理简单,危害大。
在Windows xp sp2以后,微软增加了许多安全检查措施来杜绝缓冲区溢出的发生。
本文介绍两种Windows xp下两种常见的栈溢出利用方式,重点分析利用S.E.H进行栈溢出,并且归纳总结防范和检测方法。
第一章绪论1.1 栈溢出定义程序的局部变量一般都存放在栈空间内,如果用户输入的数据超过了定义的长度,就会非法覆盖栈空间的其他数据,这种现象就是栈溢出。
1.2栈溢出普通利用方式1.2.1 利用函数返回点函数调用约定描述了函数传递参数方式和栈协同工作的技术细节。
不同的操作系统,不同的语言,不同的编译器在实现函数调用时的原理虽然基本相同,但具体的调用约定还是有差别的,包括参数传递方式,参数入栈顺序是从右向左还是从左向右,函数返回时候恢复堆栈平衡的操作在子函数进行还是在母函数中进行。
下表列出了几种调用方式。
对于Visual C++,可支持以下三种函数调用约定,如下表默认情况下,VC使用_stdcall的调用方式。
本文以下讨论如不另加说明,即指这种默认的调用方式。
函数调用大致包括以下几个步骤:(1)参数入栈:将参数从右向左依次压入系统栈中;(2)返回地址入栈:将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行;(3)代码区跳转:处理器从当前代码区跳转到被调函数的入口地址;(4)栈帧调整,包括保存当前栈帧状态值,已备后面恢复本栈帧时使用。
将当前栈帧切换到新栈帧。
给新栈帧分配空间。
对于_stdcall调用约定,函数调用时用到的汇编指令序列如下:Push 参数;从右至左Call 函数地址;Push ebp;Mov ebp,esp;Sub esp ,xxx;类似地,函数返回的步骤如下:(1)保存返回值:通常将函数的返回值保存在Eax;(2)弹出当前栈帧,恢复上一个栈帧。
(3)跳转:按照函数返回地址跳回母函数中继续执行。
相关的汇编指令序列如下:Add esp,xxx;Pop ebp;Retn可以看到函数返回点保存在栈中,且栈中的数据是可以被任意覆盖的,这就为利用提供了可能性。
第二章 S.E.H利用分析2.1 结构化异常处理(SEH)操作系统或程序在运行,难免会遇到各种各样的错误,如除零,非法内存访问,文件打开错误,内存不足,磁盘读写错误,外设操作失败。
为了保证系统在遇到错误时不至于崩溃,仍能够健壮稳定地继续运行下去,windows会对运行在其中的程序提供一次补救的机会来处理错误这种机制就是异常处理机制。
S.E.H即异常处理结构体(Structure Exception Handler),它是windows异常处理机制所采用的重要数据结构,每个S.E.H包含两个DWORD指针:S.E.H链表指针和异常处理函数句柄,共8个字节,如下图下面分别对用户模式下的原始型SEH和封装型SEH 进行讨论。
2.1.1 原始型SEHSEH 的进程相关类型是整个进程作用范围的异常处理函数,通过WIN32 API 函数SetUnhandledExceptionFilter 进行注册,而操作系统内部使用一个全局变量来记录这个顶层的处理函数,因此只能有一个全局性的异常处理函数。
而线程相关类型的作用范围是本线程内,并且可注册多个,甚至可以嵌套注册。
两者相比线程相关类型在实际应用中使用较为广泛,因此此处重点对此类型进行研究。
当线程初始化时,会自动向栈中安装一个异常处理结构,作为线程默认的异常处理。
SEH 最基本的数据结构是保存在堆栈中的称为EXCEPTION_REGISTRATION 的结构体,结构体包括2 个元素:第1 个元素是指向下一个EXCEPTION_REGISTRATION 结构的指针(prev),第2 个元素是指向异常处理程序的指针(handler)。
这样一来,基于堆栈的异常处理程序就相互连接成一个链表。
异常处理结构在堆栈中的典型分布如图1 所示。
最顶端的异常处理结构通过线程控制块(TEB)0 Byte 偏移处指针标识,即FS:[0]处地址。
用于进行实际异常处理的函数原型可表示如下:EXCEPTION_DISPOSITION __cdecl _except_handler(struct _EXCEPTION_RECORD *ExceptionRecord,void * EstablisherFrame,struct _CONTEXT *ContextRecord,void * DispatcherContext)该函数的最重要的2 个参数是指向_EXCEPTION_RECORD 结构的ExceptionRecord 参数和指向_CONTEXT 结构的ContextRecord 参数,前者主要包括异常类别编码、异常发生地址等重要信息;后者主要包括异常发生时的通用寄存器、调试寄存器和指令寄存器的值等重要的线程执行环境。
而用于注册异常处理函数的典型汇编代码可表示如下:PUSH handler ; handler 是新的异常处理函数地址PUSH FS:[0] ;指向原来的处理函数的地址压入栈内MOV FS:[0],ESP ;注册新的异常处理结构当异常发生时,操作系统的异常分发函数在进行初始处理后,如果异常没有被处理就会开始在上图所示的线程堆栈上遍历异常处理链,直到异常被处理,如果仍没有注册函数处理异常,则将异常交给缺省处理函数或直接结束产生异常的进程。
2.1.2 封装型SEH通过使用_try{}/_except(){}/_finally{}等关键字,使开发人员更方便地在软件中使用SEH 是封装型SEH 的主要特点。
该机制的异常处理数据结构定义如下:struct VC_EXCEPTION_REGISTRATION{ VC_EXCEPTION_REGISTRATION* prev;FARPROC handler;scopetable_entry* scopetable; //指向scopetable 数组指针 int _index; //在scopetable_entry 中索引DWORD _ebp; //当前EBP 值}显而易见,结构体中后3 个成员是新增的。
而scopetable_entry 的结构如下所示:struct scopetable_entry{ DWORD prev_entryindex; //前一scopetable_entry 的索引FARPROC lpfnFilter; //过滤函数地址FARPROC lpfnHandler; //处理异常代码地址}封装型SEH 的基本思想是为每个函数内的_try{}块建立一scopetable 表,每个_try{}块对应于scopetable 中的一项,该项指向_try{}块对应的scopetable_entry 结构,该结构含有与_except(){}/_finally{}对应的过滤函数和处理函数。
若有_try{}块嵌套,则在scopetable_entry 结构的prev_entryindex成员中指明,多层嵌套形成单向链表。
而每个函数只注册一个VC_EXCEPTION_REGISTRATION 结构,该结构中的handler 成员是一个重要的运行时库函数_except_handler3。
该异常处理回调函数负责对结构中的成员进行设置,查找处理函数并根据处理结果决定是继续执行还是让系统继续遍历外层SEH 链。
为了弄清看似复杂的封装型SEH 原理,此处通过分析一个简单的使用封装型SEH 的函数的反汇编实现,从而深入地了解封装型SEH 的实现过程。
该函数的C 语言实现如下:void A(){__try // 0 号try 块{__try // 1 号try 块{*(PDWORD)0 = 0;}__except(EXCEPTION_CONTINUE_SEARCH){printf("Exception Handler!");}}__finally{puts("in finally");}}对应该函数的序言部分反汇编代码如下:push ebpmov ebp, esppush -1push offset _A_scopetablepush offset _except_handler3mov eax, large fs:0push eaxmov large fs:0, esp;显而易见,压入堆栈的结构与VC_EXCEPTION_REGISTRATION 结构是一致的。
查找scopetable 的地址为0x00422048,在调试器中查找该地址起始的内容如下:FFFFFFFF ;scopetable_entry0 的prev_entryindex 值00000000 ;lpfnFilter 地址值,为0,对应_finally{}004010EE ;lpfnHandler 地址值00000000 ;scopetable_entry1 的prev_entryindex 值004010C6 ;lpfnFilter 地址值004010C9 ;lpfnHandler 地址值…第1 组值对应0 号try 块,而该块对应_finally{}块,所以过滤函数地址为0;第2 组值对应1 号try 块,而该块对应_except(){}块,所以有过滤函数和处理函数的地址。
进一步查看0x004010EE 地址处的反汇编代码如下:PUSH OFFSET ??_C@0L@PEFD@in?5finally?$AA@; ”infinally”CALL putsADD ESP,4RETN显然上述语句与_finally{}块中的C 语言语句是对应的,而其他的地址经过查找也是分别对应的。
在进入0 号try 块时的反汇编语句如下:MOV DWORD PTR SS:[EBP-4],0 ;对应第1 个_try 语句MOV DWORD PTR SS:[EBP-4],1 ;对应第2 个_try 语句而在退出_try 块时对应的反汇编语句如下:…MOV DWORD PTR SS:[EBP-4],0 ;退出第2 个_try 块MOV DWORD PTR SS:[EBP-4],-1 ;退出第1 个_try 块…根据异常处理的堆栈结构可知, [EBP-4] 处值就是VC_EXCEPTION_REGISTRATION 结构中_index 的值。
异常处理机制在进入和退出每个_try 块前设置相应的_index 值,这样就可正确处理封装型SEH 内发生的各种异常。
以上通过实例进一步验证和明确了封装型SHE 的内部机理,它只是扩展了原始型SEH 的功能,简化了软件开发人员的工作。