pikabot
背景
Pikabot 是一种于 2023 年初首次出现的新恶意软件。它有两个组件:Loader 和 core module。它仍处于起步阶段,预计未来将有更多的活动。 一些研究人员认为它与 TA570 有关,因为它与 trojan 之间的递送方法相似。以及活动期间没有活动。 Loader 的用途是执行大量的 Anti-debug、Anti-VM 和 Anti-emulation 检查,使自动化分析和注入核心模块变得更加困难。 使用 stack 和简单的 Bitwise 操作对字符串进行混淆处理。常量整数使用结构和循环进行混淆,以获得正确的偏移量。 核心模块具有许多功能,使攻击者能够完全控制受害者计算机。参考
pikabot分析
两个x86程序,选择32位ida打开,打开之后找起始函数start,
前面进行了一些空间开辟的操作,不重要,直接进入UsefulFunc_0函数分析
其中有一个sub_4145CC函数,跟进发现,没有什么重要信息,进入73行的InitialAndCheckDebug函数,
前面是一堆字符串进行操作,sub_410450函数,是计算了当前窗口是否处于最小化状态;跟进debugDetect3函数,
前面进行了一堆变量类型的修改,NtQuerySystemInformation跟进,
SysCall函数系统调用是操作系统提供的接口,允许用户程序请求内核执行特权操作;Syscall这一绕过edr hook
进入SysCall继续分析
SysCallTableBuild分析
进入SysCallIndexFindByHash函数之后
除了一个对页面操作的函数之外,全是对变量的操作,静态不好分析,先看SysCallTableBuild函数
从149行开始到209行都在进行peb遍历进程加载dll文件,找到后面进行后续操作的dll文件基址与导出表位置
获取导出表地址,判断读取的dll存在导出表没有,205行对字符串进行哈希校验,满足跳出
静态分析到这里之后具体实现不知道,打开x32动调调试,
先在x32中找到0040101Dh处的SysCallIndexFindByHash函数
打上断点f9运行到这里
通过堆栈可以看到前面的syscall参数是3A6A3CFF这里SysCallIndexFindByHash的参数v1就是syscall的参数
继续往后调试,观察循环peb调用dll的地方
在ida观察到地址是0040D8B4h,进入x32的相同地址打上断点
跳出循环判断后就能知道寻找的就是ntdll
获取导出函数的地址列表,判断导出函数名称是否为ZW开头
讲导出函数的地址偏移量和名称偏移量hash值存入sysCallHashTable,导出550个之后跳出
进入HashTableBuild函数
计算哈希值
哈希值计算结束之后,退出这个函数,之后sysCallTableStruc结构体就构造完成了
动调观察结构体的构造,427DC0h处就是sysCallHashTable
从这里开始到413行貌似是一个二重循环的冒泡排序,将sysCallHashTable函数按照地址重新排序(二重循环冒泡见补充
到这里SysCallTableBuild这个函数就结束了,返回调用这个函数的地方
这里对刚才构造的的结构体进行了遍历,根据传入的hash获取函数在结构体中的下标
再次跳出这个函数
直接看汇编代码
接下来调用了sub_40D0C4函数,跟进
这个函数前面进行了一些字符的混淆,
1 | result = DllBaseAddress |
函数地址的绝对偏移量=DllBaseAddress+functionadress;在上面可以看到v9=5
在这里加上了一个sub_40A19C取余,跟进sub_40A19C函数
随机调用?
返回上一级,根据刚才的分析,这个函数实现了一个ntdll中随机化函数的绝对地址+5,返回到查看地址进行动调分析
在00401052h处打断点
跳转到ntdll的模块进行运行,并且运行的函数是ZwSetLdtEntries
ZwSetLdtEntries 是 Windows 内核的一个系统调用,用于设置局部描述符表(LDT)中的条目,这里的起始位置应该是77244400h,加5之后就是现在的地址;跳转到了函数起始位置+5的地方执行
观察这一区域的所有函数调用会发现,他们的函数头都是进行一个mov eax,index的操作来进行对eax的赋值,之后的两行代码完全相同,只是会ret不同的值,这意味这如果在mov edx,…这行之前将eax设置为[x],就可以实现相当于调用起始为mov eax,[x]的函数的效果,此时再观察右上角eax,显示为036
一直找到eax 36,然后知道调用的是NtQuerySystemInformation
NtQuerySystemInformation 是一个 Windows 内核的系统调用,用于获取系统信息。
这就是indirectSyscall的效果,它通过调用随机ntdll.dll中Zw起始的函数头+5的位置,只需在此之前将eax的值设置为不同的数字,就可以实现调用另一个函数的效果
往前翻,一直找到eax 0的地方
ntdll中的mov eax,[x],是按x的顺序由小到大排列的;hash+functionaddress中的第一个functionaddress就是772429B0,之后的地址是 772429C0、772429D0……
这也就是之前通过hash遍历获取下标顺序的原因,下标的顺序和mov eax,[x]中的[x]是对应的,也就实现了通过hash调用一个ntdll中native函数的效果,甚至都不需要进入这个函数在应用层的调用地址中,从而躲避edr对所调用函数的hook。