IT技术博客大学习 共学习 共进步
首页 / 程序人生
IT 2016-03-07 23:34:07 / 累计浏览 3,860

深入解析DLL劫持漏洞

这篇文章深入剖析了DLL劫持这项古老但依然实用的技术。作者从Windows DLL加载机制的核心漏洞出发,对比了Windows XP SP2前后搜索顺序的关键差异,特别是SafeDllSearchMode开启与否对“当前目录”优先级的影响。 文章重点区分了三种主流的利用场景:针对应用程序安装目录的劫持(需要写权限,常用于持久化或“白加黑”免杀)、针对文件关联的劫持(只需用户打开特定文件,如PDF,条件最简单),以及针对安装程序的劫持。通过Notepad++安装包的ProcMon抓包实例,具体展示了如何识别和利用漏洞。 此外,文章还结合了HaifeiLi关于Chrome/Edge浏览器“自动下载”漏洞的案例,拓展了DLL劫持在现代软件环境中的攻击面,并简要提及了新版Edge对DLL注入的缓解措施。整体来看,它系统梳理了从原理、挖掘(如使用ProcMon过滤)到利用的完整链条。

IT 2016-02-16 20:47:25 / 累计浏览 2,200

也来谈谈沙箱逃逸技术

这篇讲的是作者基于过往经验,总结的一系列针对在线沙箱检测的逃逸技巧。核心观点是:沙箱因其环境特征,反而可能暴露出独特的“指纹”,而绕过检测的关键在于识别并利用这些差异。 文章首先从进程检测入手,指出直接明文比对进程名(如vmtoolsd.exe)会触发监控,而用加密后的密文进行比对则是一种有效规避。接着,作者详细列举了多种沙箱指纹特征:例如特定的Windows ProductId(如Anubis沙箱的76487-640-1457236-23837)、有规律的ComputerName(如某些沙箱环境以“xiaochen”开头)、固定的内存大小(Anubis 128M、火眼512M),以及固定的样本路径(如Comodo沙箱的C:\TEST\sample.exe),这些在不同厂商间存在明显差异。 此外,文章还探讨了如何在不联网的情况下泄露沙箱数据,比如将文件内容写入注册表,或更巧妙地将二进制数据编码到图片像素中,利用沙箱截图功能来传递信息。最后,作者总结道,逃逸的核心思路在于找到“沙箱有的而别的机器却没有的”特征,以及开发“你有的而别人没有的”绕过方法,为攻防双方提供了具体的实战视角。

IT 2015-01-25 21:38:28 / 累计浏览 3,420

STL笔记之hashtable

这篇讲的是SGI STL中经典hashtable容器的源码实现。作者从自己动手实现一个简单hashtable的经历切入,发现与STL源码的思路惊人相似,由此展开对底层机制的剖析。 文章深入讲解了SGI版本hashtable的核心设计:它采用开链法解决冲突,节点通过链表串联在bucket中。关键实现的巧妙之处体现在两处:一是迭代器逻辑,当前bucket遍历完毕后,能自动跳转到下一个非空bucket,保证了前向遍历的连贯性;二是容器容量的管理,预置了一张精心计算的素数表来动态选择桶的数量,这能有效降低哈希冲突概率,提升查找效率。 通过拆解节点定义、迭代器操作符和容器初始化等关键源码,文章清晰地展现了hashtable从数据结构到算法选择的完整实现脉络,有助于读者真正理解这个高效容器背后的工程权衡与精巧构思。

IT 2015-01-25 21:37:04 / 累计浏览 4,040

STL笔记之二叉查找树

这篇讲的是STL关联容器(如map和set)背后的核心数据结构——二叉查找树及其变体。作者从SGI STL的实现出发,系统梳理了三种关键树结构的区别与联系。 文章首先剖析了基础的二叉查找树(BST),说明了它通过键值左小右大的规则实现对数时间操作,但也指出了其退化为链表导致效率骤降至O(N)的风险。为了解决平衡问题,文章对比了AVL树和红黑树:AVL树是严格的平衡树,任何节点的左右子树高度差不超过1,通过旋转保持平衡,保证了稳定的O(log n)性能;而红黑树通过着色规则和局部调整,在不过分追求严格平衡的前提下,同样实现了高效的查找与动态操作。 最后,文章将理论落地,解释了为何红黑树凭借其在插入和删除场景下更少的旋转次数,成为SGI STL中map、set等容器的底层选择,而不只是理想中“更平衡”的AVL树。这种从原理到工程实现的脉络,对于理解标准库的设计哲学很有帮助。

IT 2015-01-25 21:36:02 / 累计浏览 3,740

Redis编程小技巧拾遗

这篇讲的是作者在阅读Redis源码时,特意“拾遗”的几个精妙的C语言编程技巧。作者从Redis简洁的1.0版本入手,并未重复大众熟知的源码剖析,而是聚焦于那些能让代码更健壮、更高效的小细节。 最典型的是“空数组”技巧:在`sdshdr`和`zskiplistNode`结构体的末尾定义一个空数组成员(如`char buf[]`和`level[]`)。这允许在动态内存分配时,根据实际需要的数据长度(如字符串长度、跳表层数)一次性申请合适大小的内存,实现了结构体内可变长数据的紧凑存储。 另一个常见但重要的技巧是使用 `do { } while(0)` 来包裹宏定义中的多条语句。这不仅能确保宏在if等控制流中像单条语句一样安全执行,文章还展示了将其用于简化流程控制的用法,使代码逻辑更清晰。 此外,文章还介绍了Redis中定制化的断言宏`redisAssert`和分级日志系统`redisLog`,前者在条件失败时能输出详尽的上下文信息,后者则允许根据日志级别进行过滤。这些实现虽小,却体现了生产级项目对可调试性和可观测性的重视。 这些从顶级项目中提炼出的技巧,对任何C/C++开发者都有直接的借鉴意义。