恶意代码分析实战 第十三章 实验部分

2022-03-30  本文已影响0人  doinb1517

实验

Q

Lab13-1

1、比较恶意代码中的字符串(字符串命令的输出)与动态分析提供的有用信息,基于这些比较,哪些元素可能被加密?

2、使用IDAPro搜索恶意代码中字符串xor,以此来查找潜在的加密,你发现了哪些加密类型?

3、恶意代码使用什么密钥加密,加密了什么内容?

4、使用静态工具FindCrypt2Krypto ANALyzer(KANAL)以及 IDA熵插件识别一些其他类型的加密机制,你发现了什么?

5、什么类型的加密被恶意代码用来发送部分网络流量?

6、Base64编码函数在反汇编的何处?

7、恶意代码发送的 Base64加密数据的最大长度是什么?加密了什么内容?

8、恶意代码中,你是否在 Base64加密数据中看到了填充字符(=或者==)?

9、这个恶意代码做了什么?

Lab13-2

1、使用动态分析,确定恶意代码创建了什么?

2、使用静态分析技术,例如 xor指令搜索、FindCrypt2KANAL以及IDA熵插件,查找潜在的加密,你发现了什么?

3、基于问题1的回答,哪些导入函数将是寻找加密函数比较好的一个证据?

4、加密函数在反汇编的何处?

5、从加密函数追溯原始的加密内容,原始加密内容是什么?

6、你是否能够找到加密算法?如果没有,你如何解密这些内容?

7、使用解密工具,你是否能够恢复加密文件中的一个文件到原始文件?

Lab13-3

1、比较恶意代码的输出字符串和动态分析提供的信息,通过这些比较,你发现哪些元素可能被加密?

2、使用静态分析搜索字符串xor来查找潜在的加密。通过这种方法,你发现什么类型的加密?

3、使用静态工具,如FindCrypt2KANAL 以及 IDA嫡插件识别一些其他类型的加密机制。发现的结果与搜索字符XOR结果比较如何?

4、恶意代码使用哪两种加密技术?

5、对于每一种加密技术,它们的密钥是什么?

6、对于加密算法,它的密钥足够可靠吗?另外你必须知道什么?

7.恶意代码做了什么?

8、构造代码来解密动态分析过程中生成的一些内容,解密后的内容是什么?

A

Lab13-01

先拖进IDA Pro中观察,导入表中有网络连接有关的函数,怀疑有网络连接行为。还有资源相关的函数,怀疑资源节中有东西。

01_import1.png

进行网络连接函数为sub_4011c9

4011c9.png

a1来自sub_401300,就是资源节中的数据用sub_401190进行了解码。

401300.png

解码逻辑就是和0x3B进行异或操作。

01encode.png

资源节中数据如下:

01rs.png

解码后如下:

01rs2.png

所以恶意代码访问的域名是www.practicalmalwareanalysis.com

继续看a8来源,拿到了主机名的前12个字节,然后将第十三字节置为0,截断。使用sub_4010B1进行处理。

01a8.png

继续跟进sub_4010B1,看着比较麻烦,调用了sub_401000

4010b1.png

继续跟进sub_401000,调用了byte_4050E8

01401000.png

该处是一个标准的Base64索引,所以怀疑sub_4010B1应该是一个Base64编码函数,实际看代码确实是这样。

01base64.png

使用PEID的插件寻找加密,可以看到这里找到了一个Base64表,也给出了详细位置。

kanal.png

下面动态分析一下,开启wireshark抓包,我的wireshark在宿主机,恶意代码运行在win10虚拟机中,注意选择正确接口。抓到流量如下:

wireshark.png

REVTS1RPUC0zMVVN进行Base64解码,解码结果为,正是我的主机名。这也与静态分析结果相符。

01baseencode.png hostname.png

如果前面的今天分析没有将逻辑分析的很清楚,其实可以动态调试,看看sprintf格式化的url,直接提取IOC

01sprintf.png

然后看看浏览器返回的数据,因为后面要判断浏览器返回的数据的第一个字母是o,这里我们提取数据如下

01ie.png

就是拿到了一些注释,程序的基本流程就分析结束

01content.png

Lab13-02

直接运行文件,同时打开Process Monitor,可以看到在和Lab13-03.exe同级的文件夹下创建了很多新文件,而且数量还在不断增加,大小都是7042950字节。

processmonitor.png 02size.png

将文件拖进IDA Pro中进行分析。

可以看到创建的文件名是GetTickCount的返回值,返回值是系统启动以来经过的毫秒数。

gettickcount.png

使用PEID的插件寻找加密,没有任何发现。

03kanal.png

IDA Pro的插件FindCrypt也没有找到相关信息。在IDA Pro中搜索XOR的结果如下,sub_401739函数大量使用xor,查看引用

02xor.png

查看引用,可以判断sub_401851可能是加密相关的函数。

02xrf.png

sub_401070函数如下,主要作用是对桌面截屏。

void *__cdecl sub_401070(void **a1, _DWORD *a2)
{
  void *result; // eax
  HGLOBAL hMem; // [esp+0h] [ebp-78h]
  UINT dwBytes; // [esp+8h] [ebp-70h]
  char pv[4]; // [esp+Ch] [ebp-6Ch] BYREF
  LONG v6; // [esp+10h] [ebp-68h]
  UINT cLines; // [esp+14h] [ebp-64h]
  HGLOBAL v8; // [esp+24h] [ebp-54h]
  void *v9; // [esp+28h] [ebp-50h]
  HDC hdc; // [esp+2Ch] [ebp-4Ch]
  struct tagBITMAPINFO bmi; // [esp+30h] [ebp-48h] BYREF
  int v12; // [esp+5Ch] [ebp-1Ch]
  HGDIOBJ h; // [esp+60h] [ebp-18h]
  __int16 Src[7]; // [esp+64h] [ebp-14h] BYREF
  int cy; // [esp+74h] [ebp-4h]

  v12 = GetSystemMetrics(0);
  cy = GetSystemMetrics(1);
  hWnd = GetDesktopWindow();
  hDC = GetDC(hWnd);
  hdc = CreateCompatibleDC(hDC);
  h = CreateCompatibleBitmap(hDC, v12, cy);
  SelectObject(hdc, h);
  BitBlt(hdc, 0, 0, v12, cy, hDC, 0, 0, 0xCC0020u);
  GetObjectA(h, 24, pv);
  bmi.bmiHeader.biSize = 40;
  bmi.bmiHeader.biWidth = v6;
  bmi.bmiHeader.biHeight = cLines;
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biBitCount = 32;
  bmi.bmiHeader.biCompression = 0;
  bmi.bmiHeader.biSizeImage = 0;
  bmi.bmiHeader.biXPelsPerMeter = 0;
  bmi.bmiHeader.biYPelsPerMeter = 0;
  bmi.bmiHeader.biClrUsed = 0;
  bmi.bmiHeader.biClrImportant = 0;
  dwBytes = cLines * 4 * ((32 * v6 + 31) / 32);
  hMem = GlobalAlloc(0x42u, dwBytes);
  bmi.bmiColors[0] = (RGBQUAD)GlobalLock(hMem);
  GetDIBits(hDC, (HBITMAP)h, 0, cLines, *(LPVOID *)bmi.bmiColors, &bmi, 0);
  *(_DWORD *)&Src[5] = 54;
  *(_DWORD *)&Src[1] = dwBytes + 54;
  Src[0] = 19778;
  v8 = GlobalAlloc(0x42u, dwBytes + 54);
  v9 = GlobalLock(v8);
  memcpy(v9, Src, 0xEu);
  memcpy((char *)v9 + 14, &bmi, 0x28u);
  memcpy((char *)v9 + 54, *(const void **)bmi.bmiColors, dwBytes);
  GlobalUnlock(hMem);
  GlobalFree(hMem);
  ReleaseDC(hWnd, hDC);
  DeleteDC(hdc);
  DeleteObject(h);
  result = v9;
  *a1 = v9;
  *a2 = dwBytes + 54;
  return result;
}

关于此部分代码的分析可以参考MSDN

https://docs.microsoft.com/en-us/windows/win32/gdi/capturing-an-image

开始动态调试,在0x401880位置打上断点,这时栈上是缓冲区地址(0x030F5020)和大小(0x006B7786)。

40181f.png

查阅资料可知此处格式为BMP,详细信息参考wiki:https://zh.wikipedia.org/wiki/BMP

偏移量 大小 用途
0000h 2字节 用于标识BMP和DIB文件的魔数,一般为0x42 0x4D,即ASCII的BM。以下为可能的取值:BM – Windows 3.1x, 95, NT, ... etc.BA – OS/2 struct Bitmap ArrayCI – OS/2 struct Color IconCP – OS/2 const Color PointerIC – OS/2 struct IconPT – OS/2 Pointer
0002h 4字节 BMP文件的大小(单位为字节)
0006h 2字节 保留;实际值因创建程序而异
0008h 2字节 保留;实际值因创建程序而异
000Ah 4字节 位图数据(像素数组)的地址偏移,也就是起始地址。

再看缓冲区的内容,第一二个字节为0x420x4D,后面四个字节为0x6B7786就是十进制的7,042,950,和最初发现的temp文件大小是一致的。

接下来到解密环节,可以直接将未加密的文件给dump出来,脚本如下:

from idc import *

RunTo(0x401880)
GetDebuggerEvent(WFNE_SUSP, -1)
stack = GetRegValue("esp")
buffer_addr = Dword(stack)
print("buffer_addr:{}".format(hex(buffer_addr)))
buffer_length = Dword(stack + 4)
print("buffer_length:{}".format(hex(buffer_length)))



tmp_list = []
for byte in idc.GetManyBytes(buffer_addr, buffer_length):
    tmp_list.append(byte)

with open("dump.bmp", "wb") as f:
    f.write(bytes(tmp_list))
print("success")
02dump.png

dump出的文件如下,可以看到是一个全屏截图。

bmp文件渲染不了。。。

假设此加密函数是可逆的(可以对加密后的数据再次运行加密函数得到加密前的数据),可以使用手动或者自动化的方式解密。

使用x32dbg进行解密

使用winhex打开加密后的文件,以16进制形式复制。再使用x32dbg打开Lab13-02.exe,在0x4018800x40190A两处下断点,复制加密后的数据到buffer地址,再F9运行,即可得到解密后的文件,将后缀名改为.bmp即可打开

02copy.png

使用脚本对上面操作自动化

//使用PathchByte()对内存数据进行修改(不适合修改大量数据,时间非常久)

eg:对XOR的数据进行解密
addr = 0xaaaa
for i in range(xxxx):
    PatchByte(addr +i, Byte(addr + i)^ 0x123)
    
eg:读取文件数据进行Patch
with open(file_path, "rb") as f:
    buffer = f.read()
    for index, byte in enumerate(buffer):
        PatchByte(buffer_addr +index, byte)

回答:

1、在当前目录创建了大小为7,042,950byte的文件,文件名为temp加8个十六进制数

2、XOR大量出现在sub_401739,其他检测加密的插件没有发现什么有效信息。

3、WriteFile调用之前可能会出现加密逻辑。

4、加密函数是sub_40181F

5、原内容是屏幕截图

6、可以在文件未加密之前dump出来,也可以对加密的文件再次执行加密函数进行解密

7、还原文件不再赘述

Lab13-03

使用IDA Pro打开文件,查看strings窗口,可以看到可能使用了自定义的Base64加密。

03strings.png

可以看到函数sub_4015B7可能使用了AES加密数据。

034015b7.png

使用PEID的插件KANAL也发现了AES加密的特征。

03kanal1111.png

sub_401AC2sub_4015B7两个函数都和加密相关,中间部分有网络连接行为。

03connect.png

修改Lab13-03.exe运行机器的hosts文件,将对应IP改为我们自己的机器,使用NC查看连接

03nc.png

捕获的数据包如下,根据行为可以判断应该是一个反弹shell程序,但是对应输出为乱码,应该是进行了加密。

03connect_pcap.png

开始分析代码,查找xor指令,去掉清空寄存器和库函数相关的指令,重命名相关函数。(快捷键N

重命名函数名 函数地址
s_xor1 401AC2
s_xor2 40223A
s_xor3 4027ED
s_xor4 402DA8
s_xor5 403166
s_xor6 403990

使用IDA Pro的插件寻找加密,可以看到运用了AES加密,对应有三个常量,分别查看引用。

03findcrypt2.png

0x40C908地址上的数据在s_xor1s_xor2s_xor4中被使用

0x40CA08地址上的数据在s_xor3s_xor5中被使用

0x40CB08地址上的数据在s_xor2s_xor4中被使用

查看0x40CB08位置上的数据,可以看到这是硬编码的S Box,可以重命名为s_box。与此数据关联的函数与AES加密相关。

03sbox.png

查看0x40CA08位置上的数据,可以看到这是硬编码的逆 S Box,可以重命名为reverse-s_box。与此数据关联的函数与AES解密相关。

03_reverse_s_box.png

查看s_xor6的交叉引用,函数sub_40352D调用了s_xor6

03_s_xor6.png

查看sub_40352D调用了那些函数。可以判断s_xor6也是和AES加密相关,将sub_40352D重命名为s_AES_encrypt

03_40352d_to.png

查看s_xor5的交叉引用,该函数在0x4037EE0x40392D位置被调用了,但是这两个位置并没有被识别为代码,说明这个解密函数可能没有被调用执行。

查看函数s_xor1首先有几个判断条件,条件不正确时给出错误提示,而且包含以下部分,所以判断这应该是AES加密函数的初始部分。

密钥扩展

字循环

字节代换,涉及到S盒

轮常量异或 (byte_40FB08

_main函数中调用了s_xor1函数,在调用此函数之前,使用了mov ecx, offset unk_412EF8,查看unk_412EF8的交叉引用,发现几个调用的地方都是这样使用,可以判断unk_412EF8是一个初始化的对象AES。(这里的调用方式是thiscall,第一个参数this保存在ecx32位

参考:https://zh.wikipedia.org/wiki/X86%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A#thiscall

查看AES加密函数sub_40352D的交叉引用,发现是在ReadFileWriteFile之间被调用的。该函数是sub_40132B

0340352d.png

继续向上查找交叉引用,发现这是一个新的线程,重命名为aes_thread

aes_new_thread.png

同理可以重命名Base64相关函数,Base64解密函数和AES加密函数都出现在函数sub_4015B7中,这两个新线程与两个管道和一个cmd的输入输出相关联:

base64_and_aes.png

分析到这里基本流程已经清晰,将命令dir使用自定义Base64加密,加密以后为BInaEi==,重新抓取流量。

03base642.png

对上述response流量进行AES解密,结果符合预期。

03aesde.png

使用AES解密脚本进行解密,模式为CBC

# pip install pycryptodome
from Crypto.Cipher import AES
import binascii

raw = 'eb 63 85 35 e8 45 cc e9  5c 92 36 9d 31 d5 3c 01' + \
      '8e bf e5 8b 06 e1 48 3f  42 5c 5a 0a 4c 75 b2 fa' + \
      '7a c5 3c 27 f2 04 d2 25  d8 e6 c5 d5 78 03 34 98' + \
      '49 5e 4f fd f7 dd 63 a6  91 0e 81 06 cc a8 62 ac' + \
      '74 f2 4a 26 e7 b2 55 03  d3 71 c8 a9 4c 61 c0 65'
ciphertext = binascii.unhexlify(raw.replace(' ', ''))
obj = AES.new('ijklmnopqrstuvwx', AES.MODE_CBC)
print obj.decrypt(ciphertext)

练习题目

分析恶意文件 f622a03f9c746e551b6467930413fff9,分析该程序是如何加密恶意负载的。提取相应IOC

微步在线:https://s.threatbook.cn/report/file/f73c40dd16a7299eb7ae42283e5d37757d43625a2aa95f0a03c982dd5051ebd4/?sign=history&env=win7_sp1_enx86_office2013

此文件为真实病毒,注意防护

参考

【解决IDA Python报错】https://bbs.pediy.com/thread-269644.htm

【对称密码体制和非对称密码体制】https://www.cnblogs.com/Leo_wl/p/10714011.html

【AES加密算法的详细介绍与实现】https://blog.csdn.net/qq_28205153/article/details/55798628

【AES C语言实现】https://www.ghostscript.com/doc/base/aes.c

上一篇下一篇

猜你喜欢

热点阅读