-
Notifications
You must be signed in to change notification settings - Fork 494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ELF: Detect OS from Go binaries #1987
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, my only comment would be on tests around this
if not part of this PR let's create an issue to track adding samples/tests
# content: {ff 20 47 6f 20 62 75 69 6c 64 69 6e 66 3a 04 02} | ||
# content: {ff 20 47 6f 20 62 75 69 6c 64 69 6e 66 3a 08 02} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment what these are?
thank you for the feedback - i was being lazy. i'll add some test files and some test cases. |
@@ -957,6 +960,397 @@ def guess_os_from_symtab(elf: ELF) -> Optional[OS]: | |||
return None | |||
|
|||
|
|||
def is_go_binary(elf: ELF) -> bool: | |||
for shdr in elf.section_headers: | |||
if shdr.get_name(elf) == ".note.go.buildid": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how reliable expecting the note to be present will be. Floss does this:
I would recommend testing on old go versions prior to 1.18 when buildinfo was added. I would also recommend testing with binaries emitted by |
# the current buildinfo data region. | ||
# | ||
# Brute force the k-v pair, like `GOOS=linux`, | ||
# rather than try to parse the data, which would be fragile. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is totally fine and should always work, but the buildinfo is just a string with some separator control words so could be easy to parse too.
Writing of buildinfo: https://github.com/golang/go/blob/1de46564a766f9647b22ebab0f35bccd14291460/src/runtime/debug/mod.go#L104
Reading of buildinfo, split by control words: https://github.com/mandiant/GoReSym/blob/0860a1b1b4f3495e9fb7e71eb4386bf3e0a7c500/runtime/debug/mod.go#L110-L118
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@@ -957,6 +960,485 @@ def guess_os_from_symtab(elf: ELF) -> Optional[OS]: | |||
return None | |||
|
|||
|
|||
def is_go_binary(elf: ELF) -> bool: | |||
for shdr in elf.section_headers: | |||
if shdr.get_name(elf) == ".note.go.buildid": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The go version
command uses logic similar to the one in the get_go_buildinfo_date() function (in addition to looking for the BUILDINFO_MAGIC) to check if an executable is go or not. See references to the errNotGoExe error here: https://github.com/golang/go/blob/master/src/debug/buildinfo/buildinfo.go#L41
Maybe consider incorporating that here? perhaps:
if shdr.get_name(elf) == ".note.go.buildid": | |
if shdr.get_name(elf) in (".note.go.buildid", ".go.buildinfo"): |
Or maybe consider retrieving the buildinfo and testing whether the BUILDINFO_MAGIC is therein? perhaps after we check the section names?
Also, I think this might be a good place to make use of Google's Magika. Maybe if our heuristics can't determine the OS then output the error: "Input file does not appear to target a supported OS according to our heuristics. If you want to use Magika to guess the OS then run capa with the --use-magika parameter"?
Tests are TODO / in progress? Getting the following when trying to resolve conflicts:
Before continuing, I wanted to confirm what the status here was/is. |
Yeah, I owe tests here. I believe the implementation is solid but without tests I can't prove it. At a comfortable effort level, I could have this done in maybe two weeks. If there's a pending deadline, let me know and I can squeeze it in sooner. |
This is not urgent at all! I just thought I may be able to lend a hand. |
use the strategies pioneered by GoReSym to detect the target OS for ELF binaries compiled by Go:
closes #1978
FYI @C0d3R3ad3r
FYI @stevemk14ebr
Checklist