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中,占用态的堆块被使用其的程序索引,堆表只索引空闲态的 ...
0 Day 笔记
未读notes abouter chapter 4本章基本就是教怎么使用msfconsole的。
from 4.3shellcode测试:
from 4.4Ruby 简要学习。首先hello world,这里有坑,t.rb要在msf_root/bin目录下创建,要到msf_root/bin的目录下打开msfconsole,然后输入的指令是:1ruby t.rb如图:
from 4.6触发漏洞的server代码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657#include<iostream.h>#include<winsock2.h>#pragma comment(lib, "ws2_32.lib")void msg_display(char * buf){ char msg[200]; strcpy(msg,buf);// overflow here, copy 0 ...
0 Day 笔记
未读notes for chapter3from 3.2问题描述:我们再之前的学习中使用的覆盖返回地址的方法不适用与普适情况,如当PE程序被重新加载时,栈桢可能发生移位的情况,这个时候我们得buff区的地址就需要重新计算。
解决方案:一个函数返回时,esp正好指向原理存储返回地址的下一位,我们将shellcode从ret_addr的后一个位置开始填充,并将ret_addr填充为一个进程中的”jmp esp”的指令的地址,这样函数返回后就会跳到esp指向的栈顶的位置开始执行shellcode。
3.2.3 experiment使用程序找出进程中的user32.dll中的jmp esp的指令的地址:这里使用0x77d8625f这个地址构造exp(到底使用哪一个其实需要测试一下,我第一次测试不对,第二次使用该地址就可以了)。然后根据实验需求,我们需要在弹窗结束后正常退出,即在最后加上这么一段:12mov eax,exit_addrcall eax所以我找到ExitProcess这个函数的虚拟地址:所以这里的退出进程的虚拟地址为0x7C800000+0x0001CAFA=0x7C81CAFA ...
0 Day 笔记
未读notes about chapter 2from 2.1
每一个C++类成员都有一个this指针,在win中,这个指针一般使用ecx进行保存:
2.2.1 expriment这里的auth标志位在buffer的下方:
int authenticated;char buffer[8];// add local buffto be overflowed
利用思路:覆盖掉标志位。这里的内存布局输入7777777如下:123buff[8] 71717171 qqqq 00717171 NULLqqqauth 00 00 00 01 真实存储为: 01 00 00 00 00我们想要的:123buff[8] 71717171 qqqq 00717171 NULLqqqauth 00 00 00 00 真实存储为: 00 00 00 00 00由于字符串末尾有NULL(00)作为结尾,所以我们输入8位的char型即可:123buff[8] 71717171 ...
0 Day 笔记
未读Notes for chapter one一些概念from 1.2:
静态反汇编工具汇编工具看到的PE文件中的地址都是文件偏移(文件地址),这个是文件在磁盘上存放的相对于文件开头的偏移。
装载基址:PE装载时的基地址,默认情况下(32位):
exe的装载基址:0x00400000
dll的装载基址:0x10000000
上述的基址可以通过编译选项改变
虚拟内存地址(VA):PE文件指令被装入内存后的地址(IDA之类显示的地址)。
相对虚拟地址(RVA):虚拟内存地址相对于装载基址的偏移。RVA,VA,基址存在以下的计算:
VA=RVA+Image Base
RVA和文件地址有很大的一致性,但是由于装载以后和一般存放在磁盘上内存的存放单位不同,会有差异。(P34 0x200和0x1000的区别)
文件偏移地址与虚拟内存地址之间的换算关系可以用下面的公式来计算:
文件偏移地址 = 虚拟内存地址(VA)−装载基址(Image Base)−节偏移= RVA -节偏移
上述的RVA->文件地址的计算可以用lordPE简化过程
from 1.3
ring3级别的调试(用户 ...
pwn
未读简要分析漏洞在netapi32.dll中的导出函数NetpwNameCanonicalize的子函数CanonicalizePathName中。
CanonicalizePathName函数对路径合并的后的字符进以下的一些处理:
将字符串中的”/“转化成”\”:
12345678910111213.text:5FDDA1F8 rep_slash_loop: ; CODE XREF: CanonicalizePathName+88↓j.text:5FDDA1F8 cmp word ptr [eax], 2Fh ; 将"/"转换成"\".text:5FDDA1FC jz slash_to_back_slash ; 复制"\".text:5FDDA202 slash_to_back_forward: ; CODE XREF: CanonicalizePathName+ ...