第六届西湖论剑网络安全大赛-Misc Isolated Machine Memory Analysis Writeup

本文赛后与zysgmzb共同完成

Isolated Machine Memory Analysis:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
题目名称:
Isolated Machine Memory Analysis

题目内容:
张三,现用名叫Charlie,在一家外企工作,负责flag加密技术的研究。为了避免flag泄露,这家企业制定了严格的安全策略,严禁flag离开研发服务器,登录服务器必须经过跳板机。张三使用的跳板机是一台虚拟机,虽然被全盘加密没法提取,但好消息是至少还没关机。 免责声明:本题涉及的人名、单位名、产品名、域名及IP地址等均为虚构,如有雷同纯属巧合。 注:本题模拟真实研发环境,解题有关的信息不会出现在人名、域名或IP地址等不合常理的地方。链接:https://pan.baidu.com/s/1WESej-pyjWKZni7drZGTig?pwd=cq46 提取码:cq46

题目难度:
中等

Hint:
hint1:在张三的电脑上发现一张截图,看起来应该是配置跳板机时无意留下的。https://c.img.dasctf.com/images/2022117/1667786365444-ba60f1f9-54fb-4704-8ff8-896647b30774.png

hint2:为什么这个Windows内存镜像是ELF格式?

hint3:https://github.com/volatilityfoundation/volatility/wiki/Virtual-Box-Core-Dump#meta-data

imageinfo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
crazyman@ubuntu:~/forensics/volatility$ python2 vol.py -f /home/crazyman/Desktop/CharlieBrown-PC.elf imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO : volatility.debug : Determining profile based on KDBG search...
Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_24000, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_24000, Win7SP1x64_23418
AS Layer1 : WindowsAMD64PagedMemory (Kernel AS)
AS Layer2 : VirtualBoxCoreDumpElf64 (Unnamed AS)
AS Layer3 : FileAddressSpace (/home/crazyman/Desktop/CharlieBrown-PC.elf)
PAE type : No PAE
DTB : 0x187000L
KDBG : 0xf80003c40130L
Number of Processors : 2
Image Type (Service Pack) : 1
KPCR for CPU 0 : 0xfffff80003c42000L
KPCR for CPU 1 : 0xfffff88004440000L
KUSER_SHARED_DATA : 0xfffff78000000000L
Image date and time : 2022-11-01 16:26:18 UTC+0000
Image local date and time : 2022-11-01 09:26:18 -0700

列进程,pslist:

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
crazyman@ubuntu:~/forensics/volatility$ python2 vol.py -f /home/crazyman/Desktop/CharlieBrown-PC.elf --profile=Win7SP1x64 pslist
Volatility Foundation Volatility Framework 2.6.1
Offset(V) Name PID PPID Thds Hnds Sess Wow64 Start Exit
------------------ -------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------
0xfffffa8003670470 System 4 0 88 389 ------ 0 2022-11-02 07:10:54 UTC+0000
0xfffffa80046e4040 smss.exe 228 4 3 35 ------ 0 2022-11-02 07:10:54 UTC+0000
0xfffffa8004debb00 csrss.exe 316 304 9 365 0 0 2022-11-02 07:10:55 UTC+0000
0xfffffa8004d8bb00 psxss.exe 356 228 19 791 0 0 2022-11-02 07:10:55 UTC+0000
0xfffffa8004d893f0 csrss.exe 364 344 9 184 1 0 2022-11-02 07:10:55 UTC+0000
0xfffffa8004e10660 winlogon.exe 396 344 3 117 1 0 2022-11-02 07:10:55 UTC+0000
0xfffffa8004df0790 wininit.exe 404 304 3 82 0 0 2022-11-02 07:10:55 UTC+0000
0xfffffa8004d227f0 services.exe 460 404 7 207 0 0 2022-11-02 07:10:55 UTC+0000
0xfffffa8004d2f060 lsass.exe 476 404 6 628 0 0 2022-11-02 07:10:56 UTC+0000
0xfffffa8004d35a70 lsm.exe 484 404 10 153 0 0 2022-11-02 07:10:56 UTC+0000
0xfffffa8004e555e0 svchost.exe 584 460 9 349 0 0 2022-11-02 07:10:56 UTC+0000
0xfffffa8004d307a0 VBoxService.ex 648 460 13 116 0 0 2022-11-02 07:10:56 UTC+0000
0xfffffa8004f41560 svchost.exe 716 460 7 240 0 0 2022-11-01 16:10:57 UTC+0000
0xfffffa8004f726b0 svchost.exe 800 460 18 413 0 0 2022-11-01 16:10:57 UTC+0000
0xfffffa8004f8d710 svchost.exe 840 460 29 1063 0 0 2022-11-01 16:10:57 UTC+0000
0xfffffa8004fad4f0 svchost.exe 900 460 9 285 0 0 2022-11-01 16:10:57 UTC+0000
0xfffffa8004fc5460 svchost.exe 956 460 9 270 0 0 2022-11-01 16:10:57 UTC+0000
0xfffffa8004fdf8c0 svchost.exe 1000 460 16 383 0 0 2022-11-01 16:10:57 UTC+0000
0xfffffa8004fe6b00 svchost.exe 1036 460 17 312 0 0 2022-11-01 16:10:58 UTC+0000
0xfffffa80050bbb00 spoolsv.exe 1208 460 13 301 0 0 2022-11-01 16:10:58 UTC+0000
0xfffffa80050d3b00 CISVC.EXE 1236 460 3 73 0 0 2022-11-01 16:10:58 UTC+0000
0xfffffa80050f7060 svchost.exe 1264 460 15 258 0 0 2022-11-01 16:10:58 UTC+0000
0xfffffa80050fab00 svchost.exe 1300 460 5 58 0 0 2022-11-01 16:10:58 UTC+0000
0xfffffa8005124b00 svchost.exe 1332 460 6 93 0 0 2022-11-01 16:10:58 UTC+0000
0xfffffa8005144b00 TCPSVCS.EXE 1468 460 4 99 0 0 2022-11-01 16:10:58 UTC+0000
0xfffffa80051c1b00 nfsclnt.exe 1576 460 7 104 0 0 2022-11-01 16:10:58 UTC+0000
0xfffffa8005295440 dwm.exe 2004 956 3 71 1 0 2022-11-01 16:12:08 UTC+0000
0xfffffa80037e3b00 explorer.exe 300 1940 21 717 1 0 2022-11-01 16:12:08 UTC+0000
0xfffffa80037d8930 taskhost.exe 656 460 8 151 1 0 2022-11-01 16:12:08 UTC+0000
0xfffffa800384d9b0 VBoxTray.exe 1884 300 12 138 1 0 2022-11-01 16:12:09 UTC+0000
0xfffffa8003854b00 ClipboardMonit 1516 300 1 47 1 0 2022-11-01 16:12:09 UTC+0000
0xfffffa8003dc4060 wmpnetwk.exe 2612 460 9 210 0 0 2022-11-01 16:12:29 UTC+0000
0xfffffa80050f2b00 mstsc.exe 2840 300 14 715 1 0 2022-11-01 16:12:35 UTC+0000
0xfffffa8003e16b00 mscorsvw.exe 884 460 6 87 0 1 2022-11-01 16:12:59 UTC+0000
0xfffffa8003792700 mscorsvw.exe 2116 460 6 80 0 0 2022-11-01 16:12:59 UTC+0000
0xfffffa8003ec1060 mstsc.exe 2356 300 3 241 1 0 2022-11-01 16:13:06 UTC+0000
0xfffffa8003790700 WmiPrvSE.exe 1484 584 5 108 0 0 2022-11-01 16:14:59 UTC+0000
0xfffffa8004dc4660 taskeng.exe 2888 840 4 82 0 0 2022-11-01 16:20:58 UTC+0000

观察到其有剪切板进程ClipboardMonit

clipboard提取其中的内容

1
2
3
4
5
6
7
8
9
10
11
crazyman@ubuntu:~/forensics/volatility$ python2 vol.py -f /home/crazyman/Desktop/CharlieBrown-PC.elf --profile=Win7SP1x64 clipboard
Volatility Foundation Volatility Framework 2.6.1
Session WindowStation Format Handle Object Data
---------- ------------- ------------------ ------------------ ------------------ --------------------------------------------------
1 WinSta0 0xc009L 0x901c1 0xfffff900c00e26b0
1 WinSta0 CF_TEXT 0x7400000001 ------------------
1 WinSta0 CF_UNICODETEXT 0x7021f 0xfffff900c1df7970 -----BEGIN PUBLIC KEY---...----END PUBLIC KEY-----
1 WinSta0 CF_TEXT 0x0 ------------------
1 WinSta0 CF_LOCALE 0x0 ------------------
1 WinSta0 0x0L 0x0 ------------------
1 ------------- ------------------ 0x901a3 0xfffff900c01f2cc0

-v提取一下详细内容

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
crazyman@ubuntu:~/forensics/volatility$ python2 vol.py -f /home/crazyman/Desktop/CharlieBrown-PC.elf --profile=Win7SP1x64 clipboard -v
Volatility Foundation Volatility Framework 2.6.1
Session WindowStation Format Handle Object Data
---------- ------------- ------------------ ------------------ ------------------ --------------------------------------------------
1 WinSta0 0xc009L 0x901c1 0xfffff900c00e26b0
0xfffff900c00e26c4 5e 01 03 00 00 00 00 00 ^.......
1 WinSta0 CF_TEXT 0x7400000001 ------------------
1 WinSta0 CF_UNICODETEXT 0x7021f 0xfffff900c1df7970 -----BEGIN PUBLIC KEY---...----END PUBLIC KEY-----
0xfffff900c1df7984 2d 00 2d 00 2d 00 2d 00 2d 00 42 00 45 00 47 00 -.-.-.-.-.B.E.G.
0xfffff900c1df7994 49 00 4e 00 20 00 50 00 55 00 42 00 4c 00 49 00 I.N...P.U.B.L.I.
0xfffff900c1df79a4 43 00 20 00 4b 00 45 00 59 00 2d 00 2d 00 2d 00 C...K.E.Y.-.-.-.
0xfffff900c1df79b4 2d 00 2d 00 0d 00 0a 00 4d 00 46 00 6f 00 77 00 -.-.....M.F.o.w.
0xfffff900c1df79c4 44 00 51 00 59 00 4a 00 4b 00 6f 00 5a 00 49 00 D.Q.Y.J.K.o.Z.I.
0xfffff900c1df79d4 68 00 76 00 63 00 4e 00 41 00 51 00 45 00 42 00 h.v.c.N.A.Q.E.B.
0xfffff900c1df79e4 42 00 51 00 41 00 44 00 53 00 51 00 41 00 77 00 B.Q.A.D.S.Q.A.w.
0xfffff900c1df79f4 52 00 67 00 4a 00 42 00 41 00 49 00 45 00 5a 00 R.g.J.B.A.I.E.Z.
0xfffff900c1df7a04 54 00 78 00 78 00 6c 00 65 00 37 00 2b 00 35 00 T.x.x.l.e.7.+.5.
0xfffff900c1df7a14 72 00 79 00 77 00 43 00 35 00 62 00 79 00 49 00 r.y.w.C.5.b.y.I.
0xfffff900c1df7a24 75 00 42 00 6b 00 50 00 68 00 77 00 6b 00 79 00 u.B.k.P.h.w.k.y.
0xfffff900c1df7a34 76 00 35 00 37 00 52 00 0d 00 0a 00 37 00 35 00 v.5.7.R.....7.5.
0xfffff900c1df7a44 36 00 44 00 55 00 43 00 44 00 39 00 69 00 32 00 6.D.U.C.D.9.i.2.
0xfffff900c1df7a54 4d 00 57 00 59 00 79 00 55 00 73 00 30 00 41 00 M.W.Y.y.U.s.0.A.
0xfffff900c1df7a64 63 00 63 00 36 00 4a 00 5a 00 77 00 79 00 71 00 c.c.6.J.Z.w.y.q.
0xfffff900c1df7a74 56 00 4f 00 6d 00 52 00 37 00 34 00 75 00 4d 00 V.O.m.R.7.4.u.M.
0xfffff900c1df7a84 76 00 72 00 65 00 49 00 32 00 73 00 6c 00 6c 00 v.r.e.I.2.s.l.l.
0xfffff900c1df7a94 65 00 34 00 47 00 79 00 37 00 48 00 6c 00 36 00 e.4.G.y.7.H.l.6.
0xfffff900c1df7aa4 50 00 63 00 58 00 78 00 45 00 43 00 41 00 51 00 P.c.X.x.E.C.A.Q.
0xfffff900c1df7ab4 49 00 3d 00 0d 00 0a 00 2d 00 2d 00 2d 00 2d 00 I.=.....-.-.-.-.
0xfffff900c1df7ac4 2d 00 45 00 4e 00 44 00 20 00 50 00 55 00 42 00 -.E.N.D...P.U.B.
0xfffff900c1df7ad4 4c 00 49 00 43 00 20 00 4b 00 45 00 59 00 2d 00 L.I.C...K.E.Y.-.

提取出来的Public key为:

1
2
3
4
-----BEGIN PUBLIC KEY-----
MFowDQYJKoZIhvcNAQEBBQADSQAwRgJBAIEZTxxle7+5rywC5byIuBkPhwkyv57R
756DUCD9i2MWYyUs0Acc6JZwyqVOmR74uMvreI2slle4Gy7Hl6PcXxECAQI=
-----END PUBLIC KEY-----

通过http://www.hiencode.com/pub_asys.html?public_key_content=-----BEGIN+PUBLIC+KEY-----%0D%0AMFowDQYJKoZIhvcNAQEBBQADSQAwRgJBAIEZTxxle7%2B5rywC5byIuBkPhwkyv57R%0D%0A756DUCD9i2MWYyUs0Acc6JZwyqVOmR74uMvreI2slle4Gy7Hl6PcXxECAQI%3D%0D%0A-----END+PUBLIC+KEY-----

可以得到相关的信息

1
2
3
4
5
pubkey.e=2
pubkey.n=
6761456110411637567688581808417563265129495172728559363264959694
1616763967271774525888270484885466532642358482631820091062177344
39508352645687684489830161

当然也可以使用脚本进行提取

1
2
3
4
5
6
7
8
>>> from Crypto.PublicKey import RSA
>>> with open('key.pub.pem','r') as f:
... pubKey = RSA.import_key(f.read())
...
>>> pubKey.e
2
>>> pubKey.n
6761456110411637567688581808417563265129495172728559363264959694161676396727177452588827048488546653264235848263182009106217734439508352645687684489830161

dump mstsc.exe 进程的内存

1
2
3
4
5
6
7
8
crazyman@ubuntu:~/forensics/volatility$ python2 vol.py -f /home/crazyman/Desktop/CharlieBrown-PC.elf --profile=Win7SP1x64 memdump -p 2840 -D ./
Volatility Foundation Volatility Framework 2.6.1
************************************************************************
Writing mstsc.exe [ 2840] to 2840.dmp
crazyman@ubuntu:~/forensics/volatility$ python2 vol.py -f /home/crazyman/Desktop/CharlieBrown-PC.elf --profile=Win7SP1x64 memdump -p 2356 -D ./
Volatility Foundation Volatility Framework 2.6.1
************************************************************************
Writing mstsc.exe [ 2356] to 2356.dmp

把后缀dmp改为data,利用gimp加载原始数据调一下可以得到这样的一幅图

其表示内容不存在于普通的内存结合hint3,hint1给出的显卡以及下文我们可以得知其存在于vram中

screenshot:

1
2
3
4
5
6
7
8
9
10
11
12
crazyman@ubuntu:~/forensics/volatility$ python2 vol.py -f /home/crazyman/Desktop/CharlieBrown-PC.raw --profile=Win7SP1x64 screenshot -D ./
Volatility Foundation Volatility Framework 2.6.1
Wrote ./session_0.Service-0x0-3e4$.Default.png
Wrote ./session_0.Service-0x0-3e5$.Default.png
Wrote ./session_0.Service-0x0-3e7$.Default.png
Wrote ./session_0.WinSta0.Default.png
Wrote ./session_0.WinSta0.Disconnect.png
Wrote ./session_0.WinSta0.Winlogon.png
Wrote ./session_1.WinSta0.Default.png
Wrote ./session_1.WinSta0.Disconnect.png
Wrote ./session_1.WinSta0.Winlogon.png

vboxinfo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
crazyman@ubuntu:~/forensics/volatility$ python2 vol.py -f /home/crazyman/Desktop/CharlieBrown-PC.elf --profile=Win7SP1x64 vboxinfo
Volatility Foundation Volatility Framework 2.6.1
Magic: 0xc01ac0de
Format: 0x10006
VirtualBox 7.0.2 (revision 154219)
CPUs: 2

FileOffset Memory Offset Size
0x4a2c 0x0 0xa0000
0xa4a2c 0xc0000 0x9000
0xada2c 0xe0000 0x1000
0xaea2c 0xe1000 0x1000
0xafa2c 0xe2000 0xe000
0xbda2c 0xf0000 0x10000
0xcda2c 0x100000 0x100000
0x1cda2c 0x200000 0xdfe00000
0xdffcda2c 0xe0000000 0x2000000
0xe1fcda2c 0xf0000000 0x200000
0xe21cda2c 0xf0400000 0x400000
0xe25cda2c 0xf0800000 0x4000
0xe25d1a2c 0xffff0000 0x10000
0xe25e1a2c 0x100000000 0x20000000

根据第一张提示图,可以得知屏幕分辨率等数据以及关键信息显卡
通过volatility的vboxinfo插件可以知道显存在内存文件中的位置0xdffcda2c以及大小0x2000000,于是直接动手将其提取出来

结合提示给出的1440x900的分辨率以及32的位深度,可以写个脚本将色彩文件转成图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from PIL import Image

width = 1440
height = 900
flag = open('vram','rb').read()

def makeSourceImg():
img = Image.new('RGBA', (width, height))
x = 0
for i in range(height):
for j in range(width):
img.putpixel((j, i), (flag[x], flag[x + 1], flag[x + 2],flag[x+3]))
x += 4
return img

img = makeSourceImg()
img.save('1.png')

得到的图片如下

可以得到大概的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> from Crypto.Util.number import bytes_to_long,long_to_bytes
>>> with open('flag.txt','rb') as f:
m = bytes_to_long(f.read())

>>> from Crypto.PublicKey import RSA
>>> with open('flag.pub.pem','r') as f
pubkey = RSA.import_key(f.read())

>>> pubkey.size_in_bits()
512
>>> c = pow(m,pubkey.e,pubkey.n)
>>> long_to_bytes(c).hex()
'089ebf3622f6f6d498c1b5ecfe4d831d3e876bf55578586389127e0053bb4fe006e2eee5398b86274fdce0418d16c9bb0bf24922cec491b3047d33eb661784c9'

先反解出c来

1
2
3
>>> from Crypto.Util.number import bytes_to_long,long_to_bytes
>>> bytes_to_long(bytes.fromhex("089ebf3622f6f6d498c1b5ecfe4d831d3e876bf55578586389127e0053bb4fe006e2eee5398b86274fdce0418d16c9bb0bf24922cec491b3047d33eb661784c9"))
451471540081589674653974518512438308733093273213393434162105049845933212224386755831134427109878720380821421287108607669893882611307516611482749725279433

再通过http://www.factordb.com/ 分解n可以得到

1
2
p = 79346858353882639199177956883793426898254263343390015030885061293456810296567
q = 85213910804835068776008762162103815863113854646656693711835550035527059235383

e=2,n可分解 符合rabin

最后解密脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import gmpy2

def rabin_decrypt(c, p, q, e=2):
n = p * q
mp = pow(c, (p + 1) // 4, p)
mq = pow(c, (q + 1) // 4, q)
yp = gmpy2.invert(p, q)
yq = gmpy2.invert(q, p)
r = (yp * p * mq + yq * q * mp) % n
rr = n - r
s = (yp * p * mq - yq * q * mp) % n
ss = n - s
return (r, rr, s, ss)

c = 451471540081589674653974518512438308733093273213393434162105049845933212224386755831134427109878720380821421287108607669893882611307516611482749725279433
p = 79346858353882639199177956883793426898254263343390015030885061293456810296567
q = 85213910804835068776008762162103815863113854646656693711835550035527059235383
m = rabin_decrypt(c,p,q)
for i in range(4):
try:
print(bytes.fromhex(hex(m[i])[2:]))
except:
pass

结果:

1
2
3
4
5
crazyman@ubuntu:~/Desktop$ python3 solve.py 
b'=\x7f\xc0\xdc\x96\x88D\x886\xa7\xdaa\xc9\x10\x183\x1aG4m\xf6Yws\n0f\xbb\xbb\x01V\x84\xa3R\xe1\xd0\xea\x17W\x97/C\xfd\xf4\xc48\xbc\x96\xbbn\x88\x97)\x99`\x845\x1e\x90\x95\x10\xbfk\xb5'
b'C\x99\x8e?\xce\xf3{1x\x84(\x83\xf3x\x9f\xe5\xf5?\xd4\xc4\xc9EZ|\x94R\xe9eB\x8a\x0c\x91\xbf\xd2J\xff\x1d\x05\x90\xffA\x86\xa7Y\xd4\xe6<"\x10|\xef\xf6\x82\xfc\xf73\xe6\x107\x02\x93\x1c\xf3\\'
b'\x81\x19O\x1ce{\xbf\xb9\xaf,\x02\xe5\xbc\x88\xb8\x19\x0f\x87\t2{]~\xacJ<\xd4\xd7\x89V\x03\xb2\x19\xb2\xf9l\xcf\xd0o7\r\x9a2\xfce\xb2\xc4d\x98\x87\x19\x19|7 o\xb5\xcfcfV\xa9)\x94'
b'DASCTF{It5_dIr3c7Ly_c0rR3l4T3d_t0_7He_d1M35}'

最后flag –> DASCTF{It5_dIr3c7Ly_c0rR3l4T3d_t0_7He_d1M35}