forked from EgeBalci/sgn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
decode.go
155 lines (132 loc) · 4.38 KB
/
decode.go
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package sgn
import (
"encoding/binary"
"errors"
"fmt"
"strings"
)
// STUB will contain the decoder stub for the selected architecture
// Values will be set on init
var STUB map[int]string
// x86DecoderStub is base decoder assembly for 32 bit binaries
const x86DecoderStub = `
CALL getip
getip:
POP {R}
MOV ECX,{S}
MOV {RL},{K}
decode:
XOR BYTE PTR [{R}+ECX+data-6],{RL}
ADD {RL},BYTE PTR [{R}+ECX+data-6]
LOOP decode
data:
`
// x64DecoderStub is base decoder assembly for 64 bit binaries
const x64DecoderStub = `
MOV {RL},{K}
MOV RCX,{S}
LEA {R},[RIP+data-1]
decode:
XOR BYTE PTR [{R}+RCX],{RL}
ADD {RL},BYTE PTR [{R}+RCX]
LOOP decode
data:
`
// NewDecoderAssembly creates a unobfuscated decoder stub to the given encoded payload
// with the given architecture and seed value
func (encoder *Encoder) NewDecoderAssembly(payloadSize int) string {
decoder := STUB[encoder.architecture]
reg := encoder.GetSafeRandomRegister(encoder.architecture, "ECX")
regL := encoder.GetSafeRandomRegister(8, reg, "CL")
decoder = strings.ReplaceAll(decoder, "{R}", reg)
decoder = strings.ReplaceAll(decoder, "{RL}", regL)
decoder = strings.ReplaceAll(decoder, "{K}", fmt.Sprintf("0x%x", encoder.Seed))
decoder = strings.ReplaceAll(decoder, "{S}", fmt.Sprintf("0x%x", payloadSize))
//fmt.Println(decoder)
return decoder
}
// AddADFLDecoder creates decoder stub for binaries that are ciphered with CipherADFL function.
func (encoder *Encoder) AddADFLDecoder(payload []byte) ([]byte, error) {
decoderAssembly := encoder.NewDecoderAssembly(len(payload))
decoder, ok := encoder.Assemble(decoderAssembly)
if !ok {
return nil, errors.New("decoder assembly failed")
}
return append(decoder, payload...), nil
}
// AddSchemaDecoder creates decoder stub for binaries that are ciphered with SchemaCipher function.
// The schema array that is used on the given payload, architecture of the payload and obfuscation level is required.
func (encoder *Encoder) AddSchemaDecoder(payload []byte, schema SCHEMA) ([]byte, error) {
index := 0
// Add garbage instrctions before the ciphered decoder stub
garbage, err := encoder.GenerateGarbageInstructions()
if err != nil {
return nil, err
}
payload = append(garbage, payload...)
index += len(garbage)
// Add call instruction over the ciphered payload
payload, err = encoder.AddCallOver(payload)
if err != nil {
return nil, err
}
// Add garbage instrctions after the ciphered decoder stub
garbage, err = encoder.GenerateGarbageInstructions()
if err != nil {
return nil, err
}
payload = append(garbage, payload...)
reg := encoder.GetRandomRegister(encoder.architecture)
// Toss a coin for get the garbage+decoder address to register by pop or mov
if CoinFlip() {
pop, ok := encoder.Assemble(fmt.Sprintf("POP %s;", reg)) // !!
if !ok {
return nil, errors.New("schema decoder assembly failed")
}
payload = append(payload, pop...)
} else {
mov, ok := encoder.Assemble(fmt.Sprintf("MOV %s,[%s];", reg, encoder.GetStackPointer())) // !!
if !ok {
return nil, errors.New("schema decoder assembly failed")
}
sub, ok := encoder.Assemble(fmt.Sprintf("SUB %s,0x%x;", encoder.GetStackPointer(), encoder.architecture/8)) // !!
if !ok {
return nil, errors.New("schema decoder assembly failed")
}
payload = append(payload, append(mov, sub...)...)
}
for _, cursor := range schema {
// Mandatory obfuscation with coin flip for true polimorphism
garbage, err = encoder.GenerateGarbageInstructions()
if err != nil {
return nil, err
}
payload = append(payload, garbage...)
stepAssembly := ""
if cursor.Key == nil {
stepAssembly += fmt.Sprintf("\t%s DWORD PTR [%s+0x%x];\n", cursor.OP, reg, index)
} else {
stepAssembly += fmt.Sprintf("\t%s DWORD PTR [%s+0x%x],0x%x;\n", cursor.OP, reg, index, binary.BigEndian.Uint32(cursor.Key))
}
//fmt.Println(stepAssembly)
decipherStep, ok := encoder.Assemble(stepAssembly)
if !ok {
//fmt.Println(stepAssembly)
return nil, errors.New("schema decoder step assembly failed")
}
payload = append(payload, decipherStep...)
index += 4
}
// More possibilities...
returnAssembly := ""
if CoinFlip() {
returnAssembly = fmt.Sprintf("jmp %s;", reg)
} else {
returnAssembly = fmt.Sprintf("push %s;ret;", reg)
}
returnInstruction, ok := encoder.Assemble(returnAssembly)
if !ok {
return nil, errors.New("schema decoder return assembly failed")
}
return append(payload, returnInstruction...), nil
}