众所周知,Windows PE文件结构长这样。
落到文件就像是这样,其中“■”颜色选中的地方是“IMAGE_DOS_HEADER”。
按照微软的文档说明,结构应该是这样:
是不是感觉怪怪的,好像与文档对不上?
我们可以尝试着人工先分析一下,首先,把这段明文的内容提取出来,根据内容“This program cannot be run in DOS mode.(该程序不能以DOS模式运行。)”可以猜出,这段明文可能是用来在dos环境下,提示该程序无法直接运行的。
那么我们跳过这段数据继续往下看,下面这段看起来似乎比较有结构话,很多地方都存在重复字节。
作者在对比了多个样本后发现,在PE头之前,去掉看似被填充的0x00以后,在他倒数的0x08~0x04位置,每个样本均出现了明文字符串”Rich”。
作者查阅了大量资料,发现一段数据,是使用微软的编译器时微软故意留下的编译器信息。
称为“Rich Signature”(富签名),该签名似乎只有在使用微软Visual Studio编译器时留下。
下面,作者带大家一起分析一下Rich签名,老规矩,作者会尽量讲的细一点,希望大家可以有所收获。
首先,我们可以看到,在这个”Rich Signature”中存在大量的重复字节,例如图中的红框和绿框部分,而最后一个红框部分内容很巧合的出现在明文Rich(蓝框)的后面,形成了一个结尾。但是不清楚有何用途。
作者在经过对Visual Studio的link.exe逆向分析后,在函数中找到了答案,异或!
根据他的算法我们可以看出来,他使用”Rich Signature”最后的4字节进行了一次异或,所以作者按照上图所示,使用CyberChef工具对整个”Rich Signature”异或一下,来还原原始数据。
我们根据逆向link.exe时看到的生成Rich签名的处理逻辑继续分析。首先我们忽略最前面的“DanS”部分的结构头,从0x10继续分析。
虽然从图中我们可以很明显的看出使用异或解密后的数据十分的有结构化,但是还是无法明确每个字节的含义是什么,作者又在查阅了一大堆资料后,从微软泄露的“Windows 2000“的源代码中发现了更多的答案。
正如我们所看到,”Rich Signature”以每”PRODITEM(8字节)”为一个结构数组,每个”PRODITEM(8字节)”由三个部分组成,分别是”dwProdid(ProdID(2字节)、dwProdid(2字节))”、”dwCount(4字节)“。我们按照此结构继续解析。
注意大小端!注意大小端!注意大小端!
首先读取2字节把16进制转换为10进制,”0x78 0x09″->”30729″。//ProdID
再读取2字节把16进制转换为10进制,”0x00 0x93″->”147″。//dwProdid
再读取4字节把16进制转换为10进制,”0x00 0x00 0x00 0x0A”->”10″。//dwCount
到此为止,我们便成功提取了富签名的信息,但是这些信息还不足以对我们产生太多的价值,但是如果价值不大,那么微软为什么会把这个信息加密隐藏在PE中呢?我们接着往下看。
作者继续分析了泄露的“Windows 2000“源代码,发现”dwProdid“代表的是编译工具内部的版本号,例如在本次的样本中,”147″则代表着”Implib900″(完整版本号见文末附录二)。
而”ProdID“(产品标识符)存在于”Visual Studio“开发工具中,包括微软的链接器、C/C++ 编译器、MASM、资源、导入、implibs 等。
当开发者在使用这些开发工具编译文件时,便会将这些开发工具的”ProdID“写入”Rich Signature”中,在本次的样本中,”30729″就是代表着”Visual Studio 2008 SP1 [9.0]、Visual C++ 2008 SP1 [9.0]”(完整版本号见文末附录三)。
最后的”dwCount”则是开发工具被调用到的次数,”10″代表着被调用了10次,表示参与编译的文件有10个,注意:此处的数量不一定是开发者编写了10个文件,而是开发者编写的文件加参与编译的系统库一共有10个文件调用了开发工具。
以上我们便完成了对一个”PRODITEM”结构数组的分析,我们继续往下看,…,直到看到这里。
我们按照上面的方法继续解析一下。
首先读取2字节把16进制转换为10进制,”0x7B 0x8E”->”31630″。//ProdID
再读取2字节把16进制转换为10进制,”0x01 0x02″->”258″。//dwProdid
再读取4字节把16进制转换为10进制,”0x00 0x00 0x00 0x01″->”1″。//dwCount
根据附录二,”258(dwProdid)”表示”Linker1400″,值得注意的是“dwProdid”中的“Linker”、”Cvtres”字段极有可能表示的是开发者使用的VS版本,根据附录三,”31630(ProdID)”表示”Visual Studio 2022 version 17.3.4″。
所以,这个样本就是使用”Visual Studio 2022 version 17.3.4″开发编译的!
总结一下,综上所述,当使用微软编译器编译时,他会将编译器的信息一起加密记录在编译完的二进制文件中,可以通过这个信息精准的识别编译器的版本、内部版本、调用次数等等,还可以通过编译器信息知道被编译的文件是c语言还是c++,是汇编还是cvtres,又或者是什么Visual Studio版本。
那么我们在溯源的时候可以怎么使用呢?
我们可以通过上述信息知道攻击者是使用什么环境编译的样本,并可以接着YARA在VT上进行Hunter,狩猎更多的样本。
附录一(yara规则模板):
rule MSVC5
{
condition:
pe.rich_signature.version(1668) and pe.rich_signature.toolid(6)
}
附录二(dwProdid):
dwProdid = {
0: "Unknown",
1: "Import0",
2: "Linker510",
3: "Cvtomf510",
4: "Linker600",
5: "Cvtomf600",
6: "Cvtres500",
7: "Utc11_Basic",
8: "Utc11_C",
9: "Utc12_Basic",
10: "Utc12_C",
11: "Utc12_CPP",
12: "AliasObj60",
13: "VisualBasic60",
14: "Masm613",
15: "Masm710",
16: "Linker511",
17: "Cvtomf511",
18: "Masm614",
19: "Linker512",
20: "Cvtomf512",
21: "Utc12_C_Std",
22: "Utc12_CPP_Std",
23: "Utc12_C_Book",
24: "Utc12_CPP_Book",
25: "Implib700",
26: "Cvtomf700",
27: "Utc13_Basic",
28: "Utc13_C",
29: "Utc13_CPP",
30: "Linker610",
31: "Cvtomf610",
32: "Linker601",
33: "Cvtomf601",
34: "Utc12_1_Basic",
35: "Utc12_1_C",
36: "Utc12_1_CPP",
37: "Linker620",
38: "Cvtomf620",
39: "AliasObj70",
40: "Linker621",
41: "Cvtomf621",
42: "Masm615",
43: "Utc13_LTCG_C",
44: "Utc13_LTCG_CPP",
45: "Masm620",
46: "ILAsm100",
47: "Utc12_2_Basic",
48: "Utc12_2_C",
49: "Utc12_2_CPP",
50: "Utc12_2_C_Std",
51: "Utc12_2_CPP_Std",
52: "Utc12_2_C_Book",
53: "Utc12_2_CPP_Book",
54: "Implib622",
55: "Cvtomf622",
56: "Cvtres501",
57: "Utc13_C_Std",
58: "Utc13_CPP_Std",
59: "Cvtpgd1300",
60: "Linker622",
61: "Linker700",
62: "Export622",
63: "Export700",
64: "Masm700",
65: "Utc13_POGO_I_C",
66: "Utc13_POGO_I_CPP",
67: "Utc13_POGO_O_C",
68: "Utc13_POGO_O_CPP",
69: "Cvtres700",
70: "Cvtres710p",
71: "Linker710p",
72: "Cvtomf710p",
73: "Export710p",
74: "Implib710p",
75: "Masm710p",
76: "Utc1310p_C",
77: "Utc1310p_CPP",
78: "Utc1310p_C_Std",
79: "Utc1310p_CPP_Std",
80: "Utc1310p_LTCG_C",
81: "Utc1310p_LTCG_CPP",
82: "Utc1310p_POGO_I_C",
83: "Utc1310p_POGO_I_CPP",
84: "Utc1310p_POGO_O_C",
85: "Utc1310p_POGO_O_CPP",
86: "Linker624",
87: "Cvtomf624",
88: "Export624",
89: "Implib624",
90: "Linker710",
91: "Cvtomf710",
92: "Export710",
93: "Implib710",
94: "Cvtres710",
95: "Utc1310_C",
96: "Utc1310_CPP",
97: "Utc1310_C_Std",
98: "Utc1310_CPP_Std",
99: "Utc1310_LTCG_C",
100: "Utc1310_LTCG_CPP",
101: "Utc1310_POGO_I_C",
102: "Utc1310_POGO_I_CPP",
103: "Utc1310_POGO_O_C",
104: "Utc1310_POGO_O_CPP",
105: "AliasObj710",
106: "AliasObj710p",
107: "Cvtpgd1310",
108: "Cvtpgd1310p",
109: "Utc1400_C",
110: "Utc1400_CPP",
111: "Utc1400_C_Std",
112: "Utc1400_CPP_Std",
113: "Utc1400_LTCG_C",
114: "Utc1400_LTCG_CPP",
115: "Utc1400_POGO_I_C",
116: "Utc1400_POGO_I_CPP",
117: "Utc1400_POGO_O_C",
118: "Utc1400_POGO_O_CPP",
119: "Cvtpgd1400",
120: "Linker800",
121: "Cvtomf800",
122: "Export800",
123: "Implib800",
124: "Cvtres800",
125: "Masm800",
126: "AliasObj800",
127: "PhoenixPrerelease",
128: "Utc1400_CVTCIL_C",
129: "Utc1400_CVTCIL_CPP",
130: "Utc1400_LTCG_MSIL",
131: "Utc1500_C",
132: "Utc1500_CPP",
133: "Utc1500_C_Std",
134: "Utc1500_CPP_Std",
135: "Utc1500_CVTCIL_C",
136: "Utc1500_CVTCIL_CPP",
137: "Utc1500_LTCG_C",
138: "Utc1500_LTCG_CPP",
139: "Utc1500_LTCG_MSIL",
140: "Utc1500_POGO_I_C",
141: "Utc1500_POGO_I_CPP",
142: "Utc1500_POGO_O_C",
143: "Utc1500_POGO_O_CPP",
144: "Cvtpgd1500",
145: "Linker900",
146: "Export900",
147: "Implib900",
148: "Cvtres900",
149: "Masm900",
150: "AliasObj900",
151: "Resource900",
152: "AliasObj1000",
154: "Cvtres1000",
155: "Export1000",
156: "Implib1000",
157: "Linker1000",
158: "Masm1000",
170: "Utc1600_C",
171: "Utc1600_CPP",
172: "Utc1600_CVTCIL_C",
173: "Utc1600_CVTCIL_CPP",
174: "Utc1600_LTCG_C ",
175: "Utc1600_LTCG_CPP",
176: "Utc1600_LTCG_MSIL",
177: "Utc1600_POGO_I_C",
178: "Utc1600_POGO_I_CPP",
179: "Utc1600_POGO_O_C",
180: "Utc1600_POGO_O_CPP",
183: "Linker1010",
184: "Export1010",
185: "Implib1010",
186: "Cvtres1010",
187: "Masm1010",
188: "AliasObj1010",
199: "AliasObj1100",
201: "Cvtres1100",
202: "Export1100",
203: "Implib1100",
204: "Linker1100",
205: "Masm1100",
206: "Utc1700_C",
207: "Utc1700_CPP",
208: "Utc1700_CVTCIL_C",
209: "Utc1700_CVTCIL_CPP",
210: "Utc1700_LTCG_C ",
211: "Utc1700_LTCG_CPP",
212: "Utc1700_LTCG_MSIL",
213: "Utc1700_POGO_I_C",
214: "Utc1700_POGO_I_CPP",
215: "Utc1700_POGO_O_C",
216: "Utc1700_POGO_O_CPP",
219: "Cvtres1200",
220: "Export1200",
221: "Implib1200",
222: "Linker1200",
223: "Masm1200",
# Speculation
224: "AliasObj1200",
237: "Cvtres1210",
238: "Export1210",
239: "Implib1210",
240: "Linker1210",
241: "Masm1210",
# Speculation
242: "Utc1810_C",
243: "Utc1810_CPP",
244: "Utc1810_CVTCIL_C",
245: "Utc1810_CVTCIL_CPP",
246: "Utc1810_LTCG_C ",
247: "Utc1810_LTCG_CPP",
248: "Utc1810_LTCG_MSIL",
249: "Utc1810_POGO_I_C",
250: "Utc1810_POGO_I_CPP",
251: "Utc1810_POGO_O_C",
252: "Utc1810_POGO_O_CPP",
255: "Cvtres1400",
256: "Export1400",
257: "Implib1400",
258: "Linker1400",
259: "Masm1400",
260: "Utc1900_C",
261: "Utc1900_CPP",
# Speculation
262: "Utc1900_CVTCIL_C",
263: "Utc1900_CVTCIL_CPP",
264: "Utc1900_LTCG_C ",
265: "Utc1900_LTCG_CPP",
266: "Utc1900_LTCG_MSIL",
267: "Utc1900_POGO_I_C",
268: "Utc1900_POGO_I_CPP",
269: "Utc1900_POGO_O_C",
270: "Utc1900_POGO_O_CPP"
}
附录三(Visual Studio MSC版本):
原文始发于微信公众号(狼蛛安全实验室):溯源专题 | 通过PE中的“富签名”进行攻击溯源
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论