|
| 1 | +# LLEF Experimental Go Features Readme |
| 2 | + |
| 3 | +LLEF now has experimental support for stripped Go binaries. This document contains examples of LLEF's Go features, including screenshots of what LLEF's analysis output displays compared with previous versions of LLEF. These features are tested across a range of Go versions since 1.7, which was released in 2016. |
| 4 | + |
| 5 | +## Resolving and displaying Go types |
| 6 | + |
| 7 | +Go binaries store metadata on complex data types which are used in the program, even when the binary has been stripped. From this metadata, field names and types can be recovered for `struct`, `map`, `array` and `slice` types. As an example, consider the following `struct` definition in a Go source file: |
| 8 | + |
| 9 | +```go |
| 10 | +type Tool struct { |
| 11 | + Name string `json:"name"` |
| 12 | + Developer string `json:"developer"` |
| 13 | + Score int `json:"score"` |
| 14 | +} |
| 15 | +func demo() { |
| 16 | + tools := []Tool{ |
| 17 | + {Name: "LLEF", Developer: "Foundry Zero", Score: 10}, |
| 18 | + {Name: "Binder Trace", Developer: "Foundry Zero", Score: 10}, |
| 19 | + } |
| 20 | + jsonData, _ := json.Marshal(tools) |
| 21 | + fmt.Println(string(jsonData)) |
| 22 | +} |
| 23 | +``` |
| 24 | + |
| 25 | +In the above program listing, `tools` is an `array` type of `Tool` objects, which is passed into `json.Marshal`. The definition of `json.Marshal` includes an `any` type for the input argument. To keep track of the input data type, the Go compiler loads a pointer to read-only metadata for the `[]Tool` data type at runtime, followed by a pointer to the raw object data in memory. |
| 26 | + |
| 27 | +In previous versions of LLEF, when a breakpoint is set on the call to `json.Marshal`, the register view shows the following: |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | +With Go features enabled, LLEF can now identify the pointer `0x4c3300` points to a data type definition for `[]Tool`, and used that definition to display the contents of the data pointer in `ebx`: |
| 32 | + |
| 33 | + |
| 34 | + |
| 35 | +A new command `go get-type` has been added to find Go data type definitions present within the binary. When an argument is given to the command, LLEF will to match the name of the type to the definition present in the Go binary. If no match can be found, LLEF will display similar entries: |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +When no arguments are given, all data types are displayed. |
| 40 | + |
| 41 | +If a data type pointer is not passed into a called function alongside the raw data type pointer, LLEF will not be able to determine the matching data type. In this case, an analyst can manually use the command `go unpack-type` to attempt to display a data pointer using a given data type definition. |
| 42 | + |
| 43 | + |
| 44 | + |
| 45 | +## Resolving Go Function Names |
| 46 | + |
| 47 | +Go binaries store function symbols which are used during exception handling, even for stripped binaries. LLEF can now recover these function symbols and display them: |
| 48 | + |
| 49 | + |
| 50 | + |
| 51 | +A new command `go find-func` has been added to search through function symbols, which is especially useful for finding where to set breakpoints. When no argument is given, all function symbols are displayed. |
| 52 | + |
| 53 | + |
| 54 | + |
| 55 | +## Go call stack unwinding |
| 56 | + |
| 57 | +LLEF can now display the Go call stack on x86 and x86_64 architectures. This is displayed in the listing view, but can also be displayed with the command `go backtrace`. |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | +## Before and After |
| 62 | + |
| 63 | +### Before |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | +### After |
| 68 | + |
| 69 | + |
0 commit comments