-
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add proxy bypass and merge pathgen with autobloody
- Loading branch information
1 parent
cf186d5
commit 4009a49
Showing
7 changed files
with
210 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,6 @@ | ||
#!/usr/bin/env python3 | ||
import argparse, json, sys | ||
from autobloody import automation | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description='Attack Path Executor', formatter_class=argparse.RawTextHelpFormatter) | ||
|
||
# Exploitation parameters | ||
parser.add_argument('-d', '--domain', help='Domain used for NTLM authentication') | ||
parser.add_argument('-u', '--username', help='Username used for NTLM authentication') | ||
parser.add_argument('-p', '--password', help='Cleartext password or LMHASH:NTHASH for NTLM authentication') | ||
parser.add_argument('-k', '--kerberos', action='store_true', default=False) | ||
parser.add_argument('-c', '--certificate', help='Certificate authentication, e.g: "path/to/key:path/to/cert"') | ||
parser.add_argument('-s', '--secure', help='Try to use LDAP over TLS aka LDAPS (default is LDAP)', action='store_true', default=False) | ||
parser.add_argument('--host', help='Hostname or IP of the DC (ex: my.dc.local or 172.16.1.3)', required=True) | ||
parser.add_argument('--path', help='Filename of the attack path generated with pathgen.py (default is "path.json")', default="path.json") | ||
|
||
if len(sys.argv)==1: | ||
parser.print_help(sys.stderr) | ||
sys.exit(1) | ||
|
||
args = parser.parse_args() | ||
automate = automation.Automation(args) | ||
with open(args.path, 'r') as f: | ||
automate.exploit(json.load(f)) | ||
print("[+] Done, attack path executed") | ||
from autobloody import main | ||
|
||
|
||
if __name__ == '__main__': | ||
main() | ||
main.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#!/usr/bin/env python3 | ||
import argparse, json, sys | ||
from autobloody import automation, database, proxy_bypass | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description='AD Privesc Automation', formatter_class=argparse.RawTextHelpFormatter) | ||
|
||
# DB parameters | ||
parser.add_argument("--dburi", default="bolt://localhost:7687", help="The host neo4j is running on (default is \"bolt://localhost:7687\")") | ||
parser.add_argument("-du", "--dbuser", default="neo4j", help="Neo4j username to use (default is \"neo4j\")") | ||
parser.add_argument("-dp", "--dbpassword", help="Neo4j password to use", required=True) | ||
parser.add_argument("-ds", "--dbsource", help="Case sensitive label of the source node (name property in bloodhound)", required=True) | ||
parser.add_argument("-dt", "--dbtarget", help="Case sensitive label of the target node (name property in bloodhound)", required=True) | ||
|
||
# Exploitation parameters | ||
parser.add_argument('-d', '--domain', help='Domain used for NTLM authentication') | ||
parser.add_argument('-u', '--username', help='Username used for NTLM authentication') | ||
parser.add_argument('-p', '--password', help='Cleartext password or LMHASH:NTHASH for NTLM authentication') | ||
parser.add_argument('-k', '--kerberos', action='store_true', default=False) | ||
parser.add_argument('-c', '--certificate', help='Certificate authentication, e.g: "path/to/key:path/to/cert"') | ||
parser.add_argument('-s', '--secure', help='Try to use LDAP over TLS aka LDAPS (default is LDAP)', action='store_true', default=False) | ||
parser.add_argument('--host', help='Hostname or IP of the DC (ex: my.dc.local or 172.16.1.3)', required=True) | ||
|
||
if len(sys.argv)==1: | ||
parser.print_help(sys.stderr) | ||
sys.exit(1) | ||
|
||
args = parser.parse_args() | ||
|
||
path_dict = pathgen(args) | ||
|
||
automate = automation.Automation(args) | ||
automate.exploit(path_dict) | ||
print("[+] Done, attack path executed") | ||
|
||
|
||
def pathgen(args): | ||
bypass = proxy_bypass.ProxyBypass() | ||
db = database.Database(args.dburi, args.dbuser, args.dbpassword) | ||
|
||
path = db.getPrivescPath(args.dbsource, args.dbtarget) | ||
path_dict = [] | ||
for rel in path: | ||
start_node = {'name':rel.start_node['name'], 'distinguishedname':rel.start_node['distinguishedname'], 'objectid':rel.start_node['objectid']} | ||
end_node = {'name':rel.end_node['name'], 'distinguishedname':rel.end_node['distinguishedname'], 'objectid': rel.end_node['objectid']} | ||
path_dict.append({'start_node':start_node, 'end_node':end_node, 'cost':rel['cost']}) | ||
|
||
db.close() | ||
bypass.disable() | ||
|
||
print(f"[+] Done, {len(path_dict)} edges have been found between {args.dbsource} and {args.dbtarget}") | ||
return path_dict | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
from ctypes import * | ||
import os | ||
import socket | ||
import platform | ||
from bloodyAD import utils | ||
|
||
LOG = utils.LOG | ||
|
||
class ProxyBypass(): | ||
proxy_connect = None | ||
|
||
def __init__(self): | ||
proxy_detected = 'LD_PRELOAD' in os.environ and 'proxychains' in os.environ['LD_PRELOAD'] | ||
LOG.info("[*] Connection to Neo4j") | ||
if not proxy_detected: | ||
LOG.info("[*] No proxy detected") | ||
return | ||
supported_platform = platform.system() in ["Darwin", "Linux"] | ||
if not supported_platform: | ||
LOG.warning(f"[-] Proxy detected but {plateform.system()} is not currently supported. Please raise an issue on the Github repo") | ||
return | ||
|
||
self.proxy_connect = socket.socket.connect | ||
|
||
socket.socket.connect = real_connect | ||
LOG.info("[+] Proxy bypass enabled for Neo4j connection") | ||
|
||
def disable(self): | ||
if self.proxy_connect: | ||
socket.socket.connect = self.proxy_connect | ||
LOG.info("[+] Proxy bypass disabled") | ||
|
||
|
||
class c_addrinfo(Structure): | ||
pass | ||
c_addrinfo._fields_ = [ | ||
('ai_flags', c_int), | ||
('ai_family', c_int), | ||
('ai_socktype', c_int), | ||
('ai_protocol', c_int), | ||
('ai_addrlen', c_size_t), | ||
] + ([ | ||
('ai_canonname', c_char_p), | ||
('ai_addr', POINTER(c_sockaddr_in)), | ||
] if platform.system() == 'Darwin' else [ | ||
('ai_addr', c_void_p), | ||
('ai_canonname', c_char_p), | ||
]) + [ | ||
('ai_next', POINTER(c_addrinfo)), | ||
] | ||
|
||
def real_connect(sock_obj, addro): | ||
libc = CDLL('libc.so.6') | ||
get_errno_loc = libc.__errno_location | ||
get_errno_loc.restype = POINTER(c_int) | ||
def errcheck(ret, func, args): | ||
if ret == -1: | ||
e = get_errno_loc()[0] | ||
raise OSError(e) | ||
return ret | ||
|
||
# addr = c_sockaddr_in(sock_obj.family, c_ushort(socket.htons(addro[1])), (c_byte *4)(*[int(i) for i in addro[0].split('.')])) | ||
# size_addr = sizeof(addr) | ||
c_getaddrinfo = libc.getaddrinfo | ||
c_getaddrinfo.errcheck = errcheck | ||
presult = POINTER(c_addrinfo)() | ||
hints = c_addrinfo() | ||
hints.ai_family = sock_obj.family | ||
hints.ai_socktype = sock_obj.type | ||
hints.ai_flags = 0 | ||
hints.ai_protocol = sock_obj.proto | ||
c_getaddrinfo(addro[0].encode('utf-8'), str(addro[1]).encode('utf-8'), byref(hints), byref(presult)) | ||
|
||
# Wait until DB response | ||
blocking = sock_obj.getblocking() | ||
sock_obj.setblocking(True) | ||
|
||
c_connect = libc.connect | ||
c_connect.errcheck = errcheck | ||
c_connect(sock_obj.fileno(), c_void_p(presult.contents.ai_addr), presult.contents.ai_addrlen) | ||
|
||
libc.freeaddrinfo(presult) | ||
|
||
sock_obj.setblocking(blocking) | ||
|
||
# class c_sockaddr_in(Structure): | ||
# _fields_ = [ | ||
# ('sa_family', c_ushort), | ||
# ('sin_port', c_ushort), | ||
# ("sin_addr", c_byte * 4), | ||
# ("__pad", c_byte * 8) | ||
# ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
bloodyAD>=0.1 | ||
neo4j>=4.4.6 | ||
. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from setuptools import setup | ||
from pathlib import Path | ||
this_directory = Path(__file__).parent | ||
long_description = (this_directory / "README.md").read_text() | ||
|
||
setup(name='autobloody', | ||
version='0.1.0', | ||
description='AD Privesc Automation', | ||
long_description=long_description, | ||
long_description_content_type='text/markdown', | ||
author='CravateRouge', | ||
author_email='baptiste.crepin@ntymail.com', | ||
url='https://github.com/CravateRouge/autobloody', | ||
download_url='https://github.com/CravateRouge/bloodyAD/archive/refs/tags/v0.1.0.tar.gz', | ||
packages=['autobloody'], | ||
license='MIT', | ||
install_requires=['bloodyAD>=0.1','neo4j>=4.4.6'], | ||
keywords = ['Active Directory', 'Privilege Escalation'], | ||
classifiers=[ | ||
'Intended Audience :: Information Technology', | ||
'License :: OSI Approved :: MIT License', | ||
'Programming Language :: Python :: 3.6', | ||
'Programming Language :: Python :: 3.7', | ||
'Programming Language :: Python :: 3.8', | ||
'Programming Language :: Python :: 3.9', | ||
'Programming Language :: Python :: 3.10' | ||
], | ||
python_requires='>=3.6', | ||
entry_points={ | ||
"console_scripts":["autobloody = autobloody.main:main"] | ||
} | ||
) |