pikabot

背景

Pikabot 是一种于 2023 年初首次出现的新恶意软件。它有两个组件:Loader 和 core module。它仍处于起步阶段,预计未来将有更多的活动。 一些研究人员认为它与 TA570 有关,因为它与 trojan 之间的递送方法相似。以及活动期间没有活动。 Loader 的用途是执行大量的 Anti-debug、Anti-VM 和 Anti-emulation 检查,使自动化分析和注入核心模块变得更加困难。 使用 stack 和简单的 Bitwise 操作对字符串进行混淆处理。常量整数使用结构和循环进行混淆,以获得正确的偏移量。 核心模块具有许多功能,使攻击者能够完全控制受害者计算机。参考

pikabot分析

image

两个x86程序,选择32位ida打开,打开之后找起始函数start,

image

前面进行了一些空间开辟的操作,不重要,直接进入UsefulFunc_0函数分析

image

其中有一个sub_4145CC函数,跟进发现,没有什么重要信息,进入73行的InitialAndCheckDebug函数,

image

前面是一堆字符串进行操作,sub_410450函数,是计算了当前窗口是否处于最小化状态;跟进debugDetect3函数,

image

前面进行了一堆变量类型的修改,NtQuerySystemInformation跟进,

image

SysCall函数系统调用是操作系统提供的接口,允许用户程序请求内核执行特权操作;Syscall这一绕过edr hook

进入SysCall继续分析

image

image

SysCallTableBuild分析

进入SysCallIndexFindByHash函数之后

image

除了一个对页面操作的函数之外,全是对变量的操作,静态不好分析,先看SysCallTableBuild函数

image

image

从149行开始到209行都在进行peb遍历进程加载dll文件,找到后面进行后续操作的dll文件基址与导出表位置

image

获取导出表地址,判断读取的dll存在导出表没有,205行对字符串进行哈希校验,满足跳出

静态分析到这里之后具体实现不知道,打开x32动调调试,

先在x32中找到0040101Dh处的SysCallIndexFindByHash函数

image

打上断点f9运行到这里

image

通过堆栈可以看到前面的syscall参数是3A6A3CFF这里SysCallIndexFindByHash的参数v1就是syscall的参数

继续往后调试,观察循环peb调用dll的地方

image

在ida观察到地址是0040D8B4h,进入x32的相同地址打上断点

image

跳出循环判断后就能知道寻找的就是ntdll

image

获取导出函数的地址列表,判断导出函数名称是否为ZW开头

image

讲导出函数的地址偏移量和名称偏移量hash值存入sysCallHashTable,导出550个之后跳出

进入HashTableBuild函数

image

计算哈希值

image

哈希值计算结束之后,退出这个函数,之后sysCallTableStruc结构体就构造完成了

动调观察结构体的构造,427DC0h处就是sysCallHashTable

image

image

从这里开始到413行貌似是一个二重循环的冒泡排序,将sysCallHashTable函数按照地址重新排序(二重循环冒泡见补充

到这里SysCallTableBuild这个函数就结束了,返回调用这个函数的地方

image

这里对刚才构造的的结构体进行了遍历,根据传入的hash获取函数在结构体中的下标

再次跳出这个函数

image

直接看汇编代码

image

接下来调用了sub_40D0C4函数,跟进

image

这个函数前面进行了一些字符的混淆,

1
2
3
result = DllBaseAddress
+ v9
+ sysCallHashTable.sysCallTable[sub_40A19C() % (sysCallHashTable.functionNum + 1)].functionAddress;

函数地址的绝对偏移量=DllBaseAddress+functionadress;在上面可以看到v9=5

在这里加上了一个sub_40A19C取余,跟进sub_40A19C函数

image

随机调用?

返回上一级,根据刚才的分析,这个函数实现了一个ntdll中随机化函数的绝对地址+5,返回到查看地址进行动调分析image

在00401052h处打断点

image

跳转到ntdll的模块进行运行,并且运行的函数是ZwSetLdtEntries

ZwSetLdtEntries​ 是 Windows 内核的一个系统调用,用于设置局部描述符表(LDT)中的条目,这里的起始位置应该是77244400h,加5之后就是现在的地址;跳转到了函数起始位置+5的地方执行

观察这一区域的所有函数调用会发现,他们的函数头都是进行一个mov eax,index的操作来进行对eax的赋值,之后的两行代码完全相同,只是会ret不同的值,这意味这如果在mov edx,…这行之前将eax设置为[x],就可以实现相当于调用起始为mov eax,[x]的函数的效果,此时再观察右上角eax,显示为036

image

一直找到eax 36,然后知道调用的是NtQuerySystemInformation

NtQuerySystemInformation​ 是一个 Windows 内核的系统调用,用于获取系统信息。

这就是indirectSyscall的效果,它通过调用随机ntdll.dll中Zw起始的函数头+5的位置,只需在此之前将eax的值设置为不同的数字,就可以实现调用另一个函数的效果

往前翻,一直找到eax 0的地方

image

ntdll中的mov eax,[x],是按x的顺序由小到大排列的;hash+functionaddress中的第一个functionaddress就是772429B0,之后的地址是 772429C0、772429D0……

这也就是之前通过hash遍历获取下标顺序的原因,下标的顺序和mov eax,[x]中的[x]是对应的,也就实现了通过hash调用一个ntdll中native函数的效果,甚至都不需要进入这个函数在应用层的调用地址中,从而躲避edr对所调用函数的hook。