该系列dll,从名称上看,分别用于修改审计信息、认证信息、组信息和权限信息:
每个DLL对外提供少量的导出函数,常见的导出函数原始名称分别为i_1()、i_2()、i_3()、i_4()以及一个入口函数DllEntryPoint(),如下:
逆向分析i_1()函数如下:
从我们的分析结果来看,i_1()函数主要作用是初始化,其目的是初始化后续由操作码0x10和0x11触发的系统调用。从这些dll函数的导入函数中,我们几乎没有看到太多关于上述修改系统信息的函数调用,那么这些恶意软件是如何达成目的的呢?相应的系统调用地址是通过i_1()参数传入并保存在全局变量中的。
i_1()还创建了一个用于互斥的信号量。
i_2()函数从指定的内存区域(Memory)中取出一系列的函数地址及函数参数,并逐个进行调用,随后释放i_1()函数中创建的信号量。如下:
但是我们没有分析出Memory被初始化为哪些函数序列了,初步的判断是这个函数为结束函数,释放执行过程中的创建的资源,并不涉及太多的功能操作。
i_3()是主要的功能函数,我们在后面进行分析,先来看i_4()。该函数也没有执行具体的功能,从结果上看,应该是取版本号之类的信息,并赋值给入参,从而传递给调用者:
从这个函数来看,泄漏的恶意软件版本信息应该是“2.0.2.131072”。
I_3()是主要的功能函数,该函数允许调用者传入两个操作码,分别是0x10和0x17,并执行不同的系统操作,从而修改审计、认证、权限和组等信息。这里恶意软件并没有直接调用Windows系统API,而是通过i_1()函数进行初始化,传入函数的地址后进行执行,从而躲避安全产品的检测。
大概的函数调用关系如下:
整个过程大概如下:
int (*func) (int a1, int a2, int a3, int a4); /* Initialize, system APIs are passed by parameters and stored in global variables */ i_1(void *buf, size_t bufsize); /* Get function address that to be executed. */ func = i_3(char a1); //a1=0x10 or a1= 0x11 /* Do malicious actions */ func(a1, a2, a3, a4); /* FINI */ i_2();
从单个小的组件来看,整个equation攻击平台的设计应该是比较先进的,体现出了良好的扩展性、兼容性和代码复用程度。
由于该DLL执行的功能函数均由调用者传入,因此程序的执行结果取决于攻击者传入的载荷,单独对该DLL的静态分析检测很难发现恶意行为,这也体现了equation攻击平台良好的反检测技巧。