个人学习日记

关于LordPE的AntiDump

Word count: 657Reading time: 2 min
2020/06/10 Share

原由

今天在看加密解密4关于脱壳部分的过程中,下面这一段代码让我感觉迷惑。

mark

让我感到奇怪的是,为什么这么一段代码可以用来Anti Dump的。

找出答案

在我搜索资料的过程中,发现关于LordPE dump功能的一些事情。我们将一个程序dump下来,有这么几个步骤:

1
2
3
1. 在系统中找到目标进程
2. 在进程中确定进程的大小ImageSize
3. 把进程中的数据保存到文件

这里有个问题就是ImageSize是怎么获取的。在我们的PE头里的Image_Option_Header里有一个成员叫做SizeOfImage,但是这个成员在加壳程序被修改是很常见的。因此在LordPE中并不是获取这个成员来获取ImageSize的。

在LordPE中,是使用Module32Next来获取进程的基本信息,包括ImageSize。而MODULEENTRY32结构的数据是从哪里来的呢?答案是从PEB进程环境块里获取的。以下是PEB的部分结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct   _PEB (sizeof=488)
+000 byte InheritedAddressSpace
+001 byte ReadImageFileExecOptions
+002 byte BeingDebugged
+003 byte SpareBool
+004 void *Mutant
+008 void *ImageBaseAddress
+00c struct _PEB_LDR_DATA *Ldr
+010 struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters
+014 void *SubSystemData
+018 void *ProcessHeap
+01c void *FastPebLock
+020 void *FastPebLockRoutine
+024 void *FastPebUnlockRoutine

通过偏移0xC,我们可以找到_PEB_LDR_DATA,这是_PEB_LDR_DATA的结构:

1
2
3
4
5
6
7
8
9
10
11
12
struct _PEB_LDR_DATA
{
ULONG Length; //0x0
UCHAR Initialized; //0x4
VOID* SsHandle; //0x8
struct _LIST_ENTRY InLoadOrderModuleList; //0xc
struct _LIST_ENTRY InMemoryOrderModuleList; //0x14
struct _LIST_ENTRY InInitializationOrderModuleList; //0x1c
VOID* EntryInProgress; //0x24
UCHAR ShutdownInProgress; //0x28
VOID* ShutdownThreadId; //0x2c
};

该结构的后三个成员是指向LDR_MODULE链表结构中相应的三条双向链表头的指针,分别是按照加载顺序、在内存中的地址顺序和初始化顺序排列的模块信息结构的指针。于是通过它,我们能够访问到LDR_MODULE结构。以下是LDR_MODULE结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct _LDR_MODULE {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage; //进程的image size // 0x20
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;

可以看到,在0x20的位置,存放着程序的SizeOfImage。LordPE就是通过这样的方式来获取到程序的ImageSize的,因此我们可以通过上面几条汇编代码,来修改掉这个PEB里的值来对抗LordPE的dump。

1
2
3
4
mov eax,dword ptr fs:[30h]      // 获得PEB地址
mov eax,dword ptr ds:[eax+0ch] // _PEB_LDR_DATA
mov eax,dword ptr ds:[eax+0ch] // _LDR_MODULE的首地址
mov dword ptr [eax+20h],1000h // eax+20是保存image size的地方

使用LordPE的修正镜像大小功能,即可发现,旧镜像大小Lord PE就是使用上面Module32Next的方法获取到ImageSize的,而新镜像大小则是通过Image_Option_Header来获取到SizeOfImage的。

mark

参考资料

https://bbs.pediy.com/thread-17624.htm

CATALOG
  1. 1. 原由
  2. 2. 找出答案
  3. 3. 参考资料