hillu / go-yara

Go bindings for YARA
BSD 2-Clause "Simplified" License
354 stars 114 forks source link

segmentation violation when match found #58

Closed idrii closed 4 years ago

idrii commented 4 years ago

I've run into a weird issue while playing with go-yara in a test project. After further testing I've found that the same issue occurs in the simple-yara test thats provided with this repo.

The yara rule I'm using in my testing is a very basic detection for Mimikatz:

rule MimikatzMem
{
    strings:
        $s1 = "sekurlsa::msv" fullword ascii
        $s2 = "sekurlsa::wdigest" fullword ascii
        $s4 = "sekurlsa::kerberos" fullword ascii
        $s5 = "sekurlsa::tspkg" fullword ascii
        $s6 = "sekurlsa::livessp" fullword ascii
        $s7 = "sekurlsa::ssp" fullword ascii
        $s8 = "sekurlsa::logonPasswords" fullword ascii
        $s9 = "sekurlsa::process" fullword ascii
        $s10 = "sekurlsa::minidump" fullword ascii
        $s11 = "sekurlsa::pth" fullword ascii
        $s12 = "sekurlsa::tickets" fullword ascii
        $s13 = "sekurlsa::ekeys" fullword ascii
        $s14 = "sekurlsa::dpapi" fullword ascii
        $s15 = "sekurlsa::credman" fullword ascii
    condition:
        1 of them
}

As this rule will match on itself the error I'm seeing can be triggered by scanning the rule itself (i.e. ./simple-yara -rule rules.yar rules.yar)

Doing so produces the following crash:

2020/01/02 14:43:37 Scanning file rules.yar... 
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x80 addr=0x0 pc=0x4b4687]

runtime stack:
runtime.throw(0x4fcbd1, 0x2a)
    /home/user/usr/local/go/src/runtime/panic.go:774 +0x72
runtime.sigpanic()
    /home/user/usr/local/go/src/runtime/signal_unix.go:378 +0x47c

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x4b4650, 0xc0000bd678, 0x1)
    /home/user/usr/local/go/src/runtime/cgocall.go:128 +0x5b fp=0xc0000bd648 sp=0xc0000bd610 pc=0x405beb
github.com/hillu/go-yara._Cfunc_string_matches(0x27fa400, 0x0, 0xc00009c0bc)
    _cgo_gotypes.go:1070 +0x45 fp=0xc0000bd678 sp=0xc0000bd648 pc=0x4a4e85
github.com/hillu/go-yara.(*String).Matches(0xc0000bd7a0, 0x0, 0x0, 0x0)
    /home/user/go/src/github.com/hillu/go-yara/rule.go:225 +0x6b fp=0xc0000bd710 sp=0xc0000bd678 pc=0x4a82eb
github.com/hillu/go-yara.(*Rule).getMatchStrings(0xc00009e050, 0x0, 0x0, 0x0)
    /home/user/go/src/github.com/hillu/go-yara/rule.go:244 +0x2c2 fp=0xc0000bd818 sp=0xc0000bd710 pc=0x4a8742
github.com/hillu/go-yara.(*MatchRules).RuleMatching(0xc0000940c0, 0xc00009e050, 0xc0000940c0, 0x7f507c7e6fa8, 0xc0000940c0)
    /home/user/go/src/github.com/hillu/go-yara/rules_callback.go:151 +0x224 fp=0xc0000bd978 sp=0xc0000bd818 pc=0x4a95b4
github.com/hillu/go-yara.scanCallbackFunc(0x1, 0x27f9020, 0x278e7e0, 0x40e4b6)
    /home/user/go/src/github.com/hillu/go-yara/rules_callback.go:90 +0x220 fp=0xc0000bda58 sp=0xc0000bd978 pc=0x4a8fc0
github.com/hillu/go-yara._cgoexpwrap_08a63f7e5a95_scanCallbackFunc(0x1, 0x27f9020, 0x278e7e0, 0xee341bf499c3200)
    _cgo_gotypes.go:1570 +0x3d fp=0xc0000bda88 sp=0xc0000bda58 pc=0x4a595d
runtime.call32(0x0, 0x7ffeaaa3b570, 0x7ffeaaa3b600, 0x20)
    /home/user/usr/local/go/src/runtime/asm_amd64.s:539 +0x3b fp=0xc0000bdab8 sp=0xc0000bda88 pc=0x455abb
runtime.cgocallbackg1(0x0)
    /home/user/usr/local/go/src/runtime/cgocall.go:314 +0x1b7 fp=0xc0000bdba0 sp=0xc0000bdab8 pc=0x405f97
runtime.cgocallbackg(0x0)
    /home/user/usr/local/go/src/runtime/cgocall.go:191 +0xc1 fp=0xc0000bdc08 sp=0xc0000bdba0 pc=0x405d41
runtime.cgocallback_gofunc(0x405c0f, 0x4b4860, 0xc0000bdc98, 0xc0000bdc88)
    /home/user/usr/local/go/src/runtime/asm_amd64.s:793 +0x9b fp=0xc0000bdc28 sp=0xc0000bdc08 pc=0x45708b
runtime.asmcgocall(0x4b4860, 0xc0000bdc98)
    /home/user/usr/local/go/src/runtime/asm_amd64.s:640 +0x42 fp=0xc0000bdc30 sp=0xc0000bdc28 pc=0x456f22
runtime.cgocall(0x4b4860, 0xc0000bdc98, 0xc0000bdc90)
    /home/user/usr/local/go/src/runtime/cgocall.go:131 +0x7f fp=0xc0000bdc68 sp=0xc0000bdc30 pc=0x405c0f
github.com/hillu/go-yara._Cfunc_yr_rules_scan_file(0x27f8ed0, 0x27cc090, 0x0, 0x4b3f00, 0x278e7e0, 0x0, 0x0)
    _cgo_gotypes.go:1455 +0x4d fp=0xc0000bdc98 sp=0xc0000bdc68 pc=0x4a542d
github.com/hillu/go-yara.(*Rules).ScanFileWithCallback.func2(0xc00009e038, 0x27cc090, 0x0, 0x278e7e0, 0x0, 0xc0000bddb8)
    /home/user/go/src/github.com/hillu/go-yara/rules.go:121 +0xe6 fp=0xc0000bdcf0 sp=0xc0000bdc98 pc=0x4aade6
github.com/hillu/go-yara.(*Rules).ScanFileWithCallback(0xc00009e038, 0x7ffeaaa3d520, 0x9, 0x0, 0x0, 0x4d3240, 0xc0000940c0, 0x0, 0x0)
    /home/user/go/src/github.com/hillu/go-yara/rules.go:121 +0x1ce fp=0xc0000bddf8 sp=0xc0000bdcf0 pc=0x4a89de
github.com/hillu/go-yara.(*Rules).ScanFile(...)
    /home/user/go/src/github.com/hillu/go-yara/rules.go:100
main.main()
    /home/user/go-yara/_examples/simple-yara/simple-yara.go:117 +0x729 fp=0xc0000bdf60 sp=0xc0000bddf8 pc=0x4b3889
runtime.main()
    /home/user/usr/local/go/src/runtime/proc.go:203 +0x21e fp=0xc0000bdfe0 sp=0xc0000bdf60 pc=0x42f0be
runtime.goexit()
    /home/user/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc0000bdfe8 sp=0xc0000bdfe0 pc=0x4577d1

As best I can tell this is crashing when trying to get the matches from some C binding related to getting string matches.

Any ideas on how to fix this?

Thanks

idrii commented 4 years ago

So after some more playing around it looks like the issue is somehow related to the length of the rules being used. If I reduce the previous rule down to:

rule MimikatzMem {
    strings: 
        $s1 = "sekurlsa::msv" fullword ascii
        $s2 = "sekurlsa::wdigest" fullword ascii
    condition: 
    1 of them
}

I get the expected match: Match: [{Rule:MimikatzMem Namespace:Namespace1 Tags:[] Meta:map[] Strings:[{Name:$s1 Offset:48 Data:[115 101 107 117 114 108 115 97 58 58 109 115 118]}]}]

however if I add another line string such as $s4 = "sekurlsa::kerberos" fullword ascii I get the same error as mentioned above.

Interestingly it appears to be related to the number of entries in the strings section of the rule, not the length of the rule (i.e. if I make on of the strings in the above rule really long it still works but if I add a new string it fails)

hillu commented 4 years ago

Can you share the sample? Please also tell me what operating system and what versions of Go and libyara you are using.

idrii commented 4 years ago

Sure, the sample I was scanning was just the rules that I was loading in so

{
    strings:
        $s1 = "sekurlsa::msv" fullword ascii
        $s2 = "sekurlsa::wdigest" fullword ascii
        $s4 = "sekurlsa::kerberos" fullword ascii
        $s5 = "sekurlsa::tspkg" fullword ascii
        $s6 = "sekurlsa::livessp" fullword ascii
        $s7 = "sekurlsa::ssp" fullword ascii
        $s8 = "sekurlsa::logonPasswords" fullword ascii
        $s9 = "sekurlsa::process" fullword ascii
        $s10 = "sekurlsa::minidump" fullword ascii
        $s11 = "sekurlsa::pth" fullword ascii
        $s12 = "sekurlsa::tickets" fullword ascii
        $s13 = "sekurlsa::ekeys" fullword ascii
        $s14 = "sekurlsa::dpapi" fullword ascii
        $s15 = "sekurlsa::credman" fullword ascii
    condition:
        1 of them
}

My OS is Ubuntu 18.0.4 and my GoLang version is go version go1.13.4 linux/amd64 I was using a copy of libyara 3.11.0

hillu commented 4 years ago

@idrii Do you also have libyara3 and libyara-dev from Ubuntu installed on your Ubuntu-18.04-based dev environment? If so, does the problem disappear if you uninstall those and rebuild the Go program?

I suspect that this might be essentially a duplicate of #55–and that the root cause is in ABI incompatibilities somewhere between YARA 3.7 and YARA 3.11.

idrii commented 4 years ago

@hillu Wow, that was it! I wasted so much time on this and for it to be such a simple issue is actually kind of annoying.

Thank you very much for your help and your awesome library