This SSH client was modified. It has made a trivial choice for its random. This made all SSH packets transparent.
Download: SecureSHell.zip
import os, zipfile
from Serializer.Base import *
from FileFormat import PCAPNG
from Base.Show import *
from Network.TCP import *
from Network.SSH import *
base = "/home/chihong/sambashare/CTF/events/2020-08-18_Hackers_Playground/Secure_SHell/"
files = os.listdir(base)
print(files)
src = f"{base}/{files[2]}"
dest = f"{base}"
zipfile.ZipFile(src).extractall(dest)
fp = f"{base}/{files[0]}"
data = open(fp, "rb").read()
print(len(data))
result = DeserializeIterate(PCAPNG.General_Block, data)
print(len(result))
packets = list()
for item in result:
#print("="*100)
#ShowDict(item)
if item["type"][2] == "Enhanced Packet Block":
packet_data = item["data"]["packet"][2]
packet = Unpack(Ethernet2, packet_data)
if packet["ether type"] == "IPv4":
packet["payload"] = Unpack(IPv4, bytes.fromhex(packet["payload"]))
if packet["payload"]["protocol"] == "TCP":
packet["payload"]["payload"] = Unpack(TCP, bytes.fromhex(packet["payload"]["payload"]))
packets.append(packet)
print(len(packets))
payloads = list()
for idx, packet in enumerate(packets):
print("="*100)
#ShowDict(packet)
stream = packet["payload"]["payload"]
size = 0
if "payload" in stream.keys():
size = len(stream["payload"])//2
flags = str()
items = ["NS", "CWR", "ECE", "URG", "ACK", "PSH", "RST", "SYN", "FIN"]
for item in items:
if stream[item]:
flags += item + " "
source = f"{packet['payload']['source ip address']}:{stream['source port']}"
destination = f"{packet['payload']['destination ip address']}:{stream['destination port']}"
print(f"{idx:3}-th packet {source:>22} -> {destination:<22} {flags:16} payload {size} bytes")
if size > 0:
print("-"*100)
print(f"{len(payloads)}-th payloads\t{stream['payload']}")
payloads.append(bytes.fromhex(stream["payload"]))
print(len(payloads))
version_string_from_server = payloads[0].split(b"\r\n")[0]
print(version_string_from_server.decode())
version_string_from_client = payloads[1].split(b"\r\n")[0]
print(version_string_from_client.decode())
ssh_payload_key_init_from_server = Unpack(SSH_PACKET, payloads[2])["payload"]
key_init_from_server = Unpack(SSH_MSG_KEXINIT, ssh_payload_key_init_from_server)
ShowDict(key_init_from_server)
ssh_payload_key_init_from_client = Unpack(SSH_PACKET, payloads[3])["payload"]
key_init_from_client = Unpack(SSH_MSG_KEXINIT, ssh_payload_key_init_from_client)
ShowDict(key_init_from_client)
NIST Curve P256 base point $$G = (48439561293906451759052585252797914202762949526041747995844080717082404635286, 36134250956749795798585127919587881956611106672985015071877198253568414405109)$$
client's public point $$A = a*G = (48439561293906451759052585252797914202762949526041747995844080717082404635286, 36134250956749795798585127919587881956611106672985015071877198253568414405109)$$
server's public point $$B = b*G = (21864520783665454855002022074010285730585032824798206675619652682902836405360, 63996104614066925323831115738336842583805177542348603620328310495655730595671)$$
We know that the client's secret multiplier $a = 1$ and so the shared secret point $$C = ab*G = B$$
curve_param = ECDSA_PARAM["NIST_Curve_P256"]
EC = EllipticCurve(*curve_param[0:3])
G = tuple(curve_param[3:5])
EC.AssertPoint(G)
print(G)
ssh_payload = Unpack(SSH_PACKET, payloads[4])["payload"]
key_exchange_from_client = Unpack(SSH_MSG_KEXDH_INIT, ssh_payload)
ShowDict(key_exchange_from_client)
A = BytesToECPoint(key_exchange_from_client["e"].to_bytes(65, "big"))
print(A)
i = 0
(i, result0) = UnpackPartial(SSH_PACKET, payloads[5], i)
key_exchange_from_server = Unpack(SSH_MSG_KEXDH_REPLY, result0["payload"])
ShowDict(key_exchange_from_server)
print("-"*120)
(i, result1) = UnpackPartial(SSH_PACKET, payloads[5], i)
newkeys_from_server = Unpack(SSH_MSG_KEXDH_REPLY, result1["payload"])
ShowDict(newkeys_from_server)
ssh_payload = Unpack(SSH_PACKET, payloads[6])["payload"]
newkeys_from_client = Unpack(SSH_MSG_NEWKEYS, ssh_payload)
ShowDict(newkeys_from_client)
B = BytesToECPoint(key_exchange_from_server["f"].to_bytes(65, "big"))
print(B)
#the shared secret is the x-coordinate of the shared point
shared_secret = B[0].to_bytes(32, "big")
print(len(shared_secret), shared_secret)
server_host_key = b"\x00\x00\x00\x13ecdsa-sha2-nistp256\x00\x00\x00\x08nistp256\x00\x00\x00A\x04\x16\xe8\xab=DP3\x02+\x13\x82!l\xed\x10\x8de,\xa7\xe1\x97\x1ct\xbd\x94\xa7\x06\x139\x82\xd9\xe7p\xf2#\xbbA\xd1\xb5\x16H\xa2\xaf\xc3\xf9,,\xee\xcc\x1d\x17\x90c\xc2%\xf9\xcf{\xde\xb7w@a\x86"
client_kex_pub = key_exchange_from_client["e"].to_bytes(65, "big")
server_kex_pub = key_exchange_from_server["f"].to_bytes(65, "big")
message = bytes()
message += len(version_string_from_client).to_bytes(4, "big") + version_string_from_client
message += len(version_string_from_server).to_bytes(4, "big") + version_string_from_server
message += len(ssh_payload_key_init_from_client).to_bytes(4, "big") + ssh_payload_key_init_from_client
message += len(ssh_payload_key_init_from_server).to_bytes(4, "big") + ssh_payload_key_init_from_server
message += len(server_host_key).to_bytes(4, "big") + server_host_key
message += len(client_kex_pub).to_bytes(4, "big") + client_kex_pub
message += len(server_kex_pub).to_bytes(4, "big") + server_kex_pub
message += len(shared_secret).to_bytes(4, "big") + shared_secret
#print(len(message), message)
exchange_hash = hashlib.new("sha256", message).digest()
print(exchange_hash)
public_key = BytesToECPoint(key_exchange_from_server["host_key"]["pub_key"])
print(public_key)
r = key_exchange_from_server["signature"]["signature"]["r"]
s = key_exchange_from_server["signature"]["signature"]["s"]
signature = (r, s)
print(signature)
ecdsa = ECDSA("NIST_Curve_P256", "sha256")
assert ecdsa.Verify(public_key, exchange_hash, signature)
#AES-128-CTR
enc_iv_length = 16
enc_key_length = 16
enc_block_length = 16
#HMAC-SHA256
mac_length = 32
mac_key_length = 32
hash_algo = "sha256"
session_id = exchange_hash
client_iv = hashlib.new(hash_algo, len(shared_secret).to_bytes(4, "big") + shared_secret + exchange_hash + b"A" + session_id).digest()[:enc_iv_length]
client_enc_key = hashlib.new(hash_algo, len(shared_secret).to_bytes(4, "big") + shared_secret + exchange_hash + b"C" + session_id).digest()[:enc_key_length]
client_mac_key = hashlib.new(hash_algo, len(shared_secret).to_bytes(4, "big") + shared_secret + exchange_hash + b"E" + session_id).digest()[:mac_key_length]
server_iv = hashlib.new(hash_algo, len(shared_secret).to_bytes(4, "big") + shared_secret + exchange_hash + b"B" + session_id).digest()[:enc_iv_length]
server_enc_key = hashlib.new(hash_algo, len(shared_secret).to_bytes(4, "big") + shared_secret + exchange_hash + b"D" + session_id).digest()[:enc_key_length]
server_mac_key = hashlib.new(hash_algo, len(shared_secret).to_bytes(4, "big") + shared_secret + exchange_hash + b"F" + session_id).digest()[:mac_key_length]
client_keys = (client_iv, client_enc_key, client_mac_key)
server_keys = (server_iv, server_enc_key, server_mac_key)
server_sequence = 3
server_counter = 0
client_sequence = 3
client_counter = 0
print(client_keys)
print(server_keys)
encrypted_payload = payloads[7]
print("="*120)
print(client_sequence, client_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_SERVICE_REQUEST, ssh_payload)
ShowDict(message_from_client)
##############################################################################
encrypted_payload = payloads[8]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_USERAUTH_REQUEST, ssh_payload)
ShowDict(message_from_server)
print("="*120)
print(client_sequence, client_counter)
encrypted_payload = payloads[9]
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_USERAUTH_REQUEST, ssh_payload)
ShowDict(message_from_client)
##############################################################################
encrypted_payload = payloads[10]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_USERAUTH_SUCCESS, ssh_payload)
ShowDict(message_from_server)
encrypted_payload = payloads[11]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_GLOBAL_REQUEST, ssh_payload)
ShowDict(message_from_server)
encrypted_payload = payloads[12]
print("="*120)
print(client_sequence, client_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_CHANNEL_OPEN, ssh_payload)
ShowDict(message_from_client)
##############################################################################
encrypted_payload = payloads[13]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, ssh_payload)
ShowDict(message_from_server)
encrypted_payload = payloads[14]
print("="*120)
print(client_sequence, client_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_CHANNEL_OPEN, ssh_payload)
ShowDict(message_from_client)
##############################################################################
encrypted_payload = payloads[15]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[0:32]
mac = encrypted_payload[32:64]
#ct = encrypted_payload[:-mac_length]
#mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
print(pt)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
#print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_WINDOW_ADJUST, ssh_payload)
#message_from_server = Unpack(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, ssh_payload)
ShowDict(message_from_server)
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[64:80]
mac = encrypted_payload[80:112]
#ct = encrypted_payload[:-mac_length]
#mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
print(pt)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
#print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
#message_from_server = Unpack(SSH_MSG_CHANNEL_WINDOW_ADJUST, ssh_payload)
message_from_server = Unpack(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, ssh_payload)
ShowDict(message_from_server)
encrypted_payload = payloads[16]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_DATA, ssh_payload)
ShowDict(message_from_server)
print("-"*120)
print(message_from_server["data"].decode())
encrypted_payload = payloads[17]
print("="*120)
print(client_sequence, client_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_CHANNEL_DATA, ssh_payload)
ShowDict(message_from_client)
print("-"*120)
print(message_from_client["data"].decode())
##############################################################################
encrypted_payload = payloads[18]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_DATA, ssh_payload)
ShowDict(message_from_server)
print("-"*120)
print(message_from_server["data"].decode())
encrypted_payload = payloads[19]
print("="*120)
print(client_sequence, client_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_CHANNEL_DATA, ssh_payload)
ShowDict(message_from_client)
print("-"*120)
print(message_from_client["data"].decode())
##############################################################################
encrypted_payload = payloads[20]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_DATA, ssh_payload)
ShowDict(message_from_server)
print("-"*120)
print(message_from_server["data"].decode())
encrypted_payload = payloads[21]
print("="*120)
print(client_sequence, client_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_CHANNEL_DATA, ssh_payload)
ShowDict(message_from_client)
print("-"*120)
print(message_from_client["data"].decode())
##############################################################################
encrypted_payload = payloads[22]
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[:48]
mac = encrypted_payload[48:80]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
print(pt)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_REQUEST, ssh_payload)
ShowDict(message_from_server)
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[80:128]
mac = encrypted_payload[128:160]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
print(pt)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_REQUEST, ssh_payload)
ShowDict(message_from_server)
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[160:176]
mac = encrypted_payload[176:208]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
print(pt)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_EOF, ssh_payload)
ShowDict(message_from_server)
print("="*120)
print(server_sequence, server_counter)
ct = encrypted_payload[208:224]
mac = encrypted_payload[224:256]
iv = int.from_bytes(server_keys[0], "big") + server_counter
pt = AES_CTR(server_keys[1], iv, ct)
print(pt)
assert mac == HMAC_Generate(server_keys[2], server_sequence, pt, hash_algo)
server_sequence += 1
server_counter += len(pt)//enc_block_length
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_server = Unpack(SSH_MSG_CHANNEL_EOF, ssh_payload)
ShowDict(message_from_server)
encrypted_payload = payloads[23]
print("="*120)
print(client_sequence, client_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_CHANNEL_CLOSE, ssh_payload)
ShowDict(message_from_client)
encrypted_payload = payloads[24]
print("="*120)
print(client_sequence, client_counter)
ct = encrypted_payload[:-mac_length]
mac = encrypted_payload[-mac_length:]
iv = int.from_bytes(client_keys[0], "big") + client_counter
pt = AES_CTR(client_keys[1], iv, ct)
assert mac == HMAC_Generate(client_keys[2], client_sequence, pt, hash_algo)
client_sequence += 1
client_counter += len(pt)//enc_block_length
print(pt)
ssh_payload = Unpack(SSH_PACKET, pt)["payload"]
message_from_client = Unpack(SSH_MSG_DISCONNECT, ssh_payload)
ShowDict(message_from_client)