Symbol recovery on rust executables

Why ?

  • Rust is hard to reverse engineer
  • Compilation leaves a lot of artifacts by default

Symbol recovery usual workfow

Find target dependencies
(e.g Tokio v1.2)

Symbol recovery usual workfow

Find target dependencies
(e.g Tokio v1.2)

push    rbp
push    rbx
sub     rsp, 58h
lea     rdi, off_2E60F8
call    std::thread::local::Loca...
mov     rcx, 736F6D6570736575h
xor     rcx, rax
mov     rsi, 646F72616E646F6Dh
xor     rsi, rdx
mov     rdi, 6C7967656E657261h
xor     rdi, rax
mov     r8, 7465646279746573h
xor     r8, rdx

Symbol recovery usual workfow

Find which compiler was used by your target

Find target's dependencies
(e.g Tokio v1.2)

Symbol recovery usual workfow

Find which compiler was used by your target

Compile the dependency yourself

Find target's dependencies
(e.g Tokio v1.2)

Symbol recovery usual workfow

Find which compiler was used by your target

Find target's dependencies
(e.g Tokio v1.2)

Compile the dependency yourself

Compile the dependency yourself

push    rbp
push    rbx
sub     rsp, 58h
lea     rdi, off_2E60F8
call    std::thread::local::Loca...
mov     rcx, 736F6D6570736575h
xor     rcx, rax
mov     rsi, 646F72616E646F6Dh
xor     rsi, rdx
mov     rdi, 6C7967656E657261h
xor     rdi, rax
mov     r8, 7465646279746573h
xor     r8, rdx

Symbol recovery usual workfow

Find which compiler was used by your target

Compile the dependency yourself

Find target's dependencies
(e.g Tokio v1.2)

1:1 CODE MATCH !

push    rbp
push    rbx
sub     rsp, 58h
lea     rdi, off_2E60F8
call    std::thread::local::Loca...
mov     rcx, 736F6D6570736575h
xor     rcx, rax
mov     rsi, 646F72616E646F6Dh
xor     rsi, rdx
mov     rdi, 6C7967656E657261h
xor     rdi, rax
mov     r8, 7465646279746573h
xor     r8, rdx

Compile the dependency yourself

push    rbp
push    rbx
sub     rsp, 58h
lea     rdi, off_2E60F8
call    std::thread::local::Loca...
mov     rcx, 736F6D6570736575h
xor     rcx, rax
mov     rsi, 646F72616E646F6Dh
xor     rsi, rdx
mov     rdi, 6C7967656E657261h
xor     rdi, rax
mov     r8, 7465646279746573h
xor     r8, rdx

Symbol recovery usual workfow

Find which compiler was used by your target

Compile the dependency yourself

Find target's dependencies
(e.g Tokio v1.2)

Sign it (IDA's sigmake,

binja's sigkit...)

tokiov1.2.sig

Symbol recovery usual workfow

Find which compiler was used by your target

Compile the dependency yourself

Find target's dependencies
(e.g Tokio v1.2)

Sign it (IDA's sigmake,

binja's sigkit...)

tokiov1.2.sig

Symbol recovery usual workfow

Find which compiler was used by your target

Compile the dependency yourself

Find target's dependencies
(e.g Tokio v1.2)

Sign it (IDA's sigmake,

binja's sigkit...)

tokiov1.2.sig

Rust compilation artifacts

user@computer:~$ strings target.exe
[...]
addr2line-0.17.0/src/function.rs [...]
aes-0.7.5/src/soft/fixslice64.rs [...]
bytes-1.4.0/src/buf/buf_impl.rs [...]
[...]

Dependencies & versions

user@computer:~$ strings target.exe
[...]
/rustc/90c541806f23a127002de5b4038be731ba1458ca/core/[...]
/rustc/90c541806f23a127002de5b4038be731ba1458ca/core[...]
...

Rust compiler commit hash

Issues

  • rustc does not guarantee order of fields in structs

Issues

  • rustc does not guarantee order of fields in structs
  • Rust has generics ("Monomorphization")
struct Box<T>

Issues

  • Attacker can compile with LTO (Link Time Optimization)
push    rbp
push    rbx
sub     rsp, 58h
lea     rdi, off_2E60F8
call    sub_4B224
mov     rcx, 736F6D6570736575h
push    rbp
push    rbx
sub     rsp, 58h

; <some bad boy disappeared here !>

call    sub_4B224
mov     rcx, 736F6D6570736575h

Same library, same version, compiled with LTO on different targets

Workaround

  • Rust libraries usually well maintained / developed
    • ​tests, benches, examples available to build
      • good code coverage
      • many different usage of the API

Workaround

  • Rust libraries usually well maintained / developed
    • ​tests, benches, examples available to build
      • good code coverage
      • many different usage of the API

Results in a lot of executables to sign !
(1000+ sometimes)

3mn is such a short time frame !

Way more details on my blogpost + tool trying to automate the process

 

https://nofix.re/

deck

By Nofix

deck

  • 62