FFRI Security, Inc.

How Do We Fight Against Evolving Go Language
Malware? Practical Techniques to Improve
Analytical Skills
JSAC 2023
FFRI Security, Inc.
Tsubasa Kuwabara

FFRI Security, Inc.

Tsubasa Kuwabara• FFRI Security, Inc.
– Malware Analysis– Other security services• Ghidra and x64dbg plugin development– Developed plug-ins for analyzing Go language binaries, etc.
• SecHack365, Security Camp 2019 Alumni• Security Camp 2021 Lecturer

2

FFRI Security, Inc.

Table of Contents
How Do We Fight Against Evolving Go Language Malware? Practical Techniques to
Improve Analytical Skills• Current Status and Issues• Basic Analysis– For those with limited experience in Go language malware analysis• Advanced Analysis– For those with experience in Go language malware analysis

3

FFRI Security, Inc.

GO LANGUAGE MALWARE
CURRENT STATUS AND ISSUES
4FFRI Security, Inc.

Advantages of the Go Language in Malware Development• Go Language– Easy to describe– Extensive library– Cross-compile• Advantages for Malware Developers– Easy to develop• OSS libraries are often used in malware– Easy to attack multiple platforms

5

FFRI Security, Inc.

Future of Go Language Malware• Multi-platform attacks– ElectroRAT *1• RATs steal digital wallet keys, etc.
• Activities for Windows/Linux/macOS– Chaos *2• Versatile malware that exploits vulnerabilities, etc.
• Exists for ARM/Intel/MIPS/PowerPC• About the future– Many more are appearing in 2022.
• Chaos, Nerbian, Agenda, etc.
– Go language malware will be observed in the future*1 https://www.intezer.com/blog/research/operation-electrorat-attacker-creates-fake-companies-to-drain-your-crypto-wallets/*2 https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/

6

FFRI Security, Inc.

Problems with Go Malware Analysis••

Existing malware is often C/C++ binaries
Go language binaries and C/C++ binaries are very different– The amount of functions is enormous• Even Hello World has more than 1000 functions.
• Windows APIs and other APIs are called dynamically.
– Difficult to understand functionality of functions– Unique data structure• Strings are represented as structs instead of nullterminated• Unique types such as interface{} are used
– Unique calling convention• Different registers, etc. used for arguments andreturn values

Hello World Functions
It's actually about 1400, but it's not
resolved.

ElectroRAT would be over
8,000.

Hello World string
Hello World function call

7

FFRI Security, Inc.

Response and problems with the tool
• Existing tool features– Resolving Function Names• Quite difficult to analyze without knowing this.
– String extraction, etc.
• Issue– Difficult to use existing tools for a long time
• Go language can change its structure with version upgrades– Newer versions may not be able to retrieve function names, etc.
– Malware with obfuscation, such as malware ChaChi, exists.
• Obfuscators for the Go language are used
• Difficult to solve by simply using existing tools as is– Requires modifications as appropriate

8

FFRI Security, Inc.

Contents• Basic Go Language Malware Analysis– Go Language Specific Structures– Analysis Flow
– Case Studies with Malware• Advanced Go Language Malware Analysis– Data in Go language binaries referenced by existing tools– Supports for Go language version upgrades by modifying existing tool
– Obfuscation measures

9FFRI Security, Inc.

GO LANGUAGE MALWARE
BASIC ANALYSIS
10

FFRI Security, Inc.

Go-Specific Structures• Introduction to Go language specific structures before introducing analysis methods• Data Structure Related– string– interface{}– slice– map• Function– calling conventions

11

FFRI Security, Inc.

string & interface{}• string– Structure• ̲̲data: pointer to string– Not null terminated.
• ̲̲len: String length– Its size is equivalent to sizeof(̲̲data)

struct string {char* ̲̲data;
int32 or int64 ̲̲len;}• interface{}: Multiple data types allowed– Structure• tab: Pointer to data type information• data: Pointer to data

12

FFRI Security, Inc.

slice
•
•

slice: dynamically resizable array
Structure– array: Pointer to array– len: Length of array• Its size is equivalent to sizeof(array)– cap: Length of memory-allocated array• Its size is equivalent to sizeof(array)•

Function manipulating slice– func growslice(et *̲type, old slice, cap int) slice *1• Copies the slice specified in the second argument to a slice that holds more memory than the size
specified in the third argument.
• Adding a value to the slice is done on the return value of this growslice.
• Argument structure is different starting from Go 1.20•

Variable-length arguments are represented by the same structure as slice– func Command(name string, arg .... .string) *Cmd *2• Command("cmd", "/C", "bin") == Command("cmd ", [2]string{"/C", "bin"})struct slice {void* array;
int32 or int64 len;
int32 or int64 cap;}

*1 https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/slice.go#L178*2 https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/os/exec/exec.go#L271

13

FFRI Security, Inc.

map
• map: associative array• Function manipulating map (if key is a string)– func mapaccess2̲faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) *1• Specify the type of map as the first argument, the map to access as the second
argument, and the key as the third argument• Return the value corresponding to the key and success or failure– func mapassign̲faststr(t *maptype, h *hmap, s string) unsafe.Pointer *2• Specify the type of map as the first argument, the target map as the second
argument, and the key as the third argument• Assign a value to the return value*1 https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/map̲faststr.go#L108*2 https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/map̲faststr.go#L203

14

FFRI Security, Inc.

Calling Conventions• Difference from existing in Windows amd64– If i386, the stack is used.
Microsoft x64
calling
convention

Go Language(>=Go 1.17)

Go Language(<Go 1.17)

argument

rcx,rdx,r8,r9,sta
ck

rax,rbx,rcx,rdi,rsi,r8 stack,r9,r10,r11,stack

return valuerax

same as above

same as above• Argument and return value assignment– Go 1.17 or higher & amd64: arguments and return values are used in order from rax– Go 1.16 and below ¦ i386: Return values are used from the end of the stack used by
the argument• Definition in Go language source code
– Defined in "paramIntReg<architecture name>" below.
• https://raw.githubusercontent.com/golang/go/go1.19.1/src/cmd/compile/internal/ssa/opGen.go

15

FFRI Security, Inc.

Tool
• https://github.com/mooncat-greenpy/Ghidra̲GolangAnalyzerExtension– Resolves function names– Resolves bytes and registers used in arguments and return values– Extracts data type names and field information– Extracts strings– Annotates names of the source code file corresponding to the assembly– Annotates source code line number corresponding to the assembly
Without the toolWith the tool

• Subsequent Ghidra screenshots show results using GhidraAnalyzerExtension
16

FFRI Security, Inc.

Analysis Flow
• Check main (main.main) function– Take a brief look at assembly and decompile results• Functions to be called– Check the init function used for initialization if it exists.
• Check function name, file name, and structure sequence– Obvious doubtful names– OSS libraries used
• Estimate functions from the above information and confirm its estimation– Is the function as used or not or as estimated?
• Analyze in detail
Supplement

If you don't know the main function, trace it fromthe entry point.
Please refer to the following blog for the details
https://engineers.ffri.jp/entry/2022/04/11/141131
The init function is explained in the Appendix

17

FFRI Security, Inc.

Case Study: ElectroRAT• It was active on Windows, Linux, and macOS• Analysis Flow
– Install and run GolangAnalyzerExtension on Ghidra– Check main.main– Estimate its functions from lists of function and file names• Checking structures is not covered in this talk
– Verify the above estimation– Analyze in detail18

FFRI Security, Inc.

ElectroRAT: Check main.main•••

Excerpts of Notable Function Call
– net/http.(*Client).Get– io/ioutil.readAll– main.registerUser– main.setAutostart– main.StartKeyLogger– main.socketConnect
Guessing functions– Automatic executionfunctionality is available andmain functions are based oncommunication with C2
main.init is not covered in this talk– map is created, etc.

Decompiled main.main (tools applied without manual modification)omissionomissionomittedStandard
library

Implemented
by developer

19

FFRI Security, Inc.

ElectroRAT: Check function name and file name••

Anticipated malware features– Information theft• github.com/gorilla/websocket• main.uploadFile• main.uploadFolder– Automatic startup setting• github.com/ProtonMail/go-autostart• main.HideFile• main.copyAppToStartDir– Terminal information acquisition– Software used to note content typed (typically tosteal passwords)– Obtain screenshots
Simplified check of the caller of the estimated function
and whether the estimation is correct.
– Only the bolded above is confirmed this time

File name list (Window → GolangAnalyzerExtension)

Function name list

20

FFRI Security, Inc.

ElectroRAT: Information Theft Caller

Call Trees in main.socketConnect• gorilla/websocket.(*Dialer).Dial– (*Dialer).Dial is called first– Caller: main.socketConnect• Called from main.main• main.upload(File¦Folder)– Caller: both main.socketConnect.func1• main.socketConnect.func1– Cannot figure out from Call Trees• Because Goroutine is used to perform parallel
processing– The function to be executed is passed via
arguments– Caller: main.socketConnect• Search from address references, etc.

Call Trees in main.uploadFile

main.socketConnect function

Function to execute
Goroutine

Called internally

21

FFRI Security, Inc.

ElectroRAT: Information Theft Process• The following will be added to the map– Key: "file".
– Value: Argument of main.uploadFile• File path to upload• Information theft by sending files– SetFiles to specify a map containing
file paths• Transmission file settings– Send externally with Execute• POST command

Decompile result of main.uploadFile
map type

Function to create an
object of a specified
type

Resty.Request

Object of map

key

The third and fourth arguments
are substituted
likely file path

Type of object tocommunicate with

Object of map

POST" string

22

FFRI Security, Inc.

ElectroRAT: Auto Startup Settings• Auto start setting to files created by main.copyAppToStartDir– Using OSS• https://github.com/ProtonMail/go-autostart
Decompile result of main.setAutostart• go-autostart

Confirmationof success or
failure of
IsEnabled• Using cgo

Source code for go-autostart• Go language to C language• A shortcut file is created in thestartup folder using COM

23

FFRI Security, Inc.

Examples of OSS libraries used by ElectroRAT• github.com/ProtonMail/go-autostart– Automatic startup setting• github.com/gorilla/websocket– Socket communications• github.com/matishsiao/goInfo– Obtain terminal information• github.com/mitchellh/go-ps– Get process list
• etc.
• All support Windows, Linux, and macOS.
• Read the source code for the OSS library process

24

FFRI Security, Inc.

Frequently used OSS libraries• Libraries for multiple platforms– github.com/denisbrodbeck/machineid• Obtain ID to identify the terminal– github.com/shirou/gopsutil• Obtain process and system-related information– github.com/gorilla/websocket• Socket communications– github.com/kardianos/service• Provide service operation• Libraries for specific platforms, requiring a lot of work to implement in the Go language– github.com/go-ole/go-ole• Windows COM wrapper– github.com/lxn/win• Windows API Wrapper

25

FFRI Security, Inc.

Details• Now we have a rough idea of the malware's functionality• Based on these findings, a more detailed analysis is performed– Only the following topic is covered• Communication with C2– main.socketConnect is supposed to handle the main malware• Because socket communication is performed by main.socketConnect after
preliminaries such as infection notification to C2 by main.registerUser andautomatic startup setting by main.setAutostart26

FFRI Security, Inc.

Analysis of main.socketConnect• Main processing– Establish communication• Creates Conn objects required for communication– Call main.socketConnect.func1• Passes a Conn object as the second argument
Conn object is createdConn object.
Set as 2nd argumentomissionArguments of functions executed by Goroutine aredescribed in the Appendix

IP address string(Arguments of main.socketConnect)
Function to execute
Goroutine

27

FFRI Security, Inc.

main.socketConnect.func1• Process Flow
– Receive command from C2– Parse command– Execute command– Send results to C2

28

FFRI Security, Inc.

Receive instructions & parse command
main.socketConnect.func1 function• Received data is converted tomain.Command– Type field is treated as a command

Use the Argument Conn.
Get incoming data

omission

Decoder Object
Retain incoming data

Type of&main.CommandObject of&main.Command

Command structure (Data Type Manager)omissionTypestringCommanddecisionRun command

29

FFRI Security, Inc.

Execution of instructions & transmission of results• Extracts a Command string from themain.socketConnect.func1 function
main.Command structure and executes it.
RAX=&main.Command
Offset: 0x58
• Convert results to JSON format and send toexternal devices
Get Command field
main.Command structure

Execute the Command
and return the result
omission

Return value
execution result

JSON
formatData field structure

Offset from the beginning of
main.Command: 0x58

30

FFRI Security, Inc.

Streamline analysis by comparing samples• Introduce the comparison of the samples to be analyzed with existing samples andsamples observed within the same incident• Identical process exists– Analysis can be shortened• Similar but different processes exist– Understanding Attack Trends– Investigation of the cause of infection of new samples when existing samples areprotected• Go language binaries allow you to get the file name and line number of the source
code, so you can follow the differences in detail.

31

FFRI Security, Inc.

Comparison of old and new samples• Compare the following samples– Left: e9b83d5cdefd4486b32a927d7505cdeebb43e6977759ba069d9373e46ca7d0f2 (new)– Right: 170cb5ea1a6b4af3c27358ba267a1309ed5118481619fc874f717262cb91fb77 (old)Files are facilitated for each target
environment of samples.

⊝

⊕

⊝
⊝
Some files have been added or deleted.
See the differences in commands on thenext page.

32

FFRI Security, Inc.

Command changes between samples• Analyze mainly the sections changed.
Compare the number of lines in the socket.go file in which the command is implemented(computer) command

Number of rows ine9b83d... (new)Number of rows in
170cb5... (old)Get folder content

130˜ 133

100˜ 103

Keylogger

135˜ 149

105˜ 118

Screenshot

151˜ 164

119˜ 128

Camera photo

129˜ 134

Processes list

166˜ 169135˜ 137

Download file

171˜ 179

138˜ 145

Download folder

181˜ 189

147˜ 153

Add file

191˜ 205

Delete file

207˜ 215

154˜ 161

Kill process

217˜ 225

162˜ 169

Chrome passwords

170˜ 176

Run service

227˜ 235

177˜ 202Run command

237˜ 245

203˜ 210

keylogger̲windows.go wasdeleted but keylogger
command exists

Added command related todownloadFile.go is added
Deleted command related tochrome̲windows.go is deleted

33

FFRI Security, Inc.

GO LANGUAGE MALWAREADVANCED ANALYSIS
34

FFRI Security, Inc.

Go Version Upgrade• Tools work well suddenly stop working well
– Version upgrades to the Go language change the data that the tool references– Example: ElectroRAT can be analyzed, but newer Chaos cannot be analyzed, etc.
• Contents will be covered in this presentation– Explanation of metadata structure of Go language binaries• Information used by existing tools• Changes in past version upgrades– Tool modification case study

35

FFRI Security, Inc.

Introduction of Go Binary Metadata• Data that the tool often refers to– Function Information• Contains information such as function names• Used for displaying stack traces, etc.
– Data information• Includes data names and field information• Used to specify types in object creation, interface{}, and map

36

FFRI Security, Inc.

Overview of Metadata Composition• Structure to manage the metadata– moduledata• Maintains link to pcHeader and data type information– pcHeader• Maintains links to function information

Only some fields in the binary for 64-bit are shown, andthe same applies to subsequent figures.

37

FFRI Security, Inc.

Metadata Components• moduledata *– pcHeader• Pointer to pcHeader– text• Pointer to code
• Basically identical to .text section– types• Base address for type information– typelinks• Array (slice) of offsets from types to type
information* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/symtab.go#L415-L457

38

FFRI Security, Inc.

Metadata Components• moduledata *– pcHeader
Offset changes due to field additions• Pointer to pcHeader
Go 1.7 , Go 1.8 , Go 1.16 , Go 1.17 , Go 1.18 , Go 1.20
– text• Pointer to code
• Basically identical to .text section
Adding types
Go 1.7– types• Base address for type information– typelinks• Array (slice) of offsets from types to type
information
Change from pointer to offset
Go 1.7* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/symtab.go#L415-L457

39

FFRI Security, Inc.

Metadata Components• pcHeader *– magic, pad1, pad2
• Fixed value– ptrSize• Pointer Size
– nfunc• Number of functions– textStart• Same as moduledata.text– funcnameOffset• Offset from pcHeader to function name sequence– pclnOffset• Offset from pcHeader to array containing link to function information* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/symtab.go#L395-L408

40

FFRI Security, Inc.

Metadata Components

Change magic
Go 1.16, Go 1.18, Go 1.20

• pcHeader *– magic, pad1, pad2
• Fixed value– ptrSize• Pointer Size
– nfunc• Number of functions
Offset changes due to field additions– textStart
Go 1.16 , Go 1.18
• Same as moduledata.text– funcnameOffset
Reference method change• Offset from pcHeader to function name sequence
Go 1.16– pclnOffset• Offset from pcHeader to array containing link to function information* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/symtab.go#L395-L408

41

FFRI Security, Inc.

Locating Metadata• Use the section– pcHeader is placed at the beginning of the .gopclntab section– .gopclntab section may not exist in Windows• When "-ldflags="-w -s" option is used
Go 1.19• Use magic in pcHeader– The first magic field has the value "0xfffffff0".
• Error occurs when this field is written– pclnOffset, etc. can be written– Explore this value• moduledata can be searched from pointers on pcHeader

42

FFRI Security, Inc.

Composition of function information• Flow of retrieving the following information from pcHeader– Function address– Function name
– Argument and return bytes
Flow to obtain ̲func that holding
function information

Flow of getting function informationfrom ̲func

43

FFRI Security, Inc.

Components of Function Information• functab *– entryoff• Offset to the first address of the function• Relative to pcHeader.textStart– funcoff• Offset to function information• Relative to the head of functab array* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/symtab.go#L562-L565

44

FFRI Security, Inc.

Components of Function Information• functab *– entryoff• Offset to the first address of the function• Relative to pcHeader.textStart– funcoff• Offset to function information• Relative to the head of functab array

Change from pointer to offset
Go 1.18

Change in size
Go 1.18
Change of base address
Go 1.16* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/symtab.go#L562-L565

45

FFRI Security, Inc.

Components of Function Information•

̲func *
– entryoff• Offset to the first address of the function• Relative to pcHeader.textStart– nameoff• Offset to function name
• pcHeader address + pcHeader.funcnameOffset+ ̲func.nameoff– args• Number of bytes used in arguments and return
values– pcsp, pcfile, pcln
• Information to retrieve stack size, file name,and line number corresponding to the assembly• How to retrieve the information will be published later in ourblog* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/runtime2.go#L869-L885

46

FFRI Security, Inc.

Components of Function Information•

̲func *
– entryoff• Offset to the first address of the function• Relative to pcHeader.textStart– nameoff• Offset to function name
• pcHeader address + pcHeader.funcnameOffset+ ̲func.nameoff– args• Number of bytes used in arguments and return
values– pcsp, pcfile, pcln
• Information to retrieve stack size, file name,and line number corresponding to the assembly

Change from pointer to offset
Go 1.18

Change the base address of nameoff
Go 1.16• How to retrieve the information will be published later in ourblog* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/runtime2.go#L869-L885

47

FFRI Security, Inc.

Function information retrieval

functab[nfunc].

• Exemplified by Ghidra
＋

＋
̲func

＋

＋
function namestring48

FFRI Security, Inc.

Composition of data type information• The flow for obtaining the ̲type structure containing each data type informationfrom moduledata is shown in the figure below• ̲type– Maintains information such as size and type of data type– Information specific to each type is added at the end of ̲type– Used in object creation and map access functions

49

FFRI Security, Inc.

Components of data type information• ̲type *– size• Number of bytes of data type– kind• Data Type• Example of relationship between value
and type– 1: Bool, 2: Int, 17: Array, 21: Map,
22: Pointer, 25: Struct– str• Offset to data type name• Relative to moduledata.types* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/type.go#L35-L52

50

FFRI Security, Inc.

Components of data type information• ̲type *– size• Number of bytes of data type– kind• Data Type• Example of relationship between value
and type– 1: Bool, 2: Int, 17: Array, 21: Map,
22: Pointer, 25: Struct– str• Offset to data type name• Relative to moduledata.types

Change from pointer to offset
Go 1.7
Change in method of
obtaining strings
Go 1.17* https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/runtime/type.go#L35-L52

51

FFRI Security, Inc.

Data type information retrieval• Exemplified by Ghidra

Array of typelinks

＋
̲type

0x36&0x1f=22

52

FFRI Security, Inc.

Example of Go Version Upgrade Support• Target sample– Chaos• Hash value:
ebe0f9855eb8f6bd980ed60c26e3a877dc1ace5d664e248bb0558996fe0bd06f– Go version: Go 1.18.1– OS: Linux– Arch: x86• Tool (esp. software, etc.)– https://github.com/f0rki/r2-go-helpers• Script for radare2• Function: Resolve function name53

FFRI Security, Inc.

Confirm current scope of support• Results of applying to a binary built with Go 1.15
– Function enumeration (afl)Correction
Corrected to vaddr– Assembly view of go.main.main (pdf)

Add 4 to the argument

54

FFRI Security, Inc.

Confirmation of current scope of support• Application results for Chaos– Execute script
Function Address
Obviously different values
are displayed.

– Function enumeration (afl)Functions are notenumerated

55

FFRI Security, Inc.

Impact of Version Upgrade• pcHeader → ̲func– magic value changed– Change reference method for arrays containing links to function information– Change base address of functab.funcoff– Functab field size changed from pointer size to 0x4
pcHeaderimmediately
followed byfunctab[nfunc]

Go 1.15 or earlier

0xfffffffb

0xfffffff0

Go 1.18 or later
Locating functab[nfunc]
using pclnOffset

56

FFRI Security, Inc.

Impact of Version Upgrade• ̲func → Function information– ̲func.entryoff changed from pointer to offset– Base address change for ̲func.nameoff

Go 1.15 or earlier

Go 1.18 or later

57

FFRI Security, Inc.

Tool modification for Chaos• Causes of failure in extraction– Failure to respond to changes between Go 1.15 and Go 1.18.
• Areas that should be corrected *Different method of obtaining
functab array position
Different functab sizes
It will be an offset, not anaddress.
Base address is different* https://github.com/f0rki/r2-go-helpers/blob/d1167e4b96ba0e3c33ee8c5e578bb3cde930324e/gohelper.py#L165-L177

58

FFRI Security, Inc.

Applying modified tools to Chaos• Application results for Chaos– Function enumeration (afl)– Assembly view of go.main.main (pdf)59

FFRI Security, Inc.

Support for obfuscation by gobfuscate• What will be explained– Introduction of obfuscation methods with gobfuscate– Malware String Unobfuscation– Functional Estimation in Obfuscated Malware• Target sample– ChaChi• Hash value:
8a9205709c6a1e5923c66b63addc1f833461df2c7e26d9176993f14de2a39d5b

60

FFRI Security, Inc.

Obfuscation with gobfuscate• What is gobfuscate?
– Functions: obfuscation of strings and functions, etc.
– Obfuscation by modifying source code, etc.
– https://github.com/unixpickle/gobfuscate

String obfuscation

Obfuscated functions
Should bea string
Should bea string• Here we deal with string obfuscation

func Bool(name string, value bool, usage string) *bool ** https://github.com/golang/go/blob/4a4127bccc826ebb6079af3252bc6bfeaec187c4/src/flag/flag.go#L734

61

FFRI Security, Inc.

gobfuscate string obfuscation• String obfuscation methods with gobfuscate– Generating a string with an anonymous function– String is encrypted by XOR

Function generated when obfuscating "golang" with gobfuscate
An anonymous function is used.

Converts a byte sequence to a string62

FFRI Security, Inc.

String obfuscation in ChaChi

Byte-string extraction• Function: main.main.func1

XOR a sequence of bytes.
0x41fbfb281bda8257

0x2888894d6bf7ed3

0xeb50

0x9f23

XOR

XOR

0x69737265702d6f6e

0x7473

no-persist

Number of loops

Converts a byte sequence to a string and places
it in the return value.

63

FFRI Security, Inc.

Anonymous Functions• Go Language Anonymous Functions– Example: f := func(arg string) string { return "arg: " + arg }• Representation in Assembly– Function name is in the form "<function name of implementation source>.func%d"• Not all function names of this form are developer-implemented anonymous
functions.

64FFRI Security, Inc.

String Obfuscation Removal for ChaChi•

How to implement?
– For functions that are anonymous and only called byruntime.slicebytetostring• With exceptions such as the function itself andruntime.morestack̲noctxt– Get the data stored on the stack in the second and thirdlines of the function– XOR the acquired data and convert it to a string– Rename the function name with the obtained string

main.main.func1 function

Second and third lines

snipped65

FFRI Security, Inc.

String Obfuscation Removal for ChaChi• Multiple obfuscated strings• Stored in memory after decryption

ChaChi's main.init function(The label of the destination memory is set manually.)

UnobfuscatedUnobfuscatedUnobfuscated66FFRI Security, Inc.

Function estimation of Obfuscated Malware• Obfuscated strings in ChaChi have been resolved, but there is still obfuscatedinformation that is difficult to parse• Introduction to the estimation of functions and OSS libraries used to efficiently
analyze obfuscated samples– Estimate functions• Collection of surface information
Obfuscated function names do not reveal– Estimate OSS libraries in use
what they are doing.
• Estimated from file name, line number, etc.

67

FFRI Security, Inc.

Estimating the function• Check the file name sequence• The service is supposed to have the ability to run– service.go file exists• Call OpenService in the internal process
filename sequence

68

FFRI Security, Inc.

Presumption of OSS libraries• Investigate heimaoplnhkdaeiflhmp/lpdkaklidghllnacngmd/lmmbpplgmfkpanjncdff– Probably OSS libraries available on github.com• If you can identify the above paths, you can read the source code to understand the internal
processing and usage, which makes the analysis more efficient• Attempt a search with the following unobfuscated string
SYSTEM¥CurrentControlSet¥Control

WaitToKillServiceTimeout

69

FFRI Security, Inc.

Identify Library• Search: "site:github.com golang WaitToKillServiceTimeout
SYSTEM¥CurrentControlSet¥control"– https://github.com/kardianos/service/blob/master/service̲windows.go• File name matches• Line numbers also match to some extent– String obfuscation shifts the number of lines– https://github.com/takama/daemon/blob/master/daemon̲windows.go• File names do not match• OSS library "github.com/kardianos/service" is used

70

FFRI Security, Inc.

OSS libraries used by ChaChi• github.com/rs/xid– Obtain a unique ID• github.com/fasthttp/websocket– gorilla/websocket fork with fasthttp support• github.com/armon/go-socks5– SOCKS5 Server• github.com/fsnotify/fsnotify– File system notification• github.com/jpillora/backoff– Exponential backoff counter• github.com/Jeffail/tunny– Library for generating and managing Goroutine pools• etc.
71

FFRI Security, Inc.

SUMMARY

72

FFRI Security, Inc.

Reflection and Challenges• Challenge– Go language malware presents several challenges that make analysis difficult• To improve analytical skills– Basic analysis flow and tips
– How to modify the metadata in Go language binaries and the tools that use it– Support for Go language version upgrades– Coutermeasures against obfuscated samples• Future Issues– Poor decompile performance of Ghidra and others– Lack of dynamic analysis tools73

FFRI Security, Inc.

Tools
• https://github.com/mooncat-greenpy/Ghidra̲GolangAnalyzerExtension– Ghidra plugin for binary analysis made by Go language used mainly in thispresentation• https://github.com/FFRI/JSAC2023-GolangMalwareAnalysis– Scripts of radare2 modified in response to version upgrade– Ghidra script to remove string obfuscation by gobfuscate

74

FFRI Security, Inc.

Thank you for attending!

FFRI Security, Inc.

APPENDIX76

FFRI Security, Inc.

Appendix: init Function• init function– It is a function used for initialization, etc.
– Called before the main function– Multiple definitions possible• Representation in Assembly– Function names are in the form "<module name>.init.%d" or "<module name>.init"• Example: main.init.0– init function is called by runtime.doInit function• runtime.doInit function is called from runtime.main function which calls mainfunction

77

FFRI Security, Inc.

Appendix : Goroutine• Goroutine– Go's unique lightweight threads– Example: go sub̲func(0x1, 0x10, 0x100, 0x1000) // execute sub̲func function• Representation in Assembly– Goroutine is started by runtime.newproc function– Argument differences by version• Go 1.17 or lower– Pass a pointer to memory with "call function pointer, argument 1, argument 2, ..."
as the second argument• Go 1.17 or higher– A wrapper function for the target function is passed to newproc» Some arguments are provided in the wrapper function• Go 1.18 or higher– Pass the pointer described above as the first argument

78

FFRI Security, Inc.

Appendix: Version Determination• Here is how to retrieve the version of the Go language used to build the Go binaries
Search this byte
sequence

Pointer to string

Pointer Size

Version string
It was built with Go 1.13.5.

Character string
lengthPointer to version information

79