Skip to content

Commit 545b66f

Browse files
committed
Fedorov course notes [SENATOROVAI#4] (SENATOROVAI/DA#4)
Closes SENATOROVAI/DA#4
1 parent a4e7b08 commit 545b66f

File tree

2 files changed

+494
-0
lines changed

2 files changed

+494
-0
lines changed
Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"\"\"\"Processing hashes and PE (ELF) files in Python.\"\"\""
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {},
15+
"source": [
16+
"# Обработка hashes и PE (ELF)-файлов на языке Python"
17+
]
18+
},
19+
{
20+
"cell_type": "markdown",
21+
"metadata": {},
22+
"source": [
23+
"Исходные файлы для блокнота находятся по [ссылке](https://github.com/dm-fedorov/infosec/tree/master/re-tools/samples)."
24+
]
25+
},
26+
{
27+
"cell_type": "markdown",
28+
"metadata": {},
29+
"source": [
30+
"Скачиваем весь архив с файлами для работы в Colab:"
31+
]
32+
},
33+
{
34+
"cell_type": "code",
35+
"execution_count": null,
36+
"metadata": {},
37+
"outputs": [],
38+
"source": [
39+
"!wget https://dfedorov.spb.ru/infosec/re/samples.zip"
40+
]
41+
},
42+
{
43+
"cell_type": "markdown",
44+
"metadata": {},
45+
"source": [
46+
"!unzip samples.zip"
47+
]
48+
},
49+
{
50+
"cell_type": "code",
51+
"execution_count": null,
52+
"metadata": {},
53+
"outputs": [],
54+
"source": [
55+
"!ls samples"
56+
]
57+
},
58+
{
59+
"cell_type": "markdown",
60+
"metadata": {},
61+
"source": [
62+
"## Определение сигнатуры файла"
63+
]
64+
},
65+
{
66+
"cell_type": "markdown",
67+
"metadata": {},
68+
"source": [
69+
"В системах GNU/Linux, чтобы найти сигнатуру файла (уникальная последовательность байтов), можно использовать команду [xxd](https://www.opennet.ru/man.shtml?topic=xxd&category=1&russian=0), которая генерирует шестнадцатеричный дамп файла, как показано ниже:"
70+
]
71+
},
72+
{
73+
"cell_type": "code",
74+
"execution_count": null,
75+
"metadata": {},
76+
"outputs": [],
77+
"source": [
78+
"!xxd samples/task-1.exe"
79+
]
80+
},
81+
{
82+
"cell_type": "markdown",
83+
"metadata": {},
84+
"source": [
85+
"Видим, что исполняемые файлы ОС Windows, также называемые [PE-файлами](https://ru.wikipedia.org/wiki/Portable_Executable) (например, .exe, .dll, .com, .drv, .sys и т. д.), имеют подпись файла ```MZ``` или шестнадцатеричные символы ```4D 5A``` в первых двух байтах файла."
86+
]
87+
},
88+
{
89+
"cell_type": "markdown",
90+
"metadata": {},
91+
"source": [
92+
"Выполним команду для [ELF-файла](https://ru.wikipedia.org/wiki/Executable_and_Linkable_Format) (подпись файла `ELF`):"
93+
]
94+
},
95+
{
96+
"cell_type": "code",
97+
"execution_count": null,
98+
"metadata": {},
99+
"outputs": [],
100+
"source": [
101+
"!xxd samples/test_01"
102+
]
103+
},
104+
{
105+
"cell_type": "markdown",
106+
"metadata": {},
107+
"source": [
108+
"В следующем примере команда [file](https://www.opennet.ru/man.shtml?topic=file&category=1&russian=4) была запущена для двух разных файлов:"
109+
]
110+
},
111+
{
112+
"cell_type": "code",
113+
"execution_count": null,
114+
"metadata": {},
115+
"outputs": [],
116+
"source": [
117+
"!apt-get install file"
118+
]
119+
},
120+
{
121+
"cell_type": "code",
122+
"execution_count": null,
123+
"metadata": {},
124+
"outputs": [],
125+
"source": [
126+
"!file samples/task-1.exe"
127+
]
128+
},
129+
{
130+
"cell_type": "code",
131+
"execution_count": null,
132+
"metadata": {},
133+
"outputs": [],
134+
"source": [
135+
"!file samples/test_01"
136+
]
137+
},
138+
{
139+
"cell_type": "markdown",
140+
"metadata": {},
141+
"source": [
142+
"В Python модуль [python-magic](https://github.com/ahupp/python-magic) может использоваться для определения типа файла:"
143+
]
144+
},
145+
{
146+
"cell_type": "code",
147+
"execution_count": null,
148+
"metadata": {},
149+
"outputs": [],
150+
"source": [
151+
"!pip3 install python-magic"
152+
]
153+
},
154+
{
155+
"cell_type": "code",
156+
"execution_count": null,
157+
"id": "79c036c8",
158+
"metadata": {},
159+
"outputs": [],
160+
"source": [
161+
"import hashlib\n",
162+
"\n",
163+
"import magic\n",
164+
"import pefile"
165+
]
166+
},
167+
{
168+
"cell_type": "code",
169+
"execution_count": null,
170+
"id": "908836d4",
171+
"metadata": {},
172+
"outputs": [],
173+
"source": [
174+
"magic.from_file(\"samples/test_01\")"
175+
]
176+
},
177+
{
178+
"cell_type": "code",
179+
"execution_count": null,
180+
"id": "ff877b14",
181+
"metadata": {},
182+
"outputs": [],
183+
"source": [
184+
"magic.from_file(\"samples/task-1.exe\")"
185+
]
186+
},
187+
{
188+
"cell_type": "markdown",
189+
"id": "03bea2db",
190+
"metadata": {},
191+
"source": [
192+
"## Обработка хеш-суммы на Python"
193+
]
194+
},
195+
{
196+
"cell_type": "markdown",
197+
"id": "97418b75",
198+
"metadata": {},
199+
"source": [
200+
"В системе Linux хеш-суммы могут быть сгенерированы с использованием утилит [md5sum](https://www.opennet.ru/man.shtml?topic=md5sum&category=1&russian=0), [sha256sum](https://www.opennet.ru/man.shtml?topic=sha256sum&russian=0) и [sha1sum](https://www.opennet.ru/man.shtml?topic=sha1sum&russian=0):"
201+
]
202+
},
203+
{
204+
"cell_type": "code",
205+
"execution_count": null,
206+
"id": "e7bc88b0",
207+
"metadata": {},
208+
"outputs": [],
209+
"source": [
210+
"!md5sum samples/task-1.exe"
211+
]
212+
},
213+
{
214+
"cell_type": "code",
215+
"execution_count": null,
216+
"id": "a5aa2f5d",
217+
"metadata": {},
218+
"outputs": [],
219+
"source": [
220+
"!sha256sum samples/task-1.exe"
221+
]
222+
},
223+
{
224+
"cell_type": "code",
225+
"execution_count": null,
226+
"id": "e9363496",
227+
"metadata": {},
228+
"outputs": [],
229+
"source": [
230+
"!sha1sum samples/task-1.exe"
231+
]
232+
},
233+
{
234+
"cell_type": "markdown",
235+
"id": "3bca3a9b",
236+
"metadata": {},
237+
"source": [
238+
"В Python можно генерировать хеш-суммы, используя модуль [hashlib](https://docs.python.org/3/library/hashlib.html), как показано ниже:"
239+
]
240+
},
241+
{
242+
"cell_type": "code",
243+
"execution_count": null,
244+
"id": "93a97536",
245+
"metadata": {},
246+
"outputs": [],
247+
"source": [
248+
"with open(\"samples/task-1.exe\", \"rb\") as f:\n",
249+
" content = f.read()\n",
250+
"\n",
251+
"print(hashlib.md5(content).hexdigest())"
252+
]
253+
},
254+
{
255+
"cell_type": "code",
256+
"execution_count": null,
257+
"id": "660c283e",
258+
"metadata": {},
259+
"outputs": [],
260+
"source": [
261+
"print(hashlib.sha256(content).hexdigest())"
262+
]
263+
},
264+
{
265+
"cell_type": "code",
266+
"execution_count": null,
267+
"id": "d59187d8",
268+
"metadata": {},
269+
"outputs": [],
270+
"source": [
271+
"print(hashlib.sha1(content).hexdigest())"
272+
]
273+
},
274+
{
275+
"cell_type": "markdown",
276+
"id": "5652fa9e",
277+
"metadata": {},
278+
"source": [
279+
"## Извлечение строк"
280+
]
281+
},
282+
{
283+
"cell_type": "markdown",
284+
"id": "aa84cd95",
285+
"metadata": {},
286+
"source": [
287+
"Извлечение строк может подсказать, как функционирует программа, и рассказать об индикаторах, указывающих на подозрительный двоичный код. Например, если вредоносная программа создает файл, имя файла сохраняется в виде строки в двоичном файле. Или если вредоносная программа разрешает доменное имя, контролируемое злоумышленником, это имя впоследствии хранится в виде строки.\n",
288+
"\n",
289+
"Чтобы извлечь строки из подозрительного двоичного файла, вы можете использовать утилиту [strings](https://www.opennet.ru/man.shtml?topic=strings) в системах GNU/Linux.\n",
290+
"\n",
291+
"Команда `strings` по умолчанию извлекает ASCII-строки, длина которых составляет минимум четыре символа. С помощью опции ```-a``` можно извлечь строки из целого файла."
292+
]
293+
},
294+
{
295+
"cell_type": "code",
296+
"execution_count": null,
297+
"id": "c5b541e0",
298+
"metadata": {},
299+
"outputs": [],
300+
"source": [
301+
"!strings -a samples/task-1.exe"
302+
]
303+
},
304+
{
305+
"cell_type": "markdown",
306+
"id": "223c72e0",
307+
"metadata": {},
308+
"source": [
309+
"В образцах вредоносных программ также используются Юникод-строки (2 байта на символ). Чтобы получить полезную информацию из двоичного файла, иногда нужно извлечь как ASCII-, так и Юникод-строки. Чтобы извлечь Юникод-строки с помощью команды `strings`, используйте опцию ```-el```:"
310+
]
311+
},
312+
{
313+
"cell_type": "code",
314+
"execution_count": null,
315+
"id": "bb896e4d",
316+
"metadata": {},
317+
"outputs": [],
318+
"source": [
319+
"!strings -a -el samples/task-1.exe"
320+
]
321+
},
322+
{
323+
"cell_type": "markdown",
324+
"id": "04ecbe05",
325+
"metadata": {},
326+
"source": [
327+
"Модуль [FLOSS](https://github.com/fireeye/flare-floss) автоматически извлекает запутанные строки из вредоносных программ."
328+
]
329+
},
330+
{
331+
"cell_type": "markdown",
332+
"id": "27eaf25f",
333+
"metadata": {},
334+
"source": [
335+
"Исполняемые файлы ОС Windows должны соответствовать формату PE/COFF (Portable Executable/Common Object File Format – Переносимый исполняемый/стандартный формат объектного файла).\n",
336+
"\n",
337+
"Фактическое содержимое PE-файла разделено на секции. За ними сразу же следует PE-заголовок. Эти секции представляют либо код, либо данные, они имеют ```in-memory-атрибуты```, такие как чтение/запись. Секция, представляющая код, содержит инструкции, которые будут выполняться процессором, тогда как секция, содержащая данные, может представлять различные типы данных, такие как чтение/запись данных программы (глобальные переменные), таблицы импорта/экспорта, ресурсы и т. д. У каждой секции есть свое имя, которое передает ее назначение.\n",
338+
"\n",
339+
"Например, секция с именем ```.text``` указывает на код и имеет атрибут ```read-execute```; раздел с именем ```.data``` указывает на глобальные данные и имеет атрибут ```read-write```.\n",
340+
"\n",
341+
"Следующий скрипт Python демонстрирует использование модуля [pefile](https://github.com/erocarrera/pefile) для отображения секции и её характеристик:"
342+
]
343+
},
344+
{
345+
"cell_type": "code",
346+
"execution_count": null,
347+
"id": "bcbd27d6",
348+
"metadata": {},
349+
"outputs": [],
350+
"source": [
351+
"!pip3 install pefile"
352+
]
353+
},
354+
{
355+
"cell_type": "code",
356+
"execution_count": null,
357+
"id": "43575f29",
358+
"metadata": {},
359+
"outputs": [],
360+
"source": [
361+
"pe = pefile.PE(\"samples/task-1.exe\")\n",
362+
"for section in pe.sections:\n",
363+
" print(\n",
364+
" f\"{section.Name.decode()} \\\n",
365+
" {hex(section.VirtualAddress)} \\\n",
366+
" {hex(section.Misc_VirtualSize)} \\\n",
367+
" {section.SizeOfRawData}\"\n",
368+
" )"
369+
]
370+
},
371+
{
372+
"cell_type": "markdown",
373+
"metadata": {},
374+
"source": [
375+
"Скрипт [Pescanner](https://github.com/hiddenillusion/AnalyzePE/blob/master/pescanner.py) использует эвристику вместо сигнатур и может помочь идентифицировать упакованные двоичные файлы, даже если для них нет сигнатур."
376+
]
377+
}
378+
],
379+
"metadata": {
380+
"language_info": {
381+
"name": "python"
382+
}
383+
},
384+
"nbformat": 4,
385+
"nbformat_minor": 5
386+
}

0 commit comments

Comments
 (0)