Skip to content

Commit

Permalink
Fix of the bug with long Oracle passwords and creation of oracle2john…
Browse files Browse the repository at this point in the history
….py (o5logon)
  • Loading branch information
k4amos committed Dec 30, 2024
1 parent 5c184a4 commit c718a52
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 1 deletion.
133 changes: 133 additions & 0 deletions run/oracle2john.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env python3

# This software is Copyright (c) 2024, k4amos <k4amos at proton.me>
# and it is hereby released to the general public under the following terms:
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted.

# ---

# Utility to obtain a hash of ORACLE authentication (o5logon) that can be cracked with John
# Usage: ./oracle2john.py -f <pcap files>
#
# This script depends on Scapy (https://scapy.net)
# To install: pip install --user scapy

import sys
import argparse
import re

try:
import scapy.all as scapy
except ImportError:
print(
"\033[91m[Error] Scapy seems to be missing, run 'pip install --user scapy' to install it\033[0m"
)
sys.exit(1)


def read_file(args, filename):
"""
Reads a PCAP file and extracts relevant Oracle authentication data (o5logon).
"""
auth_data = {
"server_auth_sesskey": None,
"auth_vfr_data": None,
"auth_password": None,
"client_auth_sesskey": None,
}

packets = scapy.rdpcap(filename)
for packet in packets:
auth_data = process_packet(args, packet, auth_data)

if auth_data["server_auth_sesskey"] is None or auth_data["auth_vfr_data"] is None:
print(
f"\033[91m[Error] The PCAP file {filename} does not contain the required fields of o5logon authentification\033[0m"
)
elif None not in list(auth_data.values()):
# Format of the hash : $o5logon$ <server's AUTH_SESSKEY> * <AUTH_VFR_DATA> * <AUTH_PASSWORD> * <client's AUTH_SESSKEY>
print(
f'$o5logon${auth_data["server_auth_sesskey"]}*{auth_data["auth_vfr_data"]}*{auth_data["auth_password"]}*{auth_data["client_auth_sesskey"]}'
)

else:
# Format of the hash : $o5logon$ <server's AUTH_SESSKEY> * <AUTH_VFR_DATA>
print(
f'$o5logon${auth_data["server_auth_sesskey"]}*{auth_data["auth_vfr_data"]}'
)


def select_hexa(raw_string):
"""
Extracts the first valid hexadecimal string from the raw data.
"""
match_hexa = re.search(
"([A-Fa-f0-9]+)", raw_string.decode("ascii", errors="ignore").replace(" ", "")
)
if match_hexa:
return match_hexa.group(1)


def process_packet(args, packet, auth_data):
"""
Processes a packet and updates the auth_data dictionary with the extracted values.
"""
raw_data = bytes(packet)

pbkdf2_match = re.search(rb"PBKDF2", raw_data)
if pbkdf2_match:
print(
"\033[91m[Error] Sorry, PBKDF2 is not (yet) supported by this utility (only o5logon is)\033[0m"
)
sys.exit(1)

server_auth_sesskey_match = re.search(
rb"AUTH_SESSKEY([\s\S]+?)AUTH_VFR_DATA", raw_data
)
if server_auth_sesskey_match:
auth_data["server_auth_sesskey"] = select_hexa(
server_auth_sesskey_match.group(1)
)

auth_vfr_data_match = re.search(
rb"AUTH_VFR_DATA([\s\S]+?)(AUTH_GLOBALLY_UNIQUE_DBID|$)", raw_data
)
if auth_vfr_data_match:
auth_data["auth_vfr_data"] = select_hexa(auth_vfr_data_match.group(1))

auth_password_match = re.search(rb"AUTH_PASSWORD([\s\S]+?)AUTH_RTT", raw_data)
if auth_password_match:
auth_data["auth_password"] = select_hexa(auth_password_match.group(1))

client_auth_sesskey_match = re.search(
rb"AUTH_SESSKEY([\s\S]+?)AUTH_PASSWORD", raw_data
)
if client_auth_sesskey_match:
auth_data["client_auth_sesskey"] = select_hexa(
client_auth_sesskey_match.group(1)
)

return auth_data


if __name__ == "__main__":

parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
### Utility to obtain a hash of ORACLE authentication (o5logon) that can be cracked with John
Written by k4amos
Usage: ./oracle2john.py -f <pcap files>
""",
)

parser.add_argument("-f", "--file", type=str, required=True, nargs="+")

parsed_args = parser.parse_args()
args = vars(parsed_args)

for filename in args["file"]:
auth_data = read_file(args, filename)
3 changes: 2 additions & 1 deletion src/o5logon_fmt_plug.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ static struct fmt_tests o5logon_tests[] = {
{"$o5logon$A10D52C1A432B61834F4B0D9592F55BD0DA2B440AEEE1858515A646683240D24A61F0C9366C63E93D629292B7891F44A*878C0B92D61A594F2680", "m3ow00"},
{"$o5logon$52696131746C356643796B6D716F46474444787745543263764B725A6D756A69E46DE32AFBB33E385C6D9C7031F4F2B9*3131316D557239736A65", "123456"},
{"$o5logon$4336396C304B684638634450576B30397867704F54766D71494F676F5A5A386F09F4A10B5908B3ED5B1D6878A6C78751*573167557661774E7271", ""},
{"$o5logon$4D04DBD23D103F05D9B57EB6EC14D83A0A468AB906EAC907D3A8C796573E5F34BC15F0ECBC9EAC0350A38A663A368233*442192E518F6F43D7CF7*D3963B6AAED39C231BD5C92A10C0F146CA4784D1503A9B97598B31D33406390B7CA4F8B3EE5406A54C1842E4E63D1220*192AB7C9BA21C883824CF3D5BA073AC1129FD841E0AF6DF522C7EBDC52783CB8B97B792BFB6D9D743C7F4376FF0E7F93", "password1234567890"}
{NULL}
};

Expand Down Expand Up @@ -131,7 +132,7 @@ static int valid(char *ciphertext, struct fmt_main *self)
if ((p = strtokm(NULL, "*"))) { /* client's encrypted password */
int len = hexlenu(p, &extra);

if (extra || len < 64 || len % 32 || len > 2 * PLAINTEXT_LENGTH + 16)
if (extra || len < 64 || len % 32 || len > 3 * PLAINTEXT_LENGTH)
goto err;
if ((p = strtokm(NULL, "*")) == NULL) /* client's sesskey */
goto err;
Expand Down

0 comments on commit c718a52

Please sign in to comment.