手机网站建设品牌,百度权重网站排名,百度网站名称和网址,忘记wordpress登录密码本部分将对常见的二进制漏洞做系统分析#xff0c;方便在漏洞挖掘过程中定位识别是什么类型漏洞#xff0c;工欲善其事#xff0c;必先利其器。0x01栈溢出漏洞原理栈溢出漏洞属于缓冲区漏洞的一种#xff0c;实例如下#xff1a;编译后使用windbg运行直接运行到了地址0x41…本部分将对常见的二进制漏洞做系统分析方便在漏洞挖掘过程中定位识别是什么类型漏洞工欲善其事必先利其器。0x01栈溢出漏洞原理栈溢出漏洞属于缓冲区漏洞的一种实例如下编译后使用windbg运行直接运行到了地址0x41414141这个就是字符串AAAA就是变量str里面的字符串通过strcpy拷贝到栈空间时没有对字符串长度做限制导致了栈溢出最后覆盖到了返回地址造成程序崩溃。溢出后的栈空间布局如下栈溢出原理图0x02 堆溢出漏洞原理使用以下代码演示堆溢出漏洞由于调试堆和常态堆的结构不同在演示代码中加入getchar函数用于暂停进程方便运行heapoverflowexe后用调试器附加进程。debug版本和Release版本实际运行的进程中各个内存结构和分配过程也不同因此测试的时候应该编译成release版本。运行程序使用windbg附加调试(一定要附加调试)g运行后程序崩溃上面的ecx已经被AAAA字符串覆盖掉了最后在引用该地址的时候导致崩溃通过前面的栈回溯定位到了main函数入口找到复制字符串的函数下断点此时堆块已经分配完毕对应的分配地址位于0x007104a00x007104a0是堆块数据的起始地址并非堆头信息的起始地址对于已经分配的堆块开头有8字节的HEAP_ENTRY结构因此heap的HEAP_ENTRY结构位于0x007104a0-80x710498。在windbg上查看两个堆块的信息这两个堆块目前处于占用状态共有0x10大小空间在windbg中使用heap查看HeapCreate创建的整个堆块信息可以发现堆块heap后面还有一个空闲堆块0x007104c0在复制字符串的时候原本只有0x10大小的堆块填充过多的字符串的时候就会覆盖到下方的空闲堆块007104c0在复制前007104c0空闲堆块的HEAP_FREE_ENTRY结构数据如下覆盖后0x007104c0空闲块的HEAP_FREE_ENTRY结构数据如下整个空闲堆头信息都被覆盖了包括最后的空闲链表中的前后向指针都被成了0x41414141后面调用HeapFree释放堆块的时候就会将buf2和后面的空闲堆块0x007104c0合并修改两个空闲堆块的前后向指针就会引用0x41414141最后造成崩溃。如果把上面释放堆块的操作换成分配堆块HeapAlloc()也会导致崩溃因为在分配堆块的时候会去遍历空闲链表指针会造成地址引用异常当内存中已经分配多个堆块的时候可能覆盖到的就是已经分配到的堆块此时可能就是覆盖HEAP_ENTRY结构而不是HEAP_FREE_ENTRY结构。堆溢出原理图0x03 堆调试技巧微软提供了一些调试选项用于辅助堆调试可以通过windbg提供的gflag.exe或者gflag命令来设置对heapoverflow.exe添加堆尾检查和页堆去掉堆标志堆尾检查主要是在每个堆块的尾部用户数据之后添加8字节通常是连续的2个0xabababab该数据段被破坏就可能发生了溢出。对heapoverflow.exe开启hpc和htc用windbg加载对heapoverflow程序附加进程无法在堆尾添加额外标志使用以下命令开启堆尾检查和堆参数检查执行命令g后按下回车键程序会断下来上面一句调试输出信息的意思是在大小为0x10的堆块0x001E0498的0x001E04B0覆盖破坏了0x10大小的空间加上堆头的8字节一共0x18字节0x001E04B0-0x001E04980x18也就是说0x001E04B0位于堆块数据的最后一个字节上基于上面的信息可以分析出程序主要是因为向0x10的堆块中复制过多数据导致的堆溢出。页堆在调试漏洞的时候经常需要定位导致漏洞的代码和函数比如导致堆溢出的字节复制指令rep movsz等前面的堆尾检查方式主要是堆被破坏的场景不利于定位导致漏洞的代码。为此。引入了页堆的概念开启后会在堆块中增加不可访问的栅栏页溢出覆盖到栅栏页就会触发异常。开启页堆用windbg加载heapoverflow运行gflag命令开启了页堆然后g运行后在cmd按下回车键断下可以发现程序在复制A字符串的时候触发了异常程序复制到0x11字节的时候被断下此时异常还未破坏到堆块直接定位导致溢出的复制指令rep movs根据栈回溯调用rep movs的上一层函数位于image004000000x1084的上一条指令也就是00401322此处调用了00401000函数很容易发现这是主入口函数0x04整数溢出漏洞原理整数分为有符号和无符号两类有符号数以最高位作为符号位正整数最高位为1负整数最高位为0不同类型的整数在内存中有不同的取值范围unsigned int 4字节int 4字节当存储的数值超过该类型整数的最大值就会发生溢出。在一些有符号和无符号转换的过程中最有可能发生整数溢出漏洞。基于栈的整数溢出基于栈的整数溢出的例子代码中size变量是无符号短整型取值范围是0~65535输入的值大于65535就会发生溢出最后得到size为4这样会通过边界检查但是用memcpy复制数据的时候使用的是int类型的参数i这个值是输入的65540就会发生栈溢出基于堆的整数溢出基于堆的整数溢出的例子代码中的size是unsigned short int类型当输入小于5size减去5会得到负数但由于unsigned short int取值范围的限制无法识别负数得到正数65533最后分配得到过大的堆块溢出覆盖了后面的堆管理结构0x05 格式化字符串漏洞原理格式化漏洞产生的原因主要是对用户输入的内容没有做过滤有些输入数据都是作为参数传递给某些执行格式化操作的函数的比如printffprintfvprintfsprintf。恶意用户可以使用%s和%x等格式符从堆栈和其他内存位置输出数据也可以使用格式符%n向任意地址写入数据配合printf()函数就可以向任意地址写入被格式化的字节数可能导致任意代码执行或者读取敏感数据。以下面的代码为例讲解格式化字符串漏洞原理可以发现当输入数据包含%s和%x格式符的时候会意外输出其他数据用ollydbg附加调试程序执行前需要先设置命令行参数调试-参数-命令行test-%x在运行程序后传递给printf的参数只有test-%x但是他把输入参数test-%x之后的另一个栈上数据当做参数传给了printf函数因为printf基本类型是传递给printf的参数只有一个但是程序默认将栈上的下一个数据作为参数传递给了printf函数刚好下一个数据是strcpy()函数的目标地址就是buff变量buff刚好指向test-%x的地址0x0019fec4所以程序会输出0x0019fec4如果后面再加一个%x就会将src参数的值也输出了这样就可以遍历整个栈上数据了。除了利用%x读取栈上数据还可以用%n写入数据修改返回地址来实现漏洞利用。0x06 双重释放漏洞原理Double Free漏洞是由于对同一块内存进行二次释放导致的利用漏洞可以执行任意代码编译成release示例代码如下在二次释放p2的时候就会发生程序崩溃但是并不是每次出现Double Free都会发生崩溃要有堆块合并的动作发生才会发生崩溃双重释放原理图在释放过程中邻近的已经释放的堆块存在合并操作这会改变原有堆头信息之后再对其地址引用释放就会发生访问异常。0x07释放后重引用漏洞原理通过以下代码理解UAF漏洞原理buf2 “占坑”了buf1 的内存位置经过UAF后buf2被成功篡改了程序通过分配和buf1大小相同的堆块buf2实现占坑似的buf2分配到已经释放的buf1内存位置但由于buf1指针依然有效并且指向的内存数据是不可预测的可能被堆管理器回收也可能被其他数据占用填充buf1指针称为悬挂指针借助悬挂指针buf1将内存赋值为hack导致buf2也被篡改为hack。如果原有的漏洞程序引用到悬挂指针指向的数据用于执行指令就会导致任意代码执行。在通常的浏览器UAF漏洞中都是某个C对象被释放后重引用假设程序存在UAF的漏洞有个悬挂指针指向test对象要实现漏洞利用通过占坑方式覆盖test对象的虚表指针虚表指针指向虚函数存放地址现在让其指向恶意构造的shellcode当程序再次引用到test对象就会导致任意代码执行。UAF漏洞利用原理图0x08 数组越界访问漏洞先区分一下数组越界漏洞和溢出漏洞数组越界访问包含读写类型溢出属于数据写入部分溢出漏洞本质确实就是数组越界漏洞。数组越界就像是倒水的时候倒错了杯子溢出就像是水从杯子里溢出来。下面代码为例分析数组越界访问漏洞执行生成的程序然后分别输入12345输出结果如上当输入的数组下标分别是12的时候会得到正常数值但是从索引3开始就超出了原来的数组array的范围比如输入5就会数组越界访问array数组导致读取不在程序控制范围内的数值。使用ollydbg调试发现array[5]就是从array开始的第六个数据0x4012A9已经读取到了array之外的数据如果越界访问距离过大就会访问到不可访问的内存空间导致程序崩溃。0x09类型混淆漏洞原理类型混淆漏洞(Type Confusion)一般是将数据类型A当做数据类型B来解析引用这就可能导致非法访问数据从而执行任意代码比如将Unit转成了String将类对象转成数据结构。类型混淆漏洞是现在浏览器漏洞挖掘的主流漏洞这类漏洞在javajs等弱类型语言中非常常见。下面的代码A类被混淆成B类就可能导致私有域被外部访问到class A {private int value;};class B {public int value;};B attack AcastB(var); //将A类型混淆转成B类型attack.value 1; //导致可以访问私有域以IE/Edge类型混淆漏洞(CVE-2017-0037)为例讲解漏洞原因是函数处理时没有对对象类型进行严格检查导致类型混淆。PoC如下在PoC中定义了一个table标签中定义了表id为th1在boom()中引用然后是setInterval设定事件。运行PoC用Windbg附加并加载运行出现崩溃从崩溃点可以看到eax作为指针引用了一个无效地址导致崩溃而上一条指令是一个call这个无效的返回值来自这个call在这个call处下断点ecx作为参数存放的对象是一个Layout::FlowItem::vftable虚表这里读取虚表中4的值为0时this指针赋值v1随后v116后返回因此Layout::FlowItem::vftable所属指针的这个情况是正常的函数会正常返回进入后续处理逻辑让程序继续运行会再次调用该函数此时ecx并不是一个虚表对象而是一个int Array对象这里我们可以通过条件断点来跟踪两个对象的创建过程重点关注两个对象创建的函数一个是FlowItem::vftable对应的虚表对象另一个是引发崩溃的int Array对象。这两个函数的返回值也就是eax寄存器中存放的指向这两个创建对象的指针。通过跟踪可以看到第一次调用Readable函数时ecx是一个正常的FlowItem对象而第二次调用的时候ecx是一个int Array Object。Layout::Patchable ::Readable函数是处理虚表对象的函数由于boom()函数中引用th1.align导致Readable函数得到第二次引用由于没有进行对象属性检查导致第二次调用时将table对象传入最终发生类型混淆崩溃。0x10竞争条件漏洞原理竞争条件(Race Condition)是由于多个线程/对象/进程同时操作同一资源导致系统执行违背原有逻辑设定的行为这类漏洞在linux内核层面非常多见在windows和web层面也存在。互斥锁的出现就是为了解决此类漏洞问题保证某一对象在特定资源访问时其他对象不能操作此资源。比如如下代码执行结果如下按照我们的预想结果应该都是10但是发现结果可能存在非预期解原因就在于我们没有对变量COUNT做同步制约导致可能Thread-7在读COUNT,还没来得及更改COUNT,Thread-8抢夺资源也来读COUNT,并且将COUNT修改为它读的结果1由此出现非预期。