首页
论坛
课程
招聘
[原创]震惊!某男子居然对LockBit2.0做了这种事
2021-9-28 17:16 22671

[原创]震惊!某男子居然对LockBit2.0做了这种事

2021-9-28 17:16
22671

前言:

从2013-09-13注册至今,在默默的阅览大佬们的文章学习提升自我,由于工作繁忙至今没有在论坛中发过文章,对于白嫖了那么多年的我有点惭愧,也是由于各种事情吧,这个样本分析到中期的时候无法慢慢的去品尝了,开启了走马观花模式,此次也是记录了走马观花的过程,由于时间关系也没有仔细对算法和他更多的操作性进行分析,可能会有一些写的有问题的地方也希望各位大佬多多担待。
上传图可能有点小,可以通过附件查看原版

概况:

运行环境:win10
URL:hxxp://lockbitapt6vx57t3eeqjofwgcglmutr3a35nygvokja5uuccip4ykyd.onion;
hxxps://tox.chat/download.html;
加密算法:ECC+AES

样本分析:

通过查看导出表可以得知,该程序主要利用了自解密的方式来获取自身所需要的API函数。
图片描述

反调试:

样本加载完毕后,可以代码入口点处首先获取了PEB,并且在偏移0x68处进行了0x70的比较。
图片描述
通过PEB结构体可以看出,在0x68处对应的是NtGlobalFlag,当调试状态时NtGlobalFlag的值会被赋值为0x70,所以依次确定程序首先对调试环境进行了判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
typedef struct _PEB {
/*000*/ UCHAR InheritedAddressSpace;
/*001*/ UCHAR ReadImageFileExecOptions;
/*002*/ UCHAR BeingDebugged;                // 无调试器时 = 0,有调试器时 = 1
/*003*/ UCHAR SpareBool;
/*004*/ HANDLE Mutant;
/*008*/ HINSTANCE ImageBaseAddress;
/*00C*/ VOID *LDR; 
/*010*/ PPROCESS_PARAMETERS *ProcessParameters;
/*014*/ ULONG SubSystemData;
/*018*/ HANDLE DefaultHeap;
/*01C*/ KSPIN_LOCK FastPebLock;
/*020*/ ULONG FastPebLockRoutine;
/*024*/ ULONG FastPebUnlockRoutine;
/*028*/ ULONG EnvironmentUpdateCount;
/*02C*/ ULONG KernelCallbackTable;
/*030*/ LARGE_INTEGER SystemReserved;
/*038*/ ULONG FreeList;
/*03C*/ ULONG TlsExpansionCounter;
/*040*/ ULONG TlsBitmap;
/*044*/ LARGE_INTEGER TlsBitmapBits;
/*04C*/ ULONG ReadOnlySharedMemoryBase;
/*050*/ ULONG ReadOnlySharedMemoryHeap;
/*054*/ ULONG ReadOnlyStaticServerData;
/*058*/ ULONG AnsiCodePageData;
/*05C*/ ULONG OemCodePageData;
/*060*/ ULONG UnicodeCaseTableData;
/*064*/ ULONG NumberOfProcessors;
/*068*/ LARGE_INTEGER NtGlobalFlag;         // 有调试器时会被赋值为 70h
/*070*/ LARGE_INTEGER CriticalSectionTimeout;
/*078*/ ULONG HeapSegmentReserve;
/*07C*/ ULONG HeapSegmentCommit;
/*080*/ ULONG HeapDeCommitTotalFreeThreshold;
/*084*/ ULONG HeapDeCommitFreeBlockThreshold;
/*088*/ ULONG NumberOfHeaps;
/*08C*/ ULONG MaximumNumberOfHeaps;
/*090*/ ULONG ProcessHeaps;
/*094*/ ULONG GdiSharedHandleTable;
/*098*/ ULONG ProcessStarterHelper;
/*09C*/ ULONG GdiDCAttributeList;
/*0A0*/ KSPIN_LOCK LoaderLock;
/*0A4*/ ULONG OSMajorVersion;
/*0A8*/ ULONG OSMinorVersion;
/*0AC*/ USHORT OSBuildNumber;
/*0AE*/ USHORT OSCSDVersion;
/*0B0*/ ULONG OSPlatformId;
/*0B4*/ ULONG ImageSubsystem;
/*0B8*/ ULONG ImageSubsystemMajorVersion;
/*0BC*/ ULONG ImageSubsystemMinorVersion;
/*0C0*/ ULONG ImageProcessAffinityMask;
/*0C4*/ ULONG GdiHandleBuffer[0x22];
/*14C*/ ULONG PostProcessInitRoutine;
/*150*/ ULONG TlsExpansionBitmap;
/*154*/ UCHAR TlsExpansionBitmapBits[0x80];
/*1D4*/ ULONG SessionId;
} PEB, *PPEB;

PEB寻址

检测环境不存在调试环境时,接着会将32赋值到v198中,并将字符串GDIPLUS赋值给到了v199,利用循环将大写的GDIPLUS转换成小写并且拼接.dll后缀。
图片描述
通过动态调试,得到gdiplus.dll
图片描述
判断0x4F081C是否为空,如果为空则进行计算,并将返回值赋值给到0x4F081C内存中。
图片描述
  在NT内核系统中fs寄存器指向TEB结构,TEB+0x30也就是mov eax, large fs:30h处指向PEB结构,PEB+0x0c处指向PEB_LDR_DATA结构,PEB_LDR_DATA+0x1c处存放一些指向动态链接库信息的链表地址,DLL第一个指向ntdl.dll,第三个就是kernel32.dll的。

 

图片描述
FS段寄存器作为选择子指向当前的活动线程的TEB结构(Thread Environment Block)注释。在TEB偏移的0x30处,就是指向PEB(Process Environment Block)的指针。而在PEB偏移的0x0c处是指向PEB_LDR_DATA结构的指针。PEB_LDR_DATA的结构如下:

1
2
3
4
5
6
7
8
9
typedef struct _PEB_LDR_DATA
{
 ULONG Length; // +0x00
 BOOLEAN Initialized; // +0x04
 PVOID SsHandle; // +0x08
 LIST_ENTRY InLoadOrderModuleList; // +0x0c
 LIST_ENTRY InMemoryOrderModuleList; // +0x14
 LIST_ENTRY InInitializationOrderModuleList;// +0x1c
} PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24

在PEB_LDR_DATA结构中,又包含三个LIST_ENTRY结构体分别命名为:

1
2
3
InLoadOrderModuleList;           模块加载顺序
InMemoryOrderModuleList;        模块在内存中的顺序
InInitializationOrderModuleList;     模块初始化装载顺序

LIST_ENTRY其结构定义如下:

1
2
3
4
typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

这个双链表指向进程装载的模块,结构中的每个指针,指向了一个LDR_DATA_TABLE_ENTRY 的结构:
我们来看看这个结构的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
typedef struct _LDR_DATA_TABLE_ENTRY
{
     LIST_ENTRY InLoadOrderLinks;
     LIST_ENTRY InMemoryOrderLinks;
     LIST_ENTRY InInitializationOrderLinks;
     PVOID DllBase;
     PVOID EntryPoint;
     ULONG SizeOfImage;
     UNICODE_STRING FullDllName;
     UNICODE_STRING BaseDllName;
     ULONG Flags;
     WORD LoadCount;
     WORD TlsIndex;
     union
     {
          LIST_ENTRY HashLinks;
          struct
          {
               PVOID SectionPointer;
               ULONG CheckSum;
          };
     };
     union
     {
          ULONG TimeDateStamp;
          PVOID LoadedImports;
     };
     _ACTIVATION_CONTEXT * EntryPointActivationContext;
     PVOID PatchInformation;
     LIST_ENTRY ForwarderLinks;
     LIST_ENTRY ServiceTagLinks;
     LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

为了不被勒索所污染我们的调试环境,我们使用calc进行演示。
此时我们可以看到InLoadOrderModuleList.Flink指针指向的地址是000001c83e382bb0

 

图片描述
可以看出000001c83e382bb0所在的模块地址是64790000,也就是calc.exe的内存装载地址,它的flink指针指向了000001c83e3829e0,1a600000它就是ntdll.dll的内存装载地址,000001c83e3829e0的flink指向了000001c83e383100,18a60000它就是Kerenl32.dll的内存装载地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
0:000> dd 000001c83e382bb0
000001c8`3e382bb0  3e3829e0 000001c8 1a7653d0 00007ffb
000001c8`3e382bc0  3e3829f0 000001c8 1a7653e0 00007ffb
000001c8`3e382bd0  00000000 00000000 00000000 00000000
000001c8`3e382be0  64790000 00007ff6 64791820 00007ff6
000001c8`3e382bf0  0000b000 00000000 003a0038 00000000
000001c8`3e382c00  3e382768 000001c8 00120010 00000000
000001c8`3e382c10  3e382790 000001c8 0000a2cc 0000ffff
000001c8`3e382c20  1a7651d0 00007ffb 1a7651d0 00007ffb
0:000> dd 000001c83e3829e0
000001c8`3e3829e0  3e383100 000001c8 3e382bb0 000001c8
000001c8`3e3829f0  3e383110 000001c8 3e382bc0 000001c8
000001c8`3e382a00  3e3837e0 000001c8 1a7653f0 00007ffb
000001c8`3e382a10  1a600000 00007ffb 00000000 00000000
000001c8`3e382a20  001f0000 00000000 003c003a 00000000
000001c8`3e382a30  3e382870 000001c8 00140012 00000000
000001c8`3e382a40  1a72c428 00007ffb 0000a2c4 0000ffff
000001c8`3e382a50  1a765180 00007ffb 1a765180 00007ffb
0:000> dd 000001c83e383100
000001c8`3e383100  3e3837c0 000001c8 3e3829e0 000001c8
000001c8`3e383110  3e3837d0 000001c8 3e3829f0 000001c8
000001c8`3e383120  1a7653f0 00007ffb 3e3837e0 000001c8
000001c8`3e383130  18a60000 00007ffb 18a77c70 00007ffb
000001c8`3e383140  000b2000 00000000 00420040 00000000
000001c8`3e383150  3e3832d0 000001c8 001a0018 00000000
000001c8`3e383160  3e3832f8 000001c8 000ca2cc 0000ffff
000001c8`3e383170  1a765160 00007ffb 1a765160 00007ffb

知道PEB寻址之后,我们回过头来看勒索程序它所要找到的dll地址是什么。
此时,Flink地址:0x772FE0,
图片描述
[edi+0x30]指向的是ntdll.dll的内存装载位置,并将硬编码0x811C9DC5存入第一个变量当中。
图片描述
通过特征判断,这段程序主要是利用了特征比方式来判断所需要用到的dll的地址。
图片描述
通过返回结果可以看到,所匹配到的dll为Kernel32.dll,依次,我们可以将函数名称进行改名为KenDllAddr。
图片描述
改名后。
图片描述
获取到dll的装载地址后,将地址当作参数传入了4122E0中,经过之前我们的分析可以大概推断出,这个函数主要的功能是通过获取到的dll来寻找程序后续所需要用到的API函数地址,我们来验证一下猜想。
图片描述
我们F5结合反汇编来看*this指针所指向的位置是Kernel32.dll的装载地址,也就是Kernel32的MZ位置。
图片描述
通过结构体中我们可以看到0x3C指向的是e_lfanew,它的值指向了PE文件的文件头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct _IMAGE_DOS_HEADER {
+00 h WORD e_magic // DOS可执行文件标记 MZ(4Dh 5Ah)
+02 h WORD e_cblp ; Bytes on last page of file
+04 h WORD e_cp ; Pages in file
+06 h WORD e_crlc ; Relocations
+08 h WORD e_cparhdr ; Size of header in paragraphs
+0A h WORD e_minalloc ; Minimun extra paragraphs needs
+0C h WORD e_maxalloc ; Maximun extra paragraphs needs
+0E h WORD e_ss // DOS代码的初始化堆栈SS
+10 h WORD e_sp // DOS代码的初始化堆栈指针SP
+12 h WORD e_csum ; Checksum
+14 h WORD e_ip // DOS代码的初始化指令入口[指针IP]
+16 h WORD e_cs // DOS代码的初始堆栈入口
+18 h WORD e_lfarlc ; File Address of relocation table
+1A h WORD e_ovno ; Overlay number
+1C h WORD e_res[4] ; Reserved words
+24 h WORD e_oemid ; OEM identifier(for e_oeminfo)
+26 h WORD e_oeminfo ; OEM information;e_oemid specific
+29 h WORD e_res2[10] ; Reserved words
+3C h LONG e_lfanew // 指向PE文件头
} IMAGE_DOS_HEADER ENDS

mov edx, [eax+ebx+78h]相当于:772C0000+E8+78h,通过结构体我们可以看到,该地址指向的是DataDirectory,也就是数据结构表,将获取到的偏移地址保存在了edx中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
typedef struct _IMAGE_OPTIONAL_HEADER
{
+18 h WORD Magic; // 标志字, ROM 映像(0107h),普通可执行文件(010Bh
+1A h BYTE MajorLinkerVersion; // 链接程序的主版本号
+1B h BYTE MinorLinkerVersion; // 链接程序的次版本号
+1C h DWORD SizeOfCode; // 所有含代码的节的总大小
+20 h DWORD SizeOfInitializedData; // 所有含已初始化数据的节的总大小
+24 h DWORD SizeOfUninitializedData; // 所有含未初始化数据的节的大小
+28 h DWORD AddressOfEntryPoint; // 程序执行入口RVA
+2C h DWORD BaseOfCode; // 代码的