Skip to content

Instantly share code, notes, and snippets.

@Egor-Skriptunoff
Last active April 25, 2020 21:17
Show Gist options
  • Save Egor-Skriptunoff/fc40fb206f5df6b8027e71a39f5ccfb5 to your computer and use it in GitHub Desktop.
Save Egor-Skriptunoff/fc40fb206f5df6b8027e71a39f5ccfb5 to your computer and use it in GitHub Desktop.
LuaJIT script to receive a message sent with OutputDebugMessage() from LGS/GHUB
-- This LuaJIT script receives first OutputDebugMessage() from LGS/GHUB, prints the message to stdout and exits
-- Waiting is limited to 2 seconds
local timeout_msec = 2000 -- set 2^32-1 for infinite waiting
local ffi = require"ffi"
local psapi = ffi.load"psapi"
ffi.cdef[[
uint32_t EnumProcesses(uint32_t *, uint32_t, uint32_t *);
void ** OpenProcess(uint32_t, uint32_t, uint32_t);
uint32_t CloseHandle(void **);
uint32_t GetModuleBaseNameA(void **, void **, void *, uint32_t);
uint32_t DebugActiveProcess(uint32_t);
uint32_t DebugActiveProcessStop(uint32_t);
uint32_t DebugSetProcessKillOnExit(uint32_t);
typedef struct {
uint32_t dwDebugEventCode;
uint32_t dwProcessId;
uint32_t dwThreadId;
union {
struct {
void ** hFile;
void ** hProcess;
} CreateProcessInfo;
struct {
void * lpDebugStringData;
uint16_t fUnicode;
uint16_t nDebugStringLength;
} DebugString;
} u;
} *LPDEBUG_EVENT;
uint32_t WaitForDebugEvent(LPDEBUG_EVENT, uint32_t);
uint32_t ContinueDebugEvent(uint32_t, uint32_t, uint32_t);
uint32_t ReadProcessMemory(void **, void *, void *, size_t, size_t *);
]]
local DWORDS = ffi.typeof"uint32_t[?]"
local block64K = DWORDS(16384)
local DebugEvent = ffi.cast("LPDEBUG_EVENT", block64K)
local block20 = DWORDS(5)
local PID
if psapi.EnumProcesses(block64K, ffi.sizeof(block64K), block20) ~= 0 then
for j = 0, block20[0]/4 - 1 do
local next_PID = block64K[j]
local ProcessHandle = ffi.C.OpenProcess(0x0410, 0, next_PID) -- PROCESS_VM_READ | PROCESS_QUERY_INFORMATION
if ProcessHandle ~= nil then
local name_len = psapi.GetModuleBaseNameA(ProcessHandle, nil, block20, ffi.sizeof(block20))
ffi.C.CloseHandle(ProcessHandle)
local ProcessName = ffi.string(block20, name_len)
if ProcessName == "LCore.exe" or ProcessName == "lghub_agent.exe" then
PID = next_PID
break
end
end
end
end
if PID and ffi.C.DebugActiveProcess(PID) ~= 0 then
ffi.C.DebugSetProcessKillOnExit(0)
local ProcessHandle
repeat
local exit = ffi.C.WaitForDebugEvent(DebugEvent, timeout_msec) == 0
if not exit then
local ThreadId = DebugEvent.dwThreadId
local info = DebugEvent.u.CreateProcessInfo
local DebugEventCode = DebugEvent.dwDebugEventCode
if DebugEventCode == 3 then -- CREATE_PROCESS_DEBUG_EVENT
ProcessHandle = info.hProcess
ffi.C.CloseHandle(info.hFile)
elseif DebugEventCode == 6 then -- LOAD_DLL_DEBUG_EVENT
ffi.C.CloseHandle(info.hFile)
elseif DebugEventCode == 8 then -- OUTPUT_DEBUG_STRING_EVENT
exit = true
info = DebugEvent.u.DebugString
local len = info.nDebugStringLength
if len ~= 0 and info.fUnicode == 0
and ffi.C.ReadProcessMemory(ProcessHandle, info.lpDebugStringData, block64K, len, nil) ~= 0
then
local str = ffi.string(block64K, len - 1)
print(str)
end
end
ffi.C.ContinueDebugEvent(PID, ThreadId, 0x10002) -- DBG_CONTINUE
end
until exit
ffi.C.DebugActiveProcessStop(PID)
ffi.C.CloseHandle(ProcessHandle)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment