FALSE = 0
TRUE = 1
NULL = 0
nullptr = 0
PAGE_EXECUTE = 0x10
PAGE_EXECUTE_READ = 0x20
PAGE_EXECUTE_READWRITE = 0x40
PAGE_EXECUTE_WRITECOPY = 0x80
PAGE_NOACCESS = 0x01
PAGE_READONLY = 0x02
PAGE_READWRITE = 0x04
PAGE_WRITECOPY = 0x08
PAGE_TARGETS_INVALID = 0x40000000
PAGE_TARGETS_NO_UPDATE = 0x40000000
PAGE_GUARD = 0x100
PAGE_NOCACHE = 0x200
PAGE_WRITECOMBINE = 0x400

MEM_COMMIT = 0x00001000
MEM_RESERVE = 0x00002000
MEM_RESET = 0x00080000
MEM_RESET_UNDO = 0x1000000
MEM_LARGE_PAGES = 0x20000000
MEM_PHYSICAL = 0x00400000
MEM_TOP_DOWN = 0x00100000
MEM_WRITE_WATCH = 0x00200000

MEM_DECOMMIT = 0x00004000
MEM_RELEASE = 0x00008000
MEM_COALESCE_PLACEHOLDERS = 0x00000001
MEM_PRESERVE_PLACEHOLDER = 0x00000002

WAIT_ABANDONED = 0x0000000000000080
WAIT_OBJECT_0 = 0x0000000000000000
WAIT_TIMEOUT = 0x0000000000000102
WAIT_FAILED = 0xFFFFFFFF

function AddressToAssembly(Address)
	if not Address or (Address == 0) then
		return nil
	end
	
	local Data = {}
	
	for i = 0, 7 do
		table.insert(Data, (Address >> (i * 8)) & 0xFF)
	end
	
	return Data
end

function InjectAssemblys(Address, ...)
	if not Address or (Address == 0) then
		return nil
	end
	
	local Data = {...}
	local TempData = {}
	
	for key, value in pairs(Data) do
		if (type(value) == "table") then
			for k, v in pairs(value) do
				table.insert(TempData, v)
			end
		else
			return false
		end
	end
	
	for key, value in pairs(TempData) do
		local offset = key - 1
		memory.set_byte(Address + offset, value)
	end
	
	return true
end

malloc = function(
	size --[[ size_t ]]
	)
	local Function = memory.get_dll_function("ucrtbase.dll", "malloc")
	if (Function == 0) then
		return 0
	end
	
	if not size or (size == 0) then
		size = 8
	end
	
	return memory.fastcall(Function, size)
end

free = function(
	memblock --[[ void* ]]
	)
	local Function = memory.get_dll_function("ucrtbase.dll", "free")
	if (Function == 0) then
		return false
	end
	
	if not memblock or (memblock == 0) then
		return false
	end
	
	memory.fastcall(Function, memblock)
	return true
end

calloc = function(
	number, --[[ size_t  ]]
	size    --[[ size_t ]]
	)
	local Function = memory.get_dll_function("ucrtbase.dll", "calloc")
	if (Function == 0) then
		return 0
	end
	
	if not number or (number == 0) then
		number = 1
	end
	
	if not size or (size == 0) then
		size = 8
	end
	
	local asm = {
		0x55,                                     -- push rbp
		0x48, 0x8B, 0xEC,                         -- mov rbp,rsp
		0x48, 0x81, 0xEC, 0x00, 0x01, 0x00, 0x00, -- sub rsp,100h
		0x48, 0x83, 0xE4, 0xEA,                   -- and rsp,-16h
		0x48, 0x8B, 0x01,                         -- mov rax,[rcx]
		0x48, 0x8B, 0x51, 0x10,                   -- mov rdx,[rcx+10h]
		0x48, 0x8B, 0x49, 0x08,                   -- mov rcx,[rcx+08h]
		0xFF, 0xD0,                               -- call rax
		0x48, 0x8B, 0xE5,                         -- mov rsp,rbp
		0x5D,                                     -- pop rbp
		0xC3                                      -- ret
	}
	
	local ptr = malloc(#asm)
	if (ptr == 0) then
		return 0
	end
	
	if not InjectAssemblys(ptr, asm) then
		free(ptr)
		return 0
	end
	
	local buffer = malloc(3 * 8)
	if (buffer == 0) then
		free(ptr)
		return 0
	end
	
	if (memory.set_protect(ptr, #asm, PAGE_EXECUTE_READWRITE) == 0) then
		free(ptr)
		free(buffer)
		return 0
	end
	
	memory.set_int64(buffer, Function)
	memory.set_int64(buffer + 8, number)
	memory.set_int64(buffer + 16, size)
	
	local result = memory.fastcall(ptr, buffer)
	
	memory.set_protect(ptr, #asm, PAGE_READWRITE)
	free(ptr)
	free(buffer)
	return result
end

VirtualAlloc = function(
	lpAddress,        --[[ [in, optional] LPVOID ]]
	dwSize,           --[[ [in]           SIZE_T ]]
	flAllocationType, --[[ [in]           DWORD ]]
	flProtect         --[[ [in]           DWORD ]]
	)
	local Function = memory.get_dll_function("KERNEL32.dll", "VirtualAlloc")
	if (Function == 0) then
		return 0
	end
	
	local asm = {
		0x55,                                     -- push rbp
		0x48, 0x8B, 0xEC,                         -- mov rbp,rsp
		0x48, 0x81, 0xEC, 0x00, 0x01, 0x00, 0x00, -- sub rsp,100h
		0x48, 0x83, 0xE4, 0xEA,                   -- and rsp,-16h
		0x48, 0x8B, 0x01,                         -- mov rax,[rcx]
		0x4C, 0x8B, 0x49, 0x20,                   -- mov r9,[rcx+20h]
		0x4C, 0x8B, 0x41, 0x18,                   -- mov r8,[rcx+18h]
		0x48, 0x8B, 0x51, 0x10,                   -- mov rdx,[rcx+10h]
		0x48, 0x8B, 0x49, 0x08,                   -- mov rcx,[rcx+08h]
		0xFF, 0xD0,                               -- call rax
		0x48, 0x8B, 0xE5,                         -- mov rsp,rbp
		0x5D,                                     -- pop rbp
		0xC3                                      -- ret
	}
	
	local ptr = malloc(#asm)
	if (ptr == 0) then
		return 0
	end
	
	if not InjectAssemblys(ptr, asm) then
		free(ptr)
		return 0
	end
	
	local buffer = malloc(5 * 8)
	if (buffer == 0) then
		free(ptr)
		return 0
	end
	
	if (memory.set_protect(ptr, #asm, PAGE_EXECUTE_READWRITE) == 0) then
		free(ptr)
		free(buffer)
		return 0
	end
	
	memory.set_int64(buffer, Function)
	memory.set_int64(buffer + 8, lpAddress)
	memory.set_int64(buffer + 16, dwSize)
	memory.set_int64(buffer + 24, flAllocationType)
	memory.set_int64(buffer + 32, flProtect)
	
	local result = memory.fastcall(ptr, buffer)
	
	memory.set_protect(ptr, #asm, PAGE_READWRITE)
	free(ptr)
	free(buffer)
	return result
end

VirtualFree = function(
	lpAddress, --[[ [in] LPVOID ]]
	dwSize,    --[[ [in] SIZE_T ]]
	dwFreeType --[[ [in] DWORD ]]
	)
	local Function = memory.get_dll_function("KERNEL32.dll", "VirtualFree")
	if (Function == 0) then
		return 0
	end
	
	local asm = {
		0x55,                                     -- push rbp
		0x48, 0x8B, 0xEC,                         -- mov rbp,rsp
		0x48, 0x81, 0xEC, 0x00, 0x01, 0x00, 0x00, -- sub rsp,100h
		0x48, 0x83, 0xE4, 0xEA,                   -- and rsp,-16h
		0x48, 0x8B, 0x01,                         -- mov rax,[rcx]
		0x4C, 0x8B, 0x41, 0x18,                   -- mov r8,[rcx+18h]
		0x48, 0x8B, 0x51, 0x10,                   -- mov rdx,[rcx+10h]
		0x48, 0x8B, 0x49, 0x08,                   -- mov rcx,[rcx+08h]
		0xFF, 0xD0,                               -- call rax
		0x48, 0x8B, 0xE5,                         -- mov rsp,rbp
		0x5D,                                     -- pop rbp
		0xC3                                      -- ret
	}
	
	local ptr = malloc(#asm)
	if (ptr == 0) then
		return 0
	end
	
	if not InjectAssemblys(ptr, asm) then
		free(ptr)
		return 0
	end
	
	local buffer = malloc(4 * 8)
	if (buffer == 0) then
		free(ptr)
		return 0
	end
	
	if (memory.set_protect(ptr, #asm, PAGE_EXECUTE_READWRITE) == 0) then
		free(ptr)
		free(buffer)
		return 0
	end
	
	memory.set_int64(buffer, Function)
	memory.set_int64(buffer + 8, lpAddress)
	memory.set_int64(buffer + 16, dwSize)
	memory.set_int64(buffer + 24, dwFreeType)
	
	local result = memory.fastcall(ptr, buffer)
	
	memory.set_protect(ptr, #asm, PAGE_READWRITE)
	free(ptr)
	free(buffer)
	return result
end

VirtualProtect = function(
	lpAddress,     --[[ [in]  LPVOID ]]
	dwSize,        --[[ [in]  SIZE_T ]]
	flNewProtect,  --[[ [in]  DWORD ]]
	lpflOldProtect --[[ [out] PDWORD ]]
	)
	local Function = memory.get_dll_function("KERNEL32.dll", "VirtualProtect")
	if (Function == 0) then
		return 0
	end
	
	local asm = {
		0x55,                                     -- push rbp
		0x48, 0x8B, 0xEC,                         -- mov rbp,rsp
		0x48, 0x81, 0xEC, 0x00, 0x01, 0x00, 0x00, -- sub rsp,100h
		0x48, 0x83, 0xE4, 0xEA,                   -- and rsp,-16h
		0x48, 0x8B, 0x01,                         -- mov rax,[rcx]
		0x4C, 0x8B, 0x49, 0x20,                   -- mov r9,[rcx+20h]
		0x4C, 0x8B, 0x41, 0x18,                   -- mov r8,[rcx+18h]
		0x48, 0x8B, 0x51, 0x10,                   -- mov rdx,[rcx+10h]
		0x48, 0x8B, 0x49, 0x08,                   -- mov rcx,[rcx+08h]
		0xFF, 0xD0,                               -- call rax
		0x48, 0x8B, 0xE5,                         -- mov rsp,rbp
		0x5D,                                     -- pop rbp
		0xC3                                      -- ret
	}
	
	local ptr = malloc(#asm)
	if (ptr == 0) then
		return 0
	end
	
	if not InjectAssemblys(ptr, asm) then
		free(ptr)
		return 0
	end
	
	local buffer = malloc(5 * 8)
	if (buffer == 0) then
		free(ptr)
		return 0
	end
	
	if (memory.set_protect(ptr, #asm, PAGE_EXECUTE_READWRITE) == 0) then
		free(ptr)
		free(buffer)
		return 0
	end
	
	memory.set_int64(buffer, Function)
	memory.set_int64(buffer + 8, lpAddress)
	memory.set_int64(buffer + 16, dwSize)
	memory.set_int64(buffer + 24, flNewProtect)
	memory.set_int64(buffer + 32, lpflOldProtect)
	
	local result = memory.fastcall(ptr, buffer)
	
	memory.set_protect(ptr, #asm, PAGE_READWRITE)
	free(ptr)
	free(buffer)
	return result
end

GetProcessHeap = function()
	local Function = memory.get_dll_function("KERNEL32.dll", "GetProcessHeap")
	if (Function == 0) then
		return 0
	end
	
	return memory.fastcall(Function, 0)
end

WaitForSingleObject = function(
	hHandle,       --[[ [in] HANDLE ]]
	dwMilliseconds --[[ [in] DWORD ]]
	)
	local Function = memory.get_dll_function("KERNEL32.dll", "WaitForSingleObject")
	if (Function == 0) then
		return 0
	end
	
	local asm = {
		0x55,                                     -- push rbp
		0x48, 0x8B, 0xEC,                         -- mov rbp,rsp
		0x48, 0x81, 0xEC, 0x00, 0x01, 0x00, 0x00, -- sub rsp,100h
		0x48, 0x83, 0xE4, 0xEA,                   -- and rsp,-16h
		0x48, 0x8B, 0x01,                         -- mov rax,[rcx]
		0x48, 0x8B, 0x51, 0x10,                   -- mov rdx,[rcx+10h]
		0x48, 0x8B, 0x49, 0x08,                   -- mov rcx,[rcx+08h]
		0xFF, 0xD0,                               -- call rax
		0x48, 0x8B, 0xE5,                         -- mov rsp,rbp
		0x5D,                                     -- pop rbp
		0xC3                                      -- ret
	}
	
	local ptr = VirtualAlloc(nullptr, #asm, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE)
	if (ptr == 0) then
		return 0
	end
	
	if not InjectAssemblys(ptr, asm) then
		VirtualFree(ptr)
		return 0
	end
	
	local buffer = malloc(3 * 8)
	if (buffer == 0) then
		VirtualFree(ptr, NULL, MEM_RELEASE)
		return 0
	end
	
	memory.set_int64(buffer, Function)
	memory.set_int64(buffer + 8, hHandle)
	memory.set_int64(buffer + 16, dwMilliseconds)
	
	local result = memory.fastcall(ptr, buffer)
	
	VirtualFree(ptr, NULL, MEM_RELEASE)
	free(buffer)
	return result
end

CreateThread = function(
	lpThreadAttributes, --[[ [in, optional]  LPSECURITY_ATTRIBUTES ]]
	dwStackSize,        --[[ [in]            SIZE_T ]]
	lpStartAddress,     --[[ [in]            LPTHREAD_START_ROUTINE ]]
	lpParameter,        --[[ [in, optional]  __drv_aliasesMem LPVOID ]]
	dwCreationFlags,    --[[ [in]            DWORD ]]
	lpThreadId          --[[ [out, optional] LPDWORD ]]
	)
	local Function = memory.get_dll_function("KERNEL32.dll", "CreateThread")
	if (Function == 0) then
		return 0
	end
	
	local asm = {
		0x55,                                     -- push rbp
		0x48, 0x8B, 0xEC,                         -- mov rbp,rsp
		0x48, 0x81, 0xEC, 0x00, 0x01, 0x00, 0x00, -- sub rsp,100h
		0x48, 0x83, 0xE4, 0xEA,                   -- and rsp,-16h
		0x48, 0x8B, 0x41, 0x30,                   -- mov rax,[rcx+30h]
		0x48, 0x89, 0x44, 0x24, 0x28,             -- mov [rsp+28h],rax
		0x48, 0x8B, 0x41, 0x28,                   -- mov rax,[rcx+28h]
		0x48, 0x89, 0x44, 0x24, 0x20,             -- mov [rsp+20h],rax
		0x48, 0x8B, 0x01,                         -- mov rax,[rcx]
		0x4C, 0x8B, 0x49, 0x20,                   -- mov r9,[rcx+20h]
		0x4C, 0x8B, 0x41, 0x18,                   -- mov r8,[rcx+18h]
		0x48, 0x8B, 0x51, 0x10,                   -- mov rdx,[rcx+10h]
		0x48, 0x8B, 0x49, 0x08,                   -- mov rcx,[rcx+08h]
		0xFF, 0xD0,                               -- call rax
		0x48, 0x8B, 0xE5,                         -- mov rsp,rbp
		0x5D,                                     -- pop rbp
		0xC3                                      -- ret
	}
	
	local ptr = VirtualAlloc(nullptr, #asm, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE)
	if (ptr == 0) then
		return 0
	end
	
	if not InjectAssemblys(ptr, asm) then
		VirtualFree(ptr)
		return 0
	end
	
	local buffer = malloc(7 * 8)
	if (buffer == 0) then
		VirtualFree(ptr, NULL, MEM_RELEASE)
		return 0
	end
	
	memory.set_int64(buffer, Function)
	memory.set_int64(buffer + 8, lpThreadAttributes)
	memory.set_int64(buffer + 16, dwStackSize)
	memory.set_int64(buffer + 24, lpStartAddress)
	memory.set_int64(buffer + 32, lpParameter)
	memory.set_int64(buffer + 40, dwCreationFlags)
	memory.set_int64(buffer + 48, lpThreadId)
	
	local result = memory.fastcall(ptr, buffer)
	
	VirtualFree(ptr, NULL, MEM_RELEASE)
	free(buffer)
	return result
end

LoadLibraryA = function(
	lpLibFileName --[[ [in] LPCSTR ]]
	)
	local Function = memory.get_dll_function("KERNEL32.dll", "LoadLibraryA")
	if (Function == 0) then
		return 0
	end
	
	local buffer = calloc(1, 1024)
	if (buffer == 0) then
		return 0
	end
	
	memory.set_string(buffer, lpLibFileName)
	local result = memory.fastcall(Function, buffer)
	free(buffer)
	return result
end

CloseHandle = function(
	hObject --[[ [in] HANDLE ]]
	)
	local Function = memory.get_dll_function("KERNEL32.dll", "CloseHandle")
	if (Function == 0) then
		return 0
	end
	
	return memory.fastcall(Function, hObject)
end