前言
Windows平台的漏洞挖掘和安全研究中,IE始终是绕不开的话题。IE漏洞就跟adobe系列一样经典,是学习exploit、shellcode的绝佳途径。
在IE漏洞中,UAF即Use-After-Free是最为经典的一类。UAF可以这样简单理解:A先后调用B、C、D三个子函数,B会把A的某个资源释放掉;而D由于判断不严谨即使在B把A的资源释放后依然去引用它,比如某个指针,这时D引用了很危险的悬空指针;C是个什么角色呢?我们可以通过B分配数据。所以利用方法来了:构造奇葩的数据,让A调用B,B把A的某个指针释放掉;接着执行C,C赶紧分配内存,企图使用刚才释放掉的内存,同时我们可以控制这个内存;最后D被调用,由于检查不严格调用了已经释放掉的某指针,而该指针实际上已经被我们重用并且扭曲。漏洞被利用。
初学windows分页分段机制,!pte命令是最常用的,PDE和PTE的默认值0xC0600000和0xC0000000很容易让人迷惑。有个朋友跟我吐槽说经常搞混这两个值和虚拟地址转物理地址过程。这里简单说一下。
这两个所谓的默认值指的是进程PDE和PTE所在的虚拟地址,注意不是物理地址。0xC0600000表示页目录的起始加载地址,0xC0000000表示页表起始加载地址。
进程创建、dll加载,都要用到section。我们可以hook相关的函数,比如ZwMapViewOfSection,替换section。可以通过section_object得到对应的文件对象。
dll加载时会映射到进程地址空间,成为进程的一部分,就像一个箱子被扔到屋里,成为了屋子的一部分。编写dll有一些基本的原则,比如一定要有成对的管理函数:申请和释放、获取和解除等,好的dll应该有好的封闭性和完整性。进程加载导入表中的dll有一个固定的顺序:
看到一段很有意思的代码。DPC/Dispatch Level的同步操作,除了当前CPU,其他的都插入一个DPC,利用两个全局变量同步。
一篇记录。在我把《windows核心编程》放回家之前打算再读一遍,倒着来,果然收获不小,能更清晰的了解到这本书讲得多么好。昨天晚上看了最后面的结构化异常处理,这里写个小心得。
Erlang真的很像Prolog,阿姆斯特朗博士在他的著作《Programming Erlang》开头解释为何要学习Erlang时,提到了Erlang的五大特点:
求斐波纳契数列的递归函数,一般来说我们会这么写:
def fib_normal(n): return n <= 2 and 1 or fib_normal(n-1) + fib_normal(n-2) 这当然是典型的费力不讨好的写法,弱智的教科书上都会这么写,还常常表达斐波纳契数列不是O(N)的效率,这么多年坑了不少人。这里只是引出尾递归,写了这么没效率的函数。
执行这个函数的时候,解释器每调用一次fib_normal都会开辟新的堆栈,假如每个堆栈需要K字节的缓冲区,那么计算出结果需要O(NlogN)*K大小的栈空间,如果N很大,就可能会溢出。
现在考虑另一种思路:把计算结果传下去,然后废掉本层栈空间,总的下来只用K大小的缓冲。这就是尾递归的本质,看一看使用尾递归的斐波纳契数列:
def fib_endr(n, a, b): return n == 2 and b or fib_endr(n-1, b, a + b) 舒爽了不少。
看到一个通用的加管理员shellcode,很经典的利用PEB查找kernel32.dll然后找到WinExec函数地址,压栈并执行。中规中矩,不过中规中矩就是最大的亮点。
win64系统调用比win32要简洁不少,因为寄存器增多,切换起来更方便了。还是看CreateFile的例子,直接看ntdll!ZwCreateFile。