0 Day 笔记
未读notes about chapter 25from 25.2下断点的技巧畸形RetAddr断点所谓畸形 RetAddr断点,就是将POC中溢出后覆盖的函数返回地址修改为一个非法地址(例如 0xFFFFFFFF),在调试POC时能够触发一个非法内存访问的错误,使得调试器中断下来。
条件断点条件断点是一个带有条件表达式的普通INT3 断点。当调试器遇到这类断点时,它将计算表达式的值,如果结果非零或者表达式无效,将暂停被调试程序。
od中在地址shfit f2即可。
举例:
调试记事本时,UNICODE [[ESP+4]]==”c:\test.txt”,表示当进入CreateFileW 函数后,如果第一个参数lpFileName为unicode 字符串”c:\test.txt”时则暂停被调试的程序。
消息断点消息断点是调试UI程序时的常用技巧。有时需要分析类似一个按钮被单击后程序的处理过程,就需要设置消息断点。消息断点其实是属于条件断点的,只不过是用消息来做表达式的。
内存断点调试过程更关心的是一些重要数据在内存中的读取、访问等操作,那就需要内存断点的支持了。
“Memory, on a ...
0 Day 笔记
未读notes about 0day chapter 15from 15.1微软在之前堆的基础上增加了堆的安全校验:
PEB random
Safe Unlink
Safe Unlink机制:
Windows sp2之前链表的拆卸操作:
123456int remove (ListNode * node){ node -> blink -> flink = node -> flink; node -> flink -> blink = node -> blink; return 0;}
SP2在进行删除操作时,将提前验证堆块前向指针和后向指针的完整性,以防止发生DWORD SHOOT:
1234567891011121314int safe_remove (ListNode * node){ if( (node->blink->flink==node)&&(node->flink->blink==node) ) { nod ...
0 Day 笔记
未读notes about chapter 14from 14.1开启SEHOP:
手工在注册表中HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\kernel找到DisableExceptionChainValidation项,将该值设置为0,即可启用SEHOP。
SEHOP的原理对SEH链进行检查,检查链表的最后一项是否为系统固定的终极异常处理函数,若是则表明SEH链完整,否则就有可能发生SEH覆盖攻击。
验证代码:
1234567891011121314151617181920212223242526272829303132if (process_flags & 0x40 == 0) { //如果没有 SEH 记录则不进行检测 if (record != 0xFFFFFFFF) { //开始检测 do { if (record < stack_bottom || record > stac ...
0 Day 笔记
未读notes about chapter13from 13.2 攻击未启用 ASLR 的模块from 13.3 利用部分覆盖进行定位内存地址
codes:
123456789101112131415161718192021222324252627282930313233343536373839404142434445#include<string.h>#include"stdlib.h" char shellcode[]="\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C""\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53""\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B""\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x ...
0 Day 笔记
未读notes about chapter 12from 12.3针对DEP,最好的攻击方法就是ret2libc,在可执行的模块里找到指令,构造出一条攻击链。这种方法操作难度极大,很难找到这么一条可行的攻击链。
书中给出了一些一般性的思路:
(1)通过跳转到ZwSetInformationProcess 函数将DEP 关闭后再转入shellcode执行。(2)通过跳转到VirtualProtect 函数来将shellcode 所在内存页设置为可执行状态,然后再转入shellcode 执行。(3)通过跳转到VIrtualAlloc 函数开辟一段具有执行权限的内存空间,然后将shellcode 复制到这段内存中执行。
利用ZwSetInformationProcess将DEP关闭后再转入shellcode执行一个进程的DEP设置标识保存在KPROCESS结构中的_KEXECUTE_OPTIONS中:
12345678_KEXECUTE_OPTIONSPos0 ExecuteDisable :1bitPos1 ExecuteEnable :1bitPos2 DisableThunkEmul ...
0 Day 笔记
未读notes about 0day chapter 11from 11.1简单回顾(SEH结构体):
Dword:Next SEH Header(低地址)
SEH链表指针
Dword:Exception Handler(高地址)
异常处理函数句柄
safeSEH机制的几个校验:
检查异常处理链(SEH链表指针)在当前程序栈中,若不在则终止异常处理函数得调用。
检查异常处理函数句柄是否在当前栈中,若在则终止。
在前面两项检查都通过后,程序调用一个全新的函数RtlIsValidHandler(),来对异常处理函数的有效性进行验证。
RtlIsValidHandler的一些验证:
检查程序是否设置了IMAGE_DLLCHARACTERISTICS_NO_SEH 标识。如果设置了这个标识,这个程序内的异常会被忽略。所以当这个标志被设置时,函数直接返回校验失败。
检测程序是否包含安全S.E.H 表。如果程序包含安全S.E.H 表,则将当前的异常处理函数地址与该表进行匹配,匹配成功则返回校验成功,匹配失败则返回校验失败。
判断程序是否设置ILonly 标识。如 ...
0 Day 笔记
未读notes about chapter 10
第九章:概述
from 10.1
以下情况不会应用GS。(1)函数不包含缓冲区。(2)函数被定义为具有变量参数列表。(3)函数使用无保护的关键字标记。(4)函数在第一个语句中包含内嵌汇编代码。(5)缓冲区不是8字节类型且大小不大于4 个字节。
from 10.2缓冲区不是8字节类型且大小不大于4个字节时该函数不会应用GS:
发生了溢出:
from 10.3使用199个”\x90”和一个”\0”作为参数传给buff参数,在strcpy结束后设置一个断点:
此时gsv的栈桢是这样的,紧接着的是一些参数(4个字节)以及:canary(0x862DE78E),前一个栈桢的EBP(0x0012FF7C),返回地址(0x004010C9),参数(0x00402100),虚表指针(0x004021D0)。所以buff区还差5*4=20个字节。
此时的virtual表的函数为:
继续覆盖20个字节的\x90,就可以看到虚表指针的最后一个字节已经被结束符”\0”覆盖掉了,指向了缓冲区的起始地址(0x00402100)。
之后我们要做的 ...
0 Day 笔记
未读note about chapter 8from 8.1 format string测试程序的堆栈情况:
此时首先入栈的格式化字符串读取前面进入栈的两个数:44(0x2C),77(0x4D)。但是第二个格式化字符串参数没有数据列表,于是顺着栈往下读,就是4218928(0x00406030)以及44(0x2C),若是继续读取就是77(0x4D)。
常见的格式化字符串漏洞:12345678910111213int printf( const char* format [, argument]... );int wprintf( const wchar_t* format [, argument]... );int fprintf( FILE* stream, const char* format [, argument ]...);int fwprintf( FILE* stream, const wchar_t* format [, argument ]...);int sprintf( char *buffer, const char *format [, argument] ...
0 Day 笔记
未读notes about chapter 6from 6.1Windows针对异常会使用异常处理结构体SEH:
Dword:Next SEH Header(低地址)
SEH链表指针
Dword:Exception Handler(高地址)
异常处理函数句柄
有关SEH的一些概念:
SEH结构体存放在系统栈中。
当线程初始化,会向栈中安置一个SEH,作为线程的默认异常处理。
如果程序源代码中使用了try{}except{}或者Assert 宏等异常处理机制,编译器将最终通过向当前函数栈帧中安装一个S.E.H 来实现异常处理。
栈中会有多个SEH。
栈中的多个SEH通过链表指针在栈内由栈顶向栈底串成单向链表,链表顶端的SEH通过TEB 0字节的偏移的指针标识。
当异常发生时,操作系统会中断程序,并首先从T.E.B 的0 字节偏移处取出距离栈顶最近的S.E.H,使用异常处理函数句柄所指向的代码来处理异常。
当离“事故现场”最近的异常处理函数运行失败时,将顺着S.E.H 链表依次尝试其他的异常处理函数。
当程序安装的所有SEH都处理不了,就使用(2中所述)默认的S ...
0 Day 笔记
未读notes about chapter 5from 5.1堆的一些特征:
堆是一种在程序运行时动态分配的内存。动态内存即是程序设计时不能预先决定的,需要在程序时用户给出。
堆在使用时由程序员用专用的函数进行申请,如:malloc,new等。对内存有可能申请成功,也可能失败。
一般用一个指针来使用申请得到的内存。
使用完毕后,需要把堆指针传给堆释放函数回收这片内存,不然就会导致内存泄漏。释放函数如:free,delete等。
现代操作系统处于一些基本的要求,将堆数据结构分为堆块以及堆表:
堆块:堆块分为两个部分:块首和块身。块首是一个堆块头部的几个字节,用来标识这个堆块自身的信息,如块的大小,本块的空闲情况;块身是紧跟在块首后面的部分,也是最终分配给用户使用的数据区。
堆表:堆表位于堆区的起始位置,用于索引堆区中所有的堆块的重要信息,包括堆块的的位置,堆块的大小,空闲还是占用等。堆表的数据结构在设计时可能会考虑平衡二叉树等高级数据结构用于快速查找,现代操作系统的堆表往往不止一种数据结构。
内存的分布大致如下:
Windows中,占用态的堆块被使用其的程序索引,堆表只索引空闲态的 ...