Reversing-golang Reversing Go - Part 5
Post
Cancel

Reversing Go - Part 5

Miscellaneous Topics

Looping over string

1
2
3
for i, j := range s {
    // ...
}

is compiled to

1
2
3
4
5
6
7
8
9
10
11
i := 0
var j rune
for i < len(s) {
    j = s[i]
    if j > 0x80 {
        j, i = runtime.decoderune(s, i)
    } else {
        i++
    }
    // ...
}

Counting Runes

1
l := len([]rune(s))

is compiled to

1
l := runtime.countrunes(s)

Type Switch

A type switch is a switch statement over types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func main() {
    whatAmI := func(i interface{}) {
        switch t := i.(type) {
        case bool:
            fmt.Println("I'm a bool")
        case int:
            fmt.Println("I'm an int")
        case <-chan time.Time:
            fmt.Printf("I'm a ticker - %v\n", t)
        case string:
            fmt.Printf("I am a string - %q, %d\n", t, len(t))
        default:
            fmt.Printf("Don't know type %T %[1]v\n", t)
        }
    }
    var tt interface{}
    tt = time.NewTicker(1 * time.Nanosecond)
    whatAmI(1337)
    whatAmI(true)
    whatAmI("I love go!")
    whatAmI(tt)
    tk := tt.(*time.Ticker)
    whatAmI(tk)
    whatAmI(tk.C)
}
1
2
3
4
5
6
7
8
.text:004B1CC2    mov     rax, [rsp+20h+var_10] ; *Ticker
.text:004B1CC7    mov     rax, [rax]            ; *Ticker.C
.text:004B1CCA    lea     rcx, _chan_left_chan_time_Time
.text:004B1CD1    mov     [rsp+20h+var_20], rcx
.text:004B1CD5    mov     [rsp+20h+var_18], rax
.text:004B1CDA    mov     rax, cs:off_4E1AA8
.text:004B1CE1    lea     rdx, off_4E1AA8
.text:004B1CE8    call    rax ; main_main_func1

The closures named as [package]_func[N] where N = 1, 2, 3, …

main.func1 takes an interface (i)

1
2
3
4
5
6
7
.text:004B1D36    mov     rax, [rsp+0C8h+arg_0]
.text:004B1D3E    xchg    ax, ax
.text:004B1D40    test    rax, rax
.text:004B1D43    jz      default_case
.text:004B1D49    mov     ecx, [rax+10h]    ; arg_0.hash
.text:004B1D4C    cmp     ecx, 816551E3h
.text:004B1D52    ja      loc_4B1EE0

So, a type switch is implemented by comparing hash and the type instance of every type present in the case statements with the type of the argument

1
2
3
4
5
6
.text:004B1EE0    cmp     ecx, 0E0FF5CB4h
.text:004B1EE6    jnz     loc_4B1FE0
.text:004B1EEC    lea     rcx, string_autogen_MJPKZQ
.text:004B1EF3    cmp     rcx, rax
.text:004B1EF6    jnz     default_case
.text:004B1EFC    mov     rax, [rsp+0C8h+arg_8]

So, first if the type hash matches with the hash of the type to be checked, it checks whether the type instances are same. In this case if the hash of the type is 0xe0ff5cb4 (hash of string), it checks if the type is really a string. .text:004B1EFC is executed iff the type to be checked is a string

Armed with all the concepts, we can start constructing Go source from Go binaries! Good Luck!

This post is licensed under CC BY 4.0 by the author.