movobfuscator混淆


简介

movobfuscator 是一个通过将常规 x86 指令替换为等价的 mov 指令来完成代码混淆的混淆器,得益于 mov 指令满足图灵完备性质,所有的指令都可以通过由 mov 指令组成的代码片段进行等价代换,同时保持程序逻辑不变。

由于 mov 混淆的特殊性,目前暂时没有较为高效的反混淆手段,现阶段如 demovobfuscator 等反混淆器可以完成初步的去混淆工作。

movobfuscator

  • 构建

如果要在 64 位系统上构建,必须有 32 位的 libc 库

1
apt-get install libc6-dev-i386
1
2
3
4
git clone https://github.com/xoreaxeaxeax/movfuscator
cd movfuscator
./build.sh
sudo ./install.sh
  • 使用
1
movcc ./demo.c -o mov     

利用objdump查看混淆后的效果

1
objdump -d ./demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
804a638:       c7 05 64 51 3f 08 9c    movl   $0x85f519c,0x83f5164
804a63f: 51 5f 08
804a642: 8b 04 8d 60 51 3f 08 mov 0x83f5160(,%ecx,4),%eax
804a649: 8b 15 50 c0 04 08 mov 0x804c050,%edx
804a64f: 89 10 mov %edx,(%eax)
804a651: 8b 15 54 c0 04 08 mov 0x804c054,%edx
804a657: 89 50 04 mov %edx,0x4(%eax)
804a65a: 8b 15 58 c0 04 08 mov 0x804c058,%edx
804a660: 89 50 08 mov %edx,0x8(%eax)
804a663: 8b 15 5c c0 04 08 mov 0x804c05c,%edx
804a669: 89 50 0c mov %edx,0xc(%eax)
804a66c: 8b 15 60 c0 04 08 mov 0x804c060,%edx
804a672: 89 50 10 mov %edx,0x10(%eax)
804a675: 8b 15 64 c0 04 08 mov 0x804c064,%edx
804a67b: 89 50 14 mov %edx,0x14(%eax)
804a67e: a1 48 51 3f 08 mov 0x83f5148,%eax
804a683: 8b 04 85 40 51 3f 08 mov 0x83f5140(,%eax,4),%eax
804a68a: c7 00 00 00 00 00 movl $0x0,(%eax)
804a690: 8b 25 20 51 3f 08 mov 0x83f5120,%esp
804a696: 8e c8 mov %eax,%cs

demovobfuscator

demovobfuscator混淆器我们可以本地构建也可以使用现成的 docker 镜像。

构建

  • 安装依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1.libcapstone  
sudo git clone https://github.com/aquynh/capstone.git
cd capstone/
make
sudo make install

2.libz3
sudo git clone https://github.com/Z3Prover/z3.git
cd z3
python scripts/mk_make.py
cd build
make
sudo make install

3.libkeystone
sudo git clone https://github.com/keystone-engine/keystone.git
cd keystone/
sudo mkdir build
cd build/
sudo ../make-share.sh
sudo make install


4.apt-get install libssl-dev
  • 构建
1
2
3
git clone https://github.com/kirschju/demovfuscator.git  
cd demovfuscator
make
  • 使用
1
./demov demo -o demo2

docker

我在本地构建的时候出了不少问题,即使本地构建成功也无法成功使用demovobfuscator。

后来发现了一个公开的 docker 镜像,索性就直接用 docker 了。

1
2
3
4
5
❯ docker search demovfuscator
NAME DESCRIPTION STARS OFFICIAL
iyzyi/demovfuscator demovfuscator,反混淆movfuscator生成的混淆二… 0

❯ docker pull demovfuscator

拉下来镜像之后就直接启动为容器使用就行了。

例题

2024YLCTF mmmmmmmov

IDA打开,一眼望去全是mov指令。

一眼丁真,这是加了 movobfuscator 混淆。

我们需要通过 demovobfuscator 工具来去混淆。

使用 demovobfuscator 工具去混淆

1
2
3
4
5
6
#将文件复制到 docker 容器
docker cp ./mmmmmmmov df30236a690f:/root/mmmmmmmov
#使用 demovobfuscator
./demov mmmmmmmov -o mmmmmmmov_patch
#从容器复制文件到本地
docker cp df30236a690f:/root/mmmmmmmov_patch ./mmmmmmmov_patch
  • 去混淆后

感觉效果不佳。。。

只能继续分析了

在函数窗口发现 AES 加密函数,判断一个程序是 AES 加密。

字符串窗口发现了一个疑似密钥的东西。

并且看到了获取 GZCTF_FLAG 字符。

跟进查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a = 0x7891d5ad8468ea8c9f46b26125d324ae  
a1 = 0xa0f17ec880ce6db9b117398dde4bf5a6
a2 = 0x8e9dabf1d863df6209cad8928f483d5e
b = long_to_bytes(a)
b1 = long_to_bytes(a1)
b2 = long_to_bytes(a2)
c = b''
c1 = b''
c2 = b''
for i in b:
c += long_to_bytes(i^0x11)
for i in b1:
c1 += long_to_bytes(i^0x22)
for i in b2:
c1 += long_to_bytes(i^0x22)

最后调用 AES_ECB 解密

  • exp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from Crypto.Util.number import *  
from Crypto.Cipher import AES
a = 0x7891d5ad8468ea8c9f46b26125d324ae
a1 = 0xa0f17ec880ce6db9b117398dde4bf5a6
a2 = 0x8e9dabf1d863df6209cad8928f483d5e
b = long_to_bytes(a)
b1 = long_to_bytes(a1)
b2 = long_to_bytes(a2)
c = b''
c1 = b''
c2 = b''
for i in b:
c += long_to_bytes(i^0x11)
for i in b1:
c1 += long_to_bytes(i^0x22)
for i in b2:
c1 += long_to_bytes(i^0x33)
aes_ecb = AES.new(b'0123456789abcdef',1)
d1 = aes_ecb.decrypt(c)
d2 = aes_ecb.decrypt(c1)
d3 = aes_ecb.decrypt(c2)
print(d1,d2,d3)