漏洞战争笔记

栈溢出漏洞

栈是向低地址方向生长的,而变量在栈中是向高地址方向生长的。当栈里面的变量被赋予的值超过其最大分配缓冲区的大小时,就会覆盖前面push到栈里的返回地址,导致函数在返回时发生错误,这就是栈溢出。
在这里插入图片描述

原理

栈溢出属于缓冲区溢出的一种,有时也称作堆栈溢出。堆栈溢出泛指栈溢出和堆溢出的统称。
通过strcpy复制字符串到固定长度的栈空间时,未对字符串长度进行限制,导致栈溢出,最后覆盖到返回地址,造成访问违例。
在这里插入图片描述

防范措施

复制之前对数据的长度进行判断,阻止超过额定长度的复制操作。

void testFunc(char *Buf)
{
    char testBuf[8];
    int copyLen = 64;
    if(copyLen > sizeof(testBuf))
    {
        /*
        当长度超过限制时,可根据实际情况限制复制操作
        1.强行将复制数据的长度改为testBuf的长度
        2.可以提示异常,退出复制操作        
        */
        copyLen = sizeof(testBuf);
        memcpy(testBuf,Buf,copyLen);    
    }
    else
    {
        memcpy(testBuf,Buf,copyLen);     
    }
    return;
}

常见函数

read()、weite()、gets()、puts()、strcpy()、memcpy()、strncpy()、printf()、scanf()
在这里插入图片描述

堆溢出漏洞

堆溢出是给堆里面的变量赋予超过了其分配的空间大小的值,堆链表的后续链表数据会被覆盖所致。

原理

复制的数据长度超出了代码缓冲区所分配的空间,导致了缓冲区溢出。
堆上溢(常见堆溢出):覆盖HEAP_FREE_ENTRY结构
堆下溢:反方向溢出,覆盖到堆管理结构HEAP和HEAP_SEGMENT结构
在这里插入图片描述

防范措施

在复制数据之前对数据长度进行严格的检查。

调试技巧

gflags.exe —— G:\Tools\Debuggers\x86\gflags.exe
WinDbg命令 !gflag
htc - 堆尾检查,在堆块末尾附加额外的标记信息(通常为8字节),用于检查堆块是否发生溢出。
hfc - 堆释放检查,在释放堆块时对堆进行各种检查,防止多次释放同一个堆块。
hpc - 堆参数检查,对传递给堆管理的参数进行更多的检查。
ust - 用户态栈回溯,即将每次调用堆函数的函数调用信息记录到一个数据库中。
htg - 堆标志,为堆块增加附加标记,以记录堆块的使用情况或其他信息。
hvc - 调用时验证,即每次调用堆函数时都对整个堆进行验证和检查。
hpa - 启用页堆,在堆块后增加专门用于检测溢出的栅栏页,若发生堆溢出触及栅栏页便会立刻触发异常。
示例:针对xxx.exe程序添加堆尾检查功能和页堆,去掉堆标志
!gflag -i xxx.exe +htc +hpa -htg

gflags.exe -i xxx.exe +htc +hpa -htg
在堆漏洞调式中,较为常用的是htc、hpc、hfc和hpa。

整数溢出漏洞

整数溢出漏洞从成因的角度可以分为3个大类,分别是存储溢出、计算溢出和符号问题。
存储溢出:由使用不同的数据类型存储整形数造成的。
计算溢出:在对整型数变量进行运算的过程中没有考虑其边界范围,造成运算后的数值超出了其存储空间。
符号问题:在一般情况下,对长度变量都要求使用无符号整型数,如果忽略符号,可能会引起溢出。
综上所述,整数溢出的产生是由赋值类型的大小不匹配造成的。防范整型溢出,需要开发人员养成良好的安全编程习惯,严格检查变量的赋值。

原理

向其存储的数值超过该类型整数的最大值,就会导致整数溢出。
比如unsigned short的存储范围是0~65535,但当存储的值超过65535时,数据就会截断,例如输入65536,系统就会识别为0。在一些有符号与无符号数之间转换时,程序员也容易犯整数溢出这种错误。
在这里插入图片描述

格式化字符串漏洞

原理

源于对用户输入内容未进行过滤,输入数据都是作为参数传递给执行格式化操作的函数,如printf、fprintf、vprintf、sprintf等。
恶意用户可以使用“%s”和“%x”等格式符,从堆栈或其他内存位置输出数据,也可以使用格式符“%n”向任意地址写入任意数据,配合printf()函数和其他类似功能的函数就可以向任意地址写入被格式化的字节数,可能导致任意代码执行,或者从漏洞程序中读取敏感信息,比如密码等。

常见的格式化控制符

总结

(1)通过“%n”格式化控制符实现用任意数据(ECX)写任意地址(EAX),一般是用Shellcode地址覆盖返回地址或者SEH异常处理地址。
(2)通过填充不同个数的“%x”控制符来偏移被写地址EAX到字符串的结尾,以满足覆盖地址中0x00的需求。
(3)通过“%[n]x"控制打印字符个数,以便让被写数据ECX指向Shellcode.
(4)覆写成功后,当执行返回或者触发异常时,就会执行Shellcode代码。

双重释放漏洞

原理

在这里插入图片描述
在释放过程中,邻近的已释放堆块存在合并动作,这会改变原有的堆头信息及前后向指针,之后再对其中的地址进行引用,就会导致访问异常,最后程序崩溃。如果程序不存在堆块合并动作,双重释放后可能不会马上崩溃,但会在程序中遗留隐患,导致在后续执行过程中的某一时刻爆发。

释放重引用漏洞(Use After Free,UAF)

使用到已被释放的内存,最终导致内存崩溃或任意代码执行的漏洞。

原理

如果原有的漏洞程序引用到悬挂指针指向的数据用于执行指令或作为索引地址去执行,就可能导致任意代码执行,前提是用可控数据去“占坑”释放对象。
通过“占坑”的方式覆盖对象的虚表指针,使其指向恶意构造的Shellcode,当程序再次引用到对象时,就可能导致执行任意代码。

mov ecx,[eax]      ; eax指向C++对象,即悬挂指针,而对象头4字节为虚表指针,所以ecx为虚表指针    
call [ecx+4]        ; 通过虚函数表偏移找到指定的虚函数进行调用

在这里插入图片描述

数组越界访问漏洞

数组越界犹如倒水时倒错水杯,溢出犹如倒水时水从杯子里漫出来。

原理

当索引值超出原定数组的范围,就会越界访问数组,导致读取到不在程序控制范围内的数值。
如果越界访问距离过大,就可能导致访问到不可访问的内存,导致程序崩溃。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值