Skip to content

Commit dcd8c4e

Browse files
committed
Aggiunte nuove euristiche
1 parent ab53481 commit dcd8c4e

15 files changed

Lines changed: 225 additions & 102 deletions

CHANGELOG

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
Versione 0.0.2-alpha:
22
- Risolti fix
3+
- Aggiunte euristiche sul nome della sezione
4+
- Aggiunte euristiche per le risorse
5+
- Migliorate euristiche delle stringhe per ransomware
6+
- Aumentato threshold al valore 150
7+
- Risolto un problema sui valori di export
8+
- Aggiunto il campo Timestamp alla risorsa
9+
- Aggiunte euristiche per file .NET
10+
- Risolto problema di calcolo errato della dimensione dell'intestazione
11+
- Aggiunta conversione UUID/Path
12+
- Risolto problema degli apici all'interno del file TXT di output
313

414
Versione 0.0.1-alpha:
515
- Prima versione

analysis/analysis.go

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -43,34 +43,7 @@ func PrintResult(Analyzed *formats.FileAnalyzed) {
4343
}
4444

4545
if Analyzed.OutputFormat == "txt" {
46-
47-
// carica un template .txt e popolalo con la struttura fileAnalyzed
48-
t := template.Must(template.New("output_template.txt").Funcs(funcMap).Parse(OutputTemplateTXT))
49-
var processed bytes.Buffer
50-
51-
err := t.Execute(&processed, Analyzed)
52-
if err != nil {
53-
fmt.Println("Non è stato possibile eseguire il template per questo motivo: " + err.Error())
54-
return
55-
}
56-
outputPath := "./results/" + Analyzed.Name + "_analysis.txt"
57-
f, err := os.Create(outputPath)
58-
if err != nil {
59-
fmt.Println("Impossibile creare nuovo file.")
60-
return
61-
}
62-
w := bufio.NewWriter(f)
63-
_, err = w.WriteString(string(processed.Bytes()))
64-
if err != nil {
65-
fmt.Println("Impossibile scrivere il template sul file per il seguente errore: " + err.Error())
66-
return
67-
}
68-
err = w.Flush()
69-
if err != nil {
70-
fmt.Println("Impossibile rimuovere il contenuto dell'IOBuffer.")
71-
return
72-
}
73-
46+
printTxt(*Analyzed)
7447
} else if Analyzed.OutputFormat == "html" {
7548

7649
// carica un template html e popolalo con la struttura fileAnalyzed
@@ -215,13 +188,13 @@ func isPEBinary(content [FILE_HEADER_PHASE_1]byte) bool {
215188
// e il successivo controllo sulla signature PE
216189

217190
// Controlla lo stub per Microsoft MS-DOS (i primi due byte devono essere MZ dal nome del creatore del formato)
218-
if content[0] == byte('M') || content[1] == byte('Z') {
191+
if content[0] == byte('M') && content[1] == byte('Z') {
219192
return true
220193
}
221194

222195
// Esistono anche binari che hanno la sigla "MZ" invertita
223196

224-
if content[0] == byte('Z') || content[0] == byte('M') {
197+
if content[0] == byte('Z') && content[0] == byte('M') {
225198
return true
226199
}
227200

analysis/strings.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,3 @@ func ExtractStrings(file *os.File, min, max int, ascii bool) []string {
4646
str = append(str, ch)
4747
}
4848
}
49-
50-
func ExtractHTTPAddress() {
51-
52-
}

analysis/text_template.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package analysis
2+
3+
import (
4+
"bufio"
5+
"bytes"
6+
"fmt"
7+
"microscope/formats"
8+
"microscope/formats/elf"
9+
"microscope/formats/pe"
10+
"os"
11+
"text/template"
12+
"time"
13+
)
14+
15+
func printTxt(Analyzed formats.FileAnalyzed) {
16+
17+
// lista delle funzioni passate al template
18+
funcMap := template.FuncMap{
19+
"now": time.Now,
20+
"divide": divide,
21+
"PEprintArchitecture": pe.PrintArchitecture,
22+
"PEprintResource": pe.PrintResource,
23+
"PEprintSubsystem": pe.PrintSubsystem,
24+
"PEprintMajorOperatingVersion": pe.PrintMajorOperatingSystemVersion,
25+
"PEprintCharacteristics": pe.PrintCharacteristic,
26+
"ELFprintMachine": elf.PrintMachine,
27+
"ELFprintSectionType": elf.PrintSectionType,
28+
"ELFprintFileType": elf.PrintFileType,
29+
}
30+
31+
// carica un template .txt e popolalo con la struttura fileAnalyzed
32+
t := template.Must(template.New("output_template.txt").Funcs(funcMap).Parse(OutputTemplateTXT))
33+
var processed bytes.Buffer
34+
35+
err := t.Execute(&processed, Analyzed)
36+
if err != nil {
37+
fmt.Println("Non è stato possibile eseguire il template per questo motivo: " + err.Error())
38+
return
39+
}
40+
outputPath := "./results/" + Analyzed.Name + "_analysis.txt"
41+
f, err := os.Create(outputPath)
42+
if err != nil {
43+
fmt.Println("Impossibile creare nuovo file.")
44+
return
45+
}
46+
w := bufio.NewWriter(f)
47+
_, err = w.WriteString(string(processed.Bytes()))
48+
if err != nil {
49+
fmt.Println("Impossibile scrivere il template sul file per il seguente errore: " + err.Error())
50+
return
51+
}
52+
err = w.Flush()
53+
if err != nil {
54+
fmt.Println("Impossibile rimuovere il contenuto dell'IOBuffer.")
55+
return
56+
}
57+
}

formats/elf/sections.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func parseSectionHeaders32(endianness binary.ByteOrder, numberSections uint16, o
161161
}
162162
err = binary.Read(reader, endianness, sectionsHeaders[i])
163163
if err != nil {
164-
fmt.Println("Impossibile leggere il SectionHeader")
164+
fmt.Println("Impossibile leggere il SectionHeader " + err.Error())
165165
return nil
166166
}
167167
}

heuristics/dotnet_heuristics.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,23 @@ func CalculatePointsStringDOTNET(extractedStrings []string) {
1212
"get_FileSystem": 2,
1313
"SpecialDirectoriesProxy": 10,
1414
"setShowInTaskBar": 20,
15-
"AESEncryptFile": 10,
16-
"AESDecryptFile": 10,
17-
"AESEncryptBytes": 10,
18-
"AESDecryptBytes": 10,
15+
}
16+
17+
cryptoImports := map[string]int{
18+
"AESEncryptFile": 40,
19+
"AESDecryptFile": 40,
20+
"AESEncryptBytes": 20,
21+
"AESDecryptBytes": 20,
22+
"CryptoStream": 20,
23+
"SymmetricAlgorithm": 20,
24+
"CreateEncryptor": 20,
25+
"System.Security.Cryptography": 30,
26+
"RijndaelManaged": 30,
27+
"set_KeySize": 30,
28+
"set_BlockSize": 30,
29+
"get_KeySize": 30,
30+
"set_IV": 30,
31+
"CipherMode": 30,
1932
}
2033

2134
for i := 0; i < len(extractedStrings); i++ {
@@ -24,6 +37,17 @@ func CalculatePointsStringDOTNET(extractedStrings []string) {
2437
InsertAnomalyString("La stringa "+extractedStrings[i]+" indica una funzione strettamente correlata ad un ransomware codificato in .NET.", pointsToAdd)
2538
}
2639
}
40+
41+
for stringToCompare, pointsToAdd := range cryptoImports {
42+
if strings.Contains(extractedStrings[i], stringToCompare) {
43+
InsertAnomalyString("La stringa \""+extractedStrings[i]+"\" indica una funzione della Crypto API di DotNet.", pointsToAdd)
44+
}
45+
}
46+
47+
if strings.Contains(extractedStrings[i], "Confuser.Core") {
48+
InsertAnomalyString("La stringa\""+"\" indica che molto probabilmente il programma è stato offuscato con Confuser.Core", 30)
49+
}
50+
2751
}
2852

2953
//AESEncryptFile, AESDecryptFile, AESEncryptBytes,AESDecryptBytes,CheckPassword,GenerateKey 20 per ognuno tranne gli ultimi due

heuristics/elf_headers_heuristics.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ func CheckELFHeader() {
3131
}
3232

3333
if len(sections) < int(elfHeader32.SectionEntryNumbers) {
34-
InsertAnomalyFileFormat("Non possono esserci sezioni \"nascoste\" ", 40)
34+
InsertAnomalyFileFormat("Il numero di sezioni non combacia con il numero di sezioni trovate all'interno dell'intestazione. ", 40)
35+
}
36+
37+
if len(sections) == 0 {
38+
InsertAnomalyFileFormat("Il binario non contiene alcuna sezione.", 20)
3539
}
3640

3741
} else {
@@ -45,9 +49,14 @@ func CheckELFHeader() {
4549
return
4650
}
4751

48-
if len(sections) < int(elfHeader32.SectionEntryNumbers) {
49-
InsertAnomalyFileFormat("Non possono esserci sezioni \"nascoste\" ", 40)
52+
if len(sections) < int(elfHeader64.SectionEntryNumbers) {
53+
InsertAnomalyFileFormat("Il numero di sezioni non combacia con il numero di sezioni trovate all'interno dell'intestazione. ", 40)
5054
}
55+
56+
if len(sections) == 0 {
57+
InsertAnomalyFileFormat("Il binario non contiene alcuna sezione.", 20)
58+
}
59+
5160
}
5261

5362
}

heuristics/pe_headers_heuristics.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,16 @@ func CheckHeaders() {
3434
}
3535

3636
CheckImageDataDirectories(dataDirectories, int(NumberOfRvaAndSizes))
37+
var MajorVersionWin uint16
3738
if FileAnalyzed.PEInterface.Is64bit {
3839
CheckOptionalHeader(optionalHeader64)
40+
MajorVersionWin = optionalHeader64.MajorOperatingSystemVersion
3941
} else {
4042
CheckOptionalHeader32(optionalHeader32)
43+
MajorVersionWin = optionalHeader32.MajorOperatingSystemVersion
44+
4145
}
42-
CheckCOFFHeader(&FileAnalyzed.PEInterface.COFFHeader)
46+
CheckCOFFHeader(&FileAnalyzed.PEInterface.COFFHeader, MajorVersionWin)
4347

4448
// Controllo checksum
4549
ExpectedChecksum := CalculateChecksum(FileAnalyzed.PEInterface.DosHeader.AddressExeOffset, uint32(len(FileAnalyzed.Raw)), FileAnalyzed.Raw)
@@ -161,7 +165,7 @@ func CheckOptionalHeader(header pe.PEPOptionalHeaderT) {
161165

162166
}
163167

164-
func CheckCOFFHeader(CoffHeader *pe.COFFHeaderT) {
168+
func CheckCOFFHeader(CoffHeader *pe.COFFHeaderT, MajorOperatingSystemVersion uint16) {
165169
// Controlla il COFFHeader
166170

167171
// Numero di sezioni è un intero positivo minore di 96
@@ -203,6 +207,7 @@ func CheckCOFFHeader(CoffHeader *pe.COFFHeaderT) {
203207

204208
// Controlla se un timestamp è futuro
205209
if unixTime.After(time.Now()) {
210+
// if unixTime.After(time.Now()) && MajorOperatingSystemVersion < 10
206211
unixTimeStr := fmt.Sprintf("%v", unixTime)
207212
InsertAnomalyFileFormat("Il timestamp del programma punta al futuro: "+unixTimeStr, 10)
208213
}

heuristics/resources_heuristics.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ func CalculatePointsResources(resources []pe.Resource) {
1010
// Quante risorse incontriamo vuote (dimensione 0)?
1111
blank := 0
1212

13+
// Quante risorse sono state
14+
entropy := 0
15+
1316
for i := 0; i < len(resources); i++ {
1417
if resources[i].ContentType == "binary/pe" {
1518
binary++
@@ -20,10 +23,14 @@ func CalculatePointsResources(resources []pe.Resource) {
2023
}
2124

2225
if resources[i].Entropy >= 6.6 {
23-
InsertAnomalyOthers("Il binario contiene delle risorse offuscate", 20)
26+
entropy++
2427
}
2528
}
2629

30+
if entropy > 0 {
31+
InsertAnomalyOthers("Il binario contiene delle risorse offuscate.", 20*entropy)
32+
}
33+
2734
if binary > 0 {
2835
InsertAnomalyOthers("Il binario contiene dei file eseguibili inseriti come risorse.", 20*binary)
2936
}

heuristics/sections_heuristics.go

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func CalculatePointsEntropy(sections interface{}) int {
1818

1919
for i := 0; i < len(sectionsIterable); i++ {
2020

21-
if sectionsIterable[i].Name == ".text" {
21+
if sectionsIterable[i].Name == ".text" || sectionsIterable[i].Name == "CODE" {
2222
isTextSectionFound = true
2323
}
2424

@@ -28,7 +28,7 @@ func CalculatePointsEntropy(sections interface{}) int {
2828
if sectionsIterable[i].Name == ".text" {
2929
InsertAnomalySection("Le istruzioni sono offuscate.", 120)
3030
} else {
31-
InsertAnomalySection("La sezione "+sectionsIterable[i].Name+" è offuscata.", 20)
31+
InsertAnomalySection("La sezione \""+sectionsIterable[i].Name+"\" è offuscata.", 20)
3232
}
3333
}
3434

@@ -42,15 +42,15 @@ func CalculatePointsEntropy(sections interface{}) int {
4242

4343
//
4444
if sectionsIterable[i].SizeOfRawData == 0 && sectionsIterable[i].VirtualSize == 0 {
45-
InsertAnomalySection("La sezione "+sectionsIterable[i].Name+" ha dimensione fisica e virtuale pari a 0.", 20)
45+
InsertAnomalySection("La sezione \""+sectionsIterable[i].Name+"\" ha dimensione fisica e virtuale pari a 0.", 20)
4646
}
4747

4848
if sectionsIterable[i].SizeOfRawData-sectionsIterable[i].VirtualSize > 40000 {
49-
InsertAnomalySection("La sezione "+sectionsIterable[i].Name+" ha una discrepanza importante tra la dimensione dichiarata e la dimensione virtuale.", 10)
49+
InsertAnomalySection("La sezione \""+sectionsIterable[i].Name+"\" ha una discrepanza importante tra la dimensione dichiarata e la dimensione virtuale.", 10)
5050
}
5151

5252
if sectionsIterable[i].VirtualSize == 0 {
53-
InsertAnomalySection("La sezione "+sectionsIterable[i].Name+" ha una dimensione virtuale pari a 0.", 20)
53+
InsertAnomalySection("La sezione \""+sectionsIterable[i].Name+"\" ha una dimensione virtuale pari a 0.", 20)
5454
}
5555
}
5656

@@ -71,7 +71,7 @@ func CalculatePointsEntropy(sections interface{}) int {
7171
if sectionsIterable[i].Name == ".text" {
7272
InsertAnomalySection("Le istruzioni sono offuscate.", 120)
7373
} else {
74-
InsertAnomalySection("La sezione "+sectionsIterable[i].Name+" è offuscata.", 20)
74+
InsertAnomalySection("La sezione \""+sectionsIterable[i].Name+"\" è offuscata.", 20)
7575
}
7676
}
7777

@@ -88,7 +88,7 @@ func CalculatePointsEntropy(sections interface{}) int {
8888
if sectionsIterable[i].Name == ".text" {
8989
InsertAnomalySection("Le istruzioni sono offuscate.", 120)
9090
} else {
91-
InsertAnomalySection("La sezione "+sectionsIterable[i].Name+" è offuscata.", 20)
91+
InsertAnomalySection("La sezione \""+sectionsIterable[i].Name+"\" è offuscata.", 20)
9292
}
9393
}
9494

@@ -128,6 +128,24 @@ func checkSectionName(name string, isElf bool) {
128128
".gnu.hash",
129129
".gnu.version",
130130
".gnu.version_r",
131+
".rela.dyn",
132+
".rela.plt",
133+
".init",
134+
".plt",
135+
".text",
136+
".fini",
137+
".rodata",
138+
".eh_frame_hdr",
139+
".eh_frame",
140+
".tbss",
141+
".ctors",
142+
".dtors",
143+
".dynamic",
144+
".got.plt",
145+
".data",
146+
".bss",
147+
".comment",
148+
".shstrtab",
131149
}
132150
defaultSectionName = defaultSectionsName
133151
} else {
@@ -143,22 +161,31 @@ func checkSectionName(name string, isElf bool) {
143161
".pdata",
144162
".reloc",
145163
".symtab",
164+
".tls",
165+
".eh_fram",
166+
".imrsiv",
167+
".CRT",
168+
"CODE",
169+
"BSS",
170+
"DATA",
171+
".didat",
172+
".gfids",
146173
}
147174
defaultSectionName = defaultSectionsName
148175
}
149176

150-
// Conta quante sezioni sono valide, se esistono meno di 1 sezione valida allora inserisci l'anomalia
151177
isFound := false
152178
for i := 0; i < len(defaultSectionName); i++ {
153179
if name == defaultSectionName[i] {
154180
isFound = true
181+
// Conta quante sezioni sono valide, se esistono meno di 1 sezione valida allora inserisci l'anomalia
155182
sectionsStandards++
156183
break
157184
}
158185
}
159186

160187
if !isFound {
161-
InsertAnomalySection("La sezione \""+name+"\" non è standard.", 10)
188+
InsertAnomalySection("La sezione \""+name+"\" non è una sezione standard.", 10)
162189
}
163190

164191
}

0 commit comments

Comments
 (0)