-1

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?

THX1339
  • 17
  • 3
  • I'd expact, `CreateThread` creates a thread, not a process. – kostix Apr 20 '22 at 11:41
  • 1
    Can you post the disassembled shellcode? Otherwise it's hard to understand what the code to be run by a new thread is supposed to do. "calc.exe HEX" is not it. – kostix Apr 20 '22 at 11:43
  • you need replace at the end of string *ff**d**563* to *ff**e**563* – RbMm Apr 20 '22 at 12:50
  • @kostix I'm sorry if i phrased it incorrectly, but *both* CreateProccess and Createthread are killing the parent process. Also, the shellcode was generated using msfvenom -a x64 -p windows/x64/exec CMD=calc.exe -f hex – THX1339 Apr 20 '22 at 13:02
  • I can't speak specifically to the Windows implementation, but Go uses the system's thread routines to run goroutines and will *give your thread away* if you are not careful. On a Linux or Unix like system you must use `runtime.LockOSThread` to avoid this. – torek Apr 20 '22 at 13:29
  • shell code is wrong - how i say - replace ffd563 to ffe563 in your string. crash at call `ExitProcess` because stack wrong aligned – RbMm Apr 20 '22 at 14:05
  • Thank you, @RbMm, however, once shellcode is modified to that state, the outcome is still the same, shellcode executes, parent dies. – THX1339 Apr 20 '22 at 14:27
  • not the same. in original version - was crash. if do my modification - no crash. correct process exit – RbMm Apr 20 '22 at 14:40
  • downvote for obfuscated code - we're not running or participating in an exploit farm here. please make your examples _suitable_ for the general public. – Ярослав Рахматуллин Apr 22 '22 at 08:35
  • I'm sorry but i mentioned that the base64 "code" is actually just generated through msfvenom, a well known shellcode generation tool, but at @RbMm said, It turns out it _was_ a shellcode issue indeed that's crashing my flow. – THX1339 Apr 24 '22 at 03:19

1 Answers1

0

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.

THX1339
  • 17
  • 3