13

Is there an easy way to extract all of the strings from Go binaries that will work cross architecture?

The problem with Go is that strings are stored without a null terminator, so you can't use the "strings" command plainly.

I found two solutions so far -

  • gostringsr2 - Extracts strings using references to the string section (by using radare2). But this method doesn't work 100% and screws up some strings because there are indirect references, etc...,

  • golang_loader_assist - Extracts strings by searching for lea/mov instruction to the string section. But this method only works for x86 architectures.

Is there a more generic and correct way to extract the strings from Go compiled binaries?

6
  • What is Go's native text encoding? For 7-bit ASCII look for runs of bytes >= space and < DEL. For 8-bit extensions to ASCII look for runs of bytes >= space. For UTF-8 there are specific bit patterns to look for in the various bytes of each multibyte character. For UTF-16 you need heuristics. ASCII-compatible runs have interleaves 0 bytes and bytes >= space. Unpaired surrogates are a flag that it's unlikely to be UTF-16 after all. In all cases the fidelity is lower than finding null-terminated strings. Commented May 26, 2020 at 3:13
  • @hippietrail I think that the native encoding is ASCII, but the problem is that GO saves it strings without null terminator.. So you can find only one huge blob of strings and I want to extract those strings "as is" one by one
    – Drxxd
    Commented May 26, 2020 at 7:29
  • According to this, GO uses UTF-8 for strings. If you don't want to have to split up the blobs yourself and strings are not terminated then it seems there is no "easy way" until somebody knowing all the architectures writes a unified tool using principles like the tools you mention use. In the meantime you might be able to analyse your binary with Ghidra. Ada Pro can surely do something too. But those are more heavyweight than you seem to be looking for and won't always find every string. Commented May 26, 2020 at 8:28
  • 1
    You referenced the project golang_loader_assist and it only supporting x86. If you'd like to submit a PR for updating is_string_load() for non-x86 patterns used by golang I'll gladly accept and apply them. AFAIK, there is no "easy" way to do this, which is why I resorted to this method. The calls for strings are preempted by the length, which is important since there is no null byte afterwards.
    – diff
    Commented Jun 24, 2020 at 19:03
  • You have to make a reference with other versions of golang since the opcodes might be different in every version. golang_loader_assist uses those opcodes as a pattern to search for strings. Commented Sep 25, 2021 at 23:43

1 Answer 1

1

I just read a good article on the challenges with Go binaries: https://cujo.com/reverse-engineering-go-binaries-with-ghidra/

I think this could be classed as a "cross-architecture solution" seeing as Ghidra runs under a JVM.

The Ghidra plugins they developed seem to work well. I ran the static and dynamic scripts against the Go binary they used in their Hacktivity2020 conference preso with good results:

enter image description here

I guess malware may be less amenable to analysis, but this is probably a good start.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.