多线程混淆是一种让软件具备不确定性的一种反分析方法,它主要是利用了操作系统时间分片和多线程机制,由于线程间共享程序内存,每个线程的不同仅在于寄存器、堆栈以及线程局部存储(TLS),因此可以让一个线程替另一个线程执行任务。举例而言,假设A、B两个线程,A线程需要执行一个函数,函数功能是进书房随机取一本书,函数返回这本书的指针。如果用线程B替换线程A,那么可以这样设计。首先线程A进入函数,然后告诉线程B,我进来了,线程B让线程A等待,然后线程B替线程A取书,然后交给线程A,线程A拿到书后继续执行,线程B则空转等待。
前面绕一个大弯,让一个线程替代另一个线程去执行一段代码,这样做有什么意义呢?单纯从执行效率上讲当然是没有任何意义的,而且会带来很多开销,但是站在软件保护的角度上看就非常有意义了,下面分别站在A线程和B线程的角度进行具体分析。
实际上多线程混淆技术的核心思想就是使软件具备运行时的多态性。简单解释何为运行时多态性,首先解释何为多态性。多态性是软件保护的一种机制,常用于恶意软件的自我保护中,恶意软件通过将自己的代码改变,但是又保持原有功能完全不变,从而改变自身的某些特征以躲避杀毒软件的查杀。可见多态性就是软件对自己进行等价变形,但传统的多态性是静态的,软件执行后在内存中并不会随着运行的过程而自我变形,一般软件是执行开始阶段或程序关闭前,才会重新生成新的“变形”程序。而运行时多态性是指软件在运行的过程中可以自我变形或可以实现路径多态性。
软件运行时多态性可以通过多线程混淆来实现(当然还有其它的方法,本文不展开)。由于线程数可以任意指定,执行线程可以随机选取,理论上当有�块代码和�个执行线程时,路径的可能性共有为��种。
由于实现细节有些繁琐,这里仅给出代码流程。多线程混淆的思想是比较容易理解的,我们将多态性中用来具体执行的线程记为工作线程,而原线程记为用户线程,则具体可以分8步。
前面提到了用多个线程替待一个线程的执行,工作线程执行完毕后最终还会返回到用户线程,这种策略是替身机制,其实还有其它的策略,比如用多线程完全取代一个线程,即工作线程执行完后不返回用户线程而且继续往前执行,或者将用户线程也纳入到线程池中,这种策略类似于接力跑。
代码运行时多态性的思想是软件保护研究的前沿领域,其本质和核心是为了增加了程序的复杂度,当程序的复杂度高到现有硬件条件无法遍历分析时,保护就算取得了成效。传统的静态混淆技术难以抵抗动态分析,静态混淆是预置了很多混淆项,但这些预置的混淆代码具有固定的控制流,不可能在量级上提高程序的复杂度。而传统的动态混淆技术又仅做了程序的动态加解密。无论是自生成代码技术还是自修改代码技术,很多论文中仅提到了将明文窗口大小减小,比如采用更细粒度的分片方式等,或者让明文窗口的时间缩短,比如加入冲突锁定,一旦代码冲突解锁则立即释放明文代码。这些传统的动态混淆思路距离真正的混淆还有很远的距离。
代码执行时多态性才是真正的解决途径,如果采用接力跑机制,对于每一个线程而言,其执行的代码都是不确定的,其调度是由操作系统指定的,具有不可预料性。最重要的是,由于其多样化程度可以指数级上升,因此可以用较少的代价换取较高的复杂度。
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
加入交流群
请使用微信扫一扫!