mirror of
https://github.com/mandiant/GoReSym
synced 2026-06-08 15:40:15 +00:00
Implement Regex Needle Optimization
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
module github.com/mandiant/GoReSym
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/elliotchance/orderedmap v1.4.0
|
||||
@@ -12,4 +12,5 @@ require (
|
||||
require (
|
||||
github.com/felixge/fgprof v0.9.3 // indirect
|
||||
github.com/google/pprof v0.0.0-20230728192033-2ba5b33183c6 // indirect
|
||||
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb
|
||||
)
|
||||
|
||||
@@ -24,6 +24,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff h1:XmKBi9R6duxOB3lfc72wyrwiOY7X2Jl1wuI+RFOyMDE=
|
||||
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb h1:mIKbk8weKhSeLH2GmUTrvx8CjkyJmnU1wFmg59CUjFA=
|
||||
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
+70
-106
@@ -5,6 +5,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"rsc.io/binaryregexp"
|
||||
)
|
||||
|
||||
@@ -42,14 +43,14 @@ func isHex(s string) bool {
|
||||
// although this requires more code, we provide this functionality
|
||||
// because these patterns are *much* more readable than raw regular expressions,
|
||||
// we strongly value people being able to understand GoReSym's algorithm.
|
||||
func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
func RegexpPatternFromYaraPattern(pattern string) (*RegexAndNeedle, error) {
|
||||
|
||||
if !strings.HasPrefix(pattern, "{") {
|
||||
return "", errors.New("missing prefix")
|
||||
return nil, errors.New("missing prefix")
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(pattern, "}") {
|
||||
return "", errors.New("missing suffix")
|
||||
return nil, errors.New("missing suffix")
|
||||
}
|
||||
|
||||
pattern = strings.Trim(pattern, "{}")
|
||||
@@ -58,6 +59,10 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
|
||||
pattern = strings.ToLower(pattern)
|
||||
|
||||
patLen := 0
|
||||
needle := make([]byte, 0)
|
||||
tmpNeedle := make([]byte, 0)
|
||||
|
||||
var regex_pattern string
|
||||
for i := 0; i < len(pattern); {
|
||||
// at the start of this loop,
|
||||
@@ -71,12 +76,19 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
// output: .
|
||||
if c == "?" {
|
||||
if d != "?" {
|
||||
return "", errors.New("cannot mask the first nibble")
|
||||
return nil, errors.New("cannot mask the first nibble")
|
||||
}
|
||||
|
||||
regex_pattern += "."
|
||||
|
||||
i += 2
|
||||
patLen += 1
|
||||
if len(tmpNeedle) > len(needle) {
|
||||
needle = slices.Clone(tmpNeedle)
|
||||
tmpNeedle = make([]byte, 0)
|
||||
} else {
|
||||
tmpNeedle = make([]byte, 0)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -85,23 +97,23 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
if c == "[" {
|
||||
end := strings.Index(pattern[i:], "]")
|
||||
if end == -1 {
|
||||
return "", errors.New("unbalanced [")
|
||||
return nil, errors.New("unbalanced [")
|
||||
}
|
||||
|
||||
chunk := pattern[i+1 : i+end]
|
||||
low, high, found := strings.Cut(chunk, "-")
|
||||
if !found {
|
||||
return "", errors.New("[] didn't contain a dash")
|
||||
return nil, errors.New("[] didn't contain a dash")
|
||||
}
|
||||
|
||||
_, err := strconv.Atoi(low)
|
||||
if err != nil {
|
||||
return "", errors.New("invalid number")
|
||||
return nil, errors.New("invalid number")
|
||||
}
|
||||
|
||||
_, err = strconv.Atoi(high)
|
||||
if err != nil {
|
||||
return "", errors.New("invalid number")
|
||||
return nil, errors.New("invalid number")
|
||||
}
|
||||
|
||||
regex_pattern += "."
|
||||
@@ -112,6 +124,14 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
regex_pattern += "}"
|
||||
|
||||
i += end + 1
|
||||
patLen += 1
|
||||
|
||||
if len(tmpNeedle) > len(needle) {
|
||||
needle = slices.Clone(tmpNeedle)
|
||||
tmpNeedle = make([]byte, 0)
|
||||
} else {
|
||||
tmpNeedle = make([]byte, 0)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -120,7 +140,7 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
if c == "(" {
|
||||
end := strings.Index(pattern[i:], ")")
|
||||
if end == -1 {
|
||||
return "", errors.New("unbalanced (")
|
||||
return nil, errors.New("unbalanced (")
|
||||
}
|
||||
|
||||
chunk := pattern[i+1 : i+end]
|
||||
@@ -129,7 +149,7 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
regex_pattern += "("
|
||||
for j, choice := range choices {
|
||||
if !isHex(choice) {
|
||||
return "", errors.New("choice not hex")
|
||||
return nil, errors.New("choice not hex")
|
||||
}
|
||||
|
||||
if j != 0 {
|
||||
@@ -141,6 +161,13 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
regex_pattern += ")"
|
||||
|
||||
i += end + 1
|
||||
patLen += len(choices)
|
||||
if len(tmpNeedle) > len(needle) {
|
||||
needle = slices.Clone(tmpNeedle)
|
||||
tmpNeedle = make([]byte, 0)
|
||||
} else {
|
||||
tmpNeedle = make([]byte, 0)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -148,7 +175,7 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
// output: [\x00-\x0F]
|
||||
if d == "?" {
|
||||
if !isHex(c) {
|
||||
return "", errors.New("not hex digit")
|
||||
return nil, errors.New("not hex digit")
|
||||
}
|
||||
|
||||
regex_pattern += "["
|
||||
@@ -158,6 +185,13 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
regex_pattern += "]"
|
||||
|
||||
i += 2
|
||||
patLen += 1
|
||||
if len(tmpNeedle) > len(needle) {
|
||||
needle = slices.Clone(tmpNeedle)
|
||||
tmpNeedle = make([]byte, 0)
|
||||
} else {
|
||||
tmpNeedle = make([]byte, 0)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -165,117 +199,47 @@ func RegexpPatternFromYaraPattern(pattern string) (string, error) {
|
||||
// output: \xAB
|
||||
if isHex(c) && isHex(d) {
|
||||
regex_pattern += `\x` + strings.ToUpper(c+d)
|
||||
|
||||
byt, err := strconv.ParseInt(c+d, 16, 64)
|
||||
if err != nil {
|
||||
return nil, errors.New("not hex digit")
|
||||
}
|
||||
tmpNeedle = append(tmpNeedle, byte(byt))
|
||||
i += 2
|
||||
patLen += 1
|
||||
continue
|
||||
}
|
||||
|
||||
return "", errors.New("unexpected value")
|
||||
return nil, errors.New("unexpected value")
|
||||
}
|
||||
|
||||
return regex_pattern, nil
|
||||
}
|
||||
|
||||
func RegexpFromYaraPattern(pattern string) (*binaryregexp.Regexp, error) {
|
||||
regex_pattern, e := RegexpPatternFromYaraPattern(pattern)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
if len(tmpNeedle) > len(needle) {
|
||||
needle = slices.Clone(tmpNeedle)
|
||||
//tmpNeedle = make([]byte, 0) not needed at exit
|
||||
}
|
||||
|
||||
r := binaryregexp.MustCompile(regex_pattern)
|
||||
if r == nil {
|
||||
return nil, errors.New("failed to compile regex")
|
||||
}
|
||||
|
||||
return r, nil
|
||||
return &RegexAndNeedle{patLen, regex_pattern, r, needle}, nil
|
||||
}
|
||||
|
||||
type BinaryRegexpGroup struct {
|
||||
patterns map[string]string
|
||||
|
||||
re *binaryregexp.Regexp
|
||||
}
|
||||
|
||||
func NewBinaryRegexpGroup(patterns map[string]string) (*BinaryRegexpGroup, error) {
|
||||
|
||||
var pattern string
|
||||
|
||||
i := 0
|
||||
pattern += "("
|
||||
for k, v := range patterns {
|
||||
if i != 0 {
|
||||
pattern += "|"
|
||||
}
|
||||
i += 1
|
||||
|
||||
pattern += "(?P"
|
||||
pattern += "<" + k + ">"
|
||||
pattern += v
|
||||
pattern += ")"
|
||||
}
|
||||
pattern += ")"
|
||||
|
||||
re := binaryregexp.MustCompile(pattern)
|
||||
if re == nil {
|
||||
return nil, errors.New("failed to compile regex")
|
||||
}
|
||||
|
||||
return &BinaryRegexpGroup{
|
||||
patterns: patterns,
|
||||
re: re,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type BinaryRegexGroupMatches struct {
|
||||
g *BinaryRegexpGroup
|
||||
matches [][]int
|
||||
}
|
||||
|
||||
func (g *BinaryRegexpGroup) FindAllIndex(buf []byte, n int) *BinaryRegexGroupMatches {
|
||||
matches := g.re.FindAllIndex(buf, n)
|
||||
|
||||
return &BinaryRegexGroupMatches{
|
||||
g: g,
|
||||
matches: matches,
|
||||
}
|
||||
}
|
||||
|
||||
// fetch the index of the subexp for the given regexp.
|
||||
//
|
||||
// this is called `(*Regexp) SubexpIndex` in recent Go,
|
||||
// but doesn't seem to be implemented in binaryregexp.
|
||||
// https://pkg.go.dev/regexp#Regexp.SubexpIndex
|
||||
func SubexpIndex(re *binaryregexp.Regexp, name string) int {
|
||||
for i, n := range re.SubexpNames() {
|
||||
if n == name {
|
||||
return i
|
||||
func FindRegex(data []byte, regexInfo *RegexAndNeedle) []int {
|
||||
matches := make([]int, 0)
|
||||
needleMatches := findAllOccurrences(data, [][]byte{regexInfo.needle})
|
||||
for _, needleMatch := range needleMatches {
|
||||
for _, reMatch := range regexInfo.re.FindAllIndex(data[needleMatch-regexInfo.len:needleMatch+regexInfo.len], -1) {
|
||||
start := reMatch[0]
|
||||
//end := reMatch[1]
|
||||
matches = append(matches, start)
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
return matches
|
||||
}
|
||||
|
||||
// fetch the [start, end] pairs for the subexp with the given name in the given matches.
|
||||
func SubexpIndexMatches(re *binaryregexp.Regexp, matches [][]int, name string) [][]int {
|
||||
index := SubexpIndex(re, name)
|
||||
|
||||
var ret [][]int
|
||||
for _, match := range matches {
|
||||
|
||||
start := match[2*index]
|
||||
end := match[2*index+1]
|
||||
|
||||
if start == -1 && end == -1 {
|
||||
continue
|
||||
}
|
||||
|
||||
ret = append(ret, []int{start, end})
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// fetch the [start, end] pairs for the subexp with the given name.
|
||||
func (m *BinaryRegexGroupMatches) MatchesForSubexp(name string) [][]int {
|
||||
return SubexpIndexMatches(m.g.re, m.matches, name)
|
||||
type RegexAndNeedle struct {
|
||||
len int
|
||||
rawre string
|
||||
re *binaryregexp.Regexp
|
||||
needle []byte // longest fixed sub-sequence of regex
|
||||
}
|
||||
|
||||
+21
-56
@@ -1,7 +1,7 @@
|
||||
package objfile
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"rsc.io/binaryregexp"
|
||||
@@ -104,53 +104,6 @@ func TestRegexGrouping(t *testing.T) {
|
||||
t.Errorf("5")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("two groups", func(t *testing.T) {
|
||||
re := binaryregexp.MustCompile(`((?P<xxx>a(x*)b)|(?P<yyy>c(y*)d))`)
|
||||
|
||||
fmt.Printf("aa: %v\n", re)
|
||||
fmt.Printf("%q\n", re.SubexpNames())
|
||||
|
||||
if SubexpIndex(re, "xxx") != 2 {
|
||||
t.Errorf("xxx index")
|
||||
}
|
||||
|
||||
if SubexpIndex(re, "yyy") != 4 {
|
||||
t.Errorf("yyy index")
|
||||
}
|
||||
|
||||
if !compare(SubexpIndexMatches(re, re.FindAllStringSubmatchIndex("--ab--", -1), "xxx"), [][]int{{2, 4}}) {
|
||||
t.Errorf("1")
|
||||
}
|
||||
|
||||
if !compare(SubexpIndexMatches(re, re.FindAllStringSubmatchIndex("--axxb--", -1), "xxx"), [][]int{{2, 6}}) {
|
||||
t.Errorf("2")
|
||||
}
|
||||
|
||||
if !compare(SubexpIndexMatches(re, re.FindAllStringSubmatchIndex("--ab--", -1), "yyy"), [][]int{}) {
|
||||
t.Errorf("3: no matches")
|
||||
}
|
||||
|
||||
if !compare(SubexpIndexMatches(re, re.FindAllStringSubmatchIndex("--cd--", -1), "xxx"), [][]int{}) {
|
||||
t.Errorf("4: no matches")
|
||||
}
|
||||
|
||||
if !compare(SubexpIndexMatches(re, re.FindAllStringSubmatchIndex("--cd--", -1), "yyy"), [][]int{{2, 4}}) {
|
||||
t.Errorf("5")
|
||||
}
|
||||
|
||||
if !compare(SubexpIndexMatches(re, re.FindAllStringSubmatchIndex("--cyyd--", -1), "yyy"), [][]int{{2, 6}}) {
|
||||
t.Errorf("6")
|
||||
}
|
||||
|
||||
if !compare(SubexpIndexMatches(re, re.FindAllStringSubmatchIndex("--abcd--", -1), "xxx"), [][]int{{2, 4}}) {
|
||||
t.Errorf("7")
|
||||
}
|
||||
|
||||
if !compare(SubexpIndexMatches(re, re.FindAllStringSubmatchIndex("--abcd--", -1), "yyy"), [][]int{{4, 6}}) {
|
||||
t.Errorf("8")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRegexpPatternFromYaraPattern(t *testing.T) {
|
||||
@@ -159,51 +112,63 @@ func TestRegexpPatternFromYaraPattern(t *testing.T) {
|
||||
t.Errorf("empty pattern should have errored")
|
||||
}
|
||||
|
||||
p, err := RegexpPatternFromYaraPattern("{}")
|
||||
reg, err := RegexpPatternFromYaraPattern("{}")
|
||||
if err != nil {
|
||||
t.Errorf("empty pattern errored")
|
||||
}
|
||||
if p != "" {
|
||||
if reg.rawre != "" {
|
||||
t.Errorf("incorrect empty pattern")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("x64firstmoduledata", func(t *testing.T) {
|
||||
p, err := RegexpPatternFromYaraPattern("{ 48 8D 0? ?? ?? ?? ?? EB ?? 48 8? 8? ?? 02 00 00 66 0F 1F 44 00 00 }")
|
||||
reg, err := RegexpPatternFromYaraPattern("{ 48 8D 0? ?? ?? ?? ?? EB ?? 48 8? 8? ?? 02 00 00 66 0F 1F 44 00 00 }")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("pattern errored")
|
||||
}
|
||||
|
||||
// manually translated
|
||||
if p != `\x48\x8D[\x00-\x0F]....\xEB.\x48[\x80-\x8F][\x80-\x8F].\x02\x00\x00\x66\x0F\x1F\x44\x00\x00` {
|
||||
if reg.rawre != `\x48\x8D[\x00-\x0F]....\xEB.\x48[\x80-\x8F][\x80-\x8F].\x02\x00\x00\x66\x0F\x1F\x44\x00\x00` {
|
||||
t.Errorf("incorrect pattern")
|
||||
}
|
||||
|
||||
if !bytes.Equal(reg.needle, []byte{02, 00, 00, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00}) {
|
||||
t.Errorf("incorrect needle")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("x86sig", func(t *testing.T) {
|
||||
p, err := RegexpPatternFromYaraPattern("{ 8D ?? ?? ?? ?? ?? EB ?? [0-50] 8B ?? ?? 01 00 00 8B ?? ?? ?? 85 ?? 75 ?? }")
|
||||
reg, err := RegexpPatternFromYaraPattern("{ 8D ?? ?? ?? ?? ?? EB ?? [0-50] 8B ?? ?? 01 00 00 8B ?? ?? ?? 85 ?? 75 ?? }")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("pattern errored")
|
||||
}
|
||||
|
||||
// manually translated
|
||||
if p != `\x8D.....\xEB..{0,50}\x8B..\x01\x00\x00\x8B...\x85.\x75.` {
|
||||
if reg.rawre != `\x8D.....\xEB..{0,50}\x8B..\x01\x00\x00\x8B...\x85.\x75.` {
|
||||
t.Errorf("incorrect pattern")
|
||||
}
|
||||
|
||||
if !bytes.Equal(reg.needle, []byte{0x01, 0x00, 0x00, 0x8B}) {
|
||||
t.Errorf("incorrect needle")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("arm64", func(t *testing.T) {
|
||||
p, err := RegexpPatternFromYaraPattern("{ ?? ?? ?? (90 | b0 | f0 | d0) ?? ?? ?? 91 ?? ?? ?? (14 | 17) ?? ?? 41 F9 ?? ?? ?? B4 }")
|
||||
reg, err := RegexpPatternFromYaraPattern("{ ?? ?? ?? (90 | b0 | f0 | d0) ?? ?? ?? 91 ?? ?? ?? (14 | 17) ?? ?? 41 F9 ?? ?? ?? B4 }")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("pattern errored")
|
||||
}
|
||||
|
||||
// manually translated
|
||||
if p != `...(\x90|\xB0|\xF0|\xD0)...\x91...(\x14|\x17)..\x41\xF9...\xB4` {
|
||||
if reg.rawre != `...(\x90|\xB0|\xF0|\xD0)...\x91...(\x14|\x17)..\x41\xF9...\xB4` {
|
||||
t.Errorf("incorrect pattern")
|
||||
}
|
||||
|
||||
if !bytes.Equal(reg.needle, []byte{0x41, 0xF9}) {
|
||||
t.Errorf("incorrect needle")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+32
-29
@@ -1,8 +1,6 @@
|
||||
package objfile
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
import "encoding/binary"
|
||||
|
||||
type signatureModuleDataInitx64 struct {
|
||||
moduleDataPtrLoc uint64 // offset in signature to the location of the pointer to the PCHeader
|
||||
@@ -81,22 +79,13 @@ var ARM32_sig = signatureModuleDataInitARM32{0, `{ ?? ?? 9F E5 ?? ?? ?? EA ?? ??
|
||||
func findModuleInitPCHeader(data []byte, sectionBase uint64) []SignatureMatch {
|
||||
var matches []SignatureMatch = make([]SignatureMatch, 0)
|
||||
|
||||
g, e := NewBinaryRegexpGroup(map[string]string{
|
||||
"x64": x64sig.signature,
|
||||
"x86": x86sig.signature,
|
||||
"ARM64": ARM64_sig.signature,
|
||||
"ARM32": ARM32_sig.signature,
|
||||
"PPC_BE": PPC_BE_sig.signature,
|
||||
})
|
||||
if e != nil {
|
||||
// programmer error: check the patterns
|
||||
panic(e)
|
||||
x64reg, err := RegexpPatternFromYaraPattern(x64sig.signature)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
m := g.FindAllIndex(data, -1)
|
||||
|
||||
for _, match := range m.MatchesForSubexp("x64") {
|
||||
sigPtr := uint64(match[0]) // from int
|
||||
for _, match := range FindRegex(data, x64reg) {
|
||||
sigPtr := uint64(match) // from int
|
||||
|
||||
// this is the pointer offset stored in the instruction
|
||||
// 0x44E06A: 48 8D 0D 4F F0 24 00 lea rcx, off_69D0C0 (result: 0x24f04f)
|
||||
@@ -110,8 +99,13 @@ func findModuleInitPCHeader(data []byte, sectionBase uint64) []SignatureMatch {
|
||||
})
|
||||
}
|
||||
|
||||
for _, match := range m.MatchesForSubexp("x86") {
|
||||
sigPtr := uint64(match[0]) // from int
|
||||
x86reg, err := RegexpPatternFromYaraPattern(x86sig.signature)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, match := range FindRegex(data, x86reg) {
|
||||
sigPtr := uint64(match) // from int
|
||||
|
||||
moduleDataPtr := uint64(binary.LittleEndian.Uint32(data[sigPtr+x86sig.moduleDataPtrLoc:][:4]))
|
||||
matches = append(matches, SignatureMatch{
|
||||
@@ -119,8 +113,13 @@ func findModuleInitPCHeader(data []byte, sectionBase uint64) []SignatureMatch {
|
||||
})
|
||||
}
|
||||
|
||||
for _, match := range m.MatchesForSubexp("ARM64") {
|
||||
sigPtr := uint64(match[0]) // from int
|
||||
arm64reg, err := RegexpPatternFromYaraPattern(ARM64_sig.signature)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, match := range FindRegex(data, arm64reg) {
|
||||
sigPtr := uint64(match) // from int
|
||||
|
||||
adrp := binary.LittleEndian.Uint32(data[sigPtr+ARM64_sig.moduleDataPtrADRP:][:4])
|
||||
add := binary.LittleEndian.Uint32(data[sigPtr+ARM64_sig.moduleDataPtrADD:][:4])
|
||||
@@ -140,28 +139,32 @@ func findModuleInitPCHeader(data []byte, sectionBase uint64) []SignatureMatch {
|
||||
})
|
||||
}
|
||||
|
||||
for _, match := range m.MatchesForSubexp("ARM32") {
|
||||
sigPtr := uint64(match[0]) // from int
|
||||
arm32reg, err := RegexpPatternFromYaraPattern(ARM32_sig.signature)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, match := range FindRegex(data, arm32reg) {
|
||||
sigPtr := uint64(match) // from int
|
||||
ldr := binary.LittleEndian.Uint32(data[sigPtr+ARM32_sig.moduleDataPtrLDR:][:4])
|
||||
|
||||
// ARM PC relative is always +8 due to legacy nonsense
|
||||
ldr_pointer_stub := uint64((ldr & 0x00000FFF) + 8)
|
||||
final := uint64(binary.LittleEndian.Uint32(data[sigPtr+ARM32_sig.moduleDataPtrLDR+ldr_pointer_stub:][:4]))
|
||||
|
||||
matches = append(matches, SignatureMatch{
|
||||
final,
|
||||
})
|
||||
}
|
||||
|
||||
for _, match := range m.MatchesForSubexp("PPC_BE") {
|
||||
sigPtr := uint64(match[0]) // from int
|
||||
ppcBEreg, err := RegexpPatternFromYaraPattern(PPC_BE_sig.signature)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, match := range FindRegex(data, ppcBEreg) {
|
||||
sigPtr := uint64(match) // from int
|
||||
moduleDataPtrHi := int64(binary.BigEndian.Uint16(data[sigPtr+PPC_BE_sig.moduleDataPtrHi:][:2]))
|
||||
|
||||
// addi takes a signed immediate
|
||||
moduleDataPtrLo := int64(int16(binary.BigEndian.Uint16(data[sigPtr+PPC_BE_sig.moduleDataPtrLo:][:2])))
|
||||
|
||||
moduleDataIpOffset := uint64((moduleDataPtrHi << 16) + moduleDataPtrLo)
|
||||
matches = append(matches, SignatureMatch{
|
||||
moduleDataIpOffset,
|
||||
|
||||
Reference in New Issue
Block a user