Skip to content

Latest commit

 

History

History
136 lines (94 loc) · 4.79 KB

Anatomy of a Gopher - Binary Analysis of Go Binaries, Alex Useche.pdf.md

File metadata and controls

136 lines (94 loc) · 4.79 KB

ANATOMY OF A GOPHER || BINARY ANALYSIS OF GO BINARIES HEX0PUNK / ALEX USECHE

WHO IS THIS GUY? hex0punk Father & husband Senior AppSec Consultant at nVisium Fan of Go and Rust Likes playing with binaries

WHAT ARE WE DOING?

Learning about what makes go binaries different than C and C++ binaries Identifying techniques for recognizing and conducting analysis of go binaries. Tips for finding vulnerabilities in go binaries. Identifying common patterns found in go binaries Learning about protections that can be added to go binaries

ONCE UPON A TIME Found go binaries during an IoT assessment Wait, this isn't C or C++! This is Go! Now what?

THE GO ASSEMBLER

The go compiler is based on the plan9 compiler Semi-abstract instruction set Pseudo-Assembly Not a direct representation of the underlying machine (i.e. a MOV may be a LD) It also introduces a set of pseudo registers

GO TOOL OBJDUMP go tool objdump -s RADARE2

go tool objdump vs. radare2

· Use both! · Differences are easy to understand: · A big advantage of using go tool objdump is that you get line numbers in code. This can be help you group instructions by operations

true for MachO Got ROP?

THE GO ASSEMBLER DEFAULT PROTECTIONS Stack Protection: export CGO_LDFLAGS='fstack-protector' Stripped: GOOS=linux go build -ldflags="s -w" PIE: export GOFLAGS='-buildmode=pie' Use a tool like UPX (https://upx.github.io/) to strip function names and reduce size

SEARCHING FOR

rabin2 -zz go-bin-goo | grep 1.__TEXT.__rodata | grep intruder

STRINGS

SEARCHING FOR STRINGS · Go does not store null terminated strings. · Strings are clumped together, while keeping a separate table with length information. · This can make it difficult to look for string cross-references · We can use a projects like https://github.com/carvesystems/gostringsr2 to parse strings · When working with MachO binaries, you'd have to list strings from .rodata or entire binary · rabin2 -zz · izz using r2

SEARCHING FOR FUNCTIONS

· Most of the times, functions are easy to find, even in stripped binaries. · Functions follow with the following naming conventions: package.function package.receiver struct.function Package.receiver struct.function

THE EASY PART FINDING MAIN

· Go routines have small stacks by default (2 kibibyte = 1024 bytes stack) · Many goroutines will calls morestack to grow the stack (in powers of 2) as needed using stack copying · This is called because go can't be sure the function will outgrow the stack (i.e. recursive functions) given non-deterministic goroutines · When this occurs, stack grows, pointers in the stack are updated. · Additionally, each function compares its stack pointer against g->stackguard to check for overflow.

GO STACKS GO FUNCTION PROLOGUE

GO FUNCTION PROLOGUE OR FINDING OPPORTUNITIES TO OVERFLOW THE STACK · Developers call tell go to skip this check to test performance issues with pragma //go:nosplit · Some library functions may call //go:nosplit · Look for opportunities to corrupt the stack · Callers pass arguments in the stack

CONVENTIONS

Placing return values in the stack

ARGUMENTS AND RETURN VALUES

Return values are placed in the stack A opposed to C where return values are placed in registers Arguments are also moved to the stack rather than registers.

Passing arguments in the stack

IT'S ALL ABOUT THE GO LIBRARY FUNCTIONS

USE GO LIBRARIES AS A GUIDE TO UNDERSTAND THE BINARY Understanding go internal libraries can significantly help us understand what is going on the assembly code Read the go docs!

CALLING A GOROUTINE

DEREFENCING RECEIVER

SO WHAT? · We have identified a race condition · Note //go:nosplit for typedmemmove

DEFER Function responsible for concurrency are easy to locate In the case of a defer call: Functions are registered with deferprocStack Check whether a panic has been caught Prepare return values and call deferred functions before exiting function Assure to defer if a panic is caught

GO INTERFACES Interfaces consist of: A pointer to a vtable (which contains function pointers that point to the virtual functions) A value pointer

GO ERROR HANDLING error is an an interface Error handling in clumsy in go Bugs due to unhandled errors are common When checking for error != nil we load the error vtable and error value. Then we test if the value is nil And branch depending on the result

SO WHAT? WELL...

WHAT ELSE SHOULD I LOOK FOR? cgo functions! Hacking like its 1995(98)(2000)

EL FIN

· Go is everywhere · We are likely to see see more go in IoT with projects like TinyGo · Fancy, yet exploitable under the right conditions · Look for programmer errors (i.e. error handling) · Understand stack handling · Look for cgo usage · Leverage go tools · RTFM

· For developers: · Test your code with gosec, govet · Fuzz it with go-fuzz

QUESTIONS?