SMC基本原理

SMC(Software-Based Memory Encryption)是一种局部代码加密技术。

SMC的基本原理是在编译可执行文件时,将需要加密的代码区段(例如函数、代码块等)单独编译成一个section(段),并将其标记为可读、可写、不可执行(readable, writable, non-executable),然后通过某种方式在程序运行时将这个section解密为可执行代码,并将其标记为可读、可执行、不可写(readable, executable, non-writable)。这样,攻击者就无法在内存中找到加密的代码,从而无法直接执行或修改加密的代码。

主要步骤:

  1. 读取PE文件并找到需要加密的代码段。
  2. 将代码段的内容进行异或加密,并更新到内存中的代码段。
  3. 重定向代码段的内存地址,使得加密后的代码能够正确执行。
  4. 执行加密后的代码段

上面都比较官方,下面是我自己的理解:

SMC是一种加密的手段,主要是对地址进行加密,比如我现在遇到的这个题,对地址进行了加密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+---------------------+
| 读取PE文件 |
| 找到代码段 |
+---------------------+
|
|
v
+---------------------------------+
| 对代码段进行异或加密 |
| 并更新到内存中的代码段 |
+---------------------------------+
|
|
v
+---------------------------------+
| 重定向代码段的内存地址, |
| 使得加密后的代码能够正确执行 |
+---------------------------------+
|
|
v
+---------------------+
| 执行加密后的代码段 |
+---------------------+

过程:读取PE文件=>找到代码段=>对代码段进行加密【听说主要是xor】=>更新到内存中的代码段=>重定向代码段的内存地址,使加密后的代码能正常执行 => 执行加密后的代码段

这个被加密后的代码段是不能被IDA之间反编译的。

用伪代码来解释这个技术:

1
2
3
4
5
6
7
8
9
10
11
proc main:
............
IF .运行条件满足
CALL DecryptProc (Address of MyProc)//对某个函数代码解密
........
CALL MyProc //调用这个函数
........
CALL EncryptProc (Address of MyProc)//再对代码进行加密,防止程序被Dump

......
end main

在调用某个函数的时候,需要对这个函数进行加密。

CTF题

首先,这种SMC加密方式,用IDA在F5的时候会出现错误。

这种题,就是在你使用某个函数之前会莫名其妙的多一个函数,多出来的这个函数多数是用API来进行操作的,并且这个函数是对地址直接进行操作,而不是地址上的值。

比如:

image-20230919161516839

伴随SMC加密的总会有某些API对地址的操作权限进行修改。比如这里的VirtualProtect。该API可以对地址的读写情况进行修改,代码段?数据段?

在做这种题的时候,会用到IDApython。来对地址进行修改回去。

然后找到被修改的地址,按下“c”让IDA重新分析。当然也可能是函数拿就可能是“p”重新分析函数。