Created
January 10, 2024 10:22
-
-
Save kendallgoto/530526755d527f44618ee3baf75e154e to your computer and use it in GitHub Desktop.
tear up ilo4_extract.py to messily read ilo3 binaries
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
#!/usr/bin/python | |
# modified from https://github.com/airbus-seclab/ilo4_toolbox/blob/master/scripts/iLO4/ilo4_extract.py | |
# and dependent on some adjacent libraries | |
# Extract binaries from HPIMAGE update file | |
# Blackbox analysis, might be inaccurate | |
import os | |
import sys | |
from ilo4lib import * | |
from struct import unpack_from | |
BEGIN_SIGN = "--=</Begin HP Signed File Fingerprint\>=--\n" | |
END_SIGN = "--=</End HP Signed File Fingerprint\>=--\n" | |
BEGIN_CERT = "-----BEGIN CERTIFICATE-----\n" | |
END_CERT = "-----END CERTIFICATE-----\n" | |
IMG_LIST = ["elf", "kernel_main", "kernel_recovery"] | |
HPIMAGE_HDR_SIZE = 0x4A0 | |
BOOTLOADER_HDR_SIZE = 0x440 | |
IMG_HDR_SIZE = 0x440 | |
if len(sys.argv) != 3: | |
print "usage: %s <filename> <outdir>" | |
sys.exit(1) | |
filename = sys.argv[1] | |
outdir = sys.argv[2] | |
if not os.path.exists(outdir): | |
os.makedirs(outdir) | |
with open(filename, "rb") as fff: | |
data = fff.read() | |
# jump to fingerprints | |
signature_data = data[:] | |
cert_num = 0 | |
while True: | |
end_mark = signature_data.find(END_SIGN) | |
if end_mark < 0: | |
break | |
signature_data = signature_data[end_mark+len(END_SIGN):] | |
while signature_data.startswith(BEGIN_CERT): | |
off = signature_data.find(END_CERT) + len(END_CERT) | |
cert_data = signature_data[:off] | |
signature_data = signature_data[off:] | |
print "[+] Extracting certificate %d" % cert_num | |
with open(outdir + "/cert%d.x509" % cert_num, "wb") as fff: | |
fff.write(cert_data) | |
cert_num += 1 | |
#------------------------------------------------------------------------------ | |
# extract HP images: userland, kernel and bootloader | |
# HPImage header seems to go away in iLO3, | |
# instead we immediately start with the iLO magic string ... | |
# if not data.startswith("HPIMAGE"): | |
# print "[-] Bad file format\n HPIMAGE magic not found" | |
# sys.exit(1) | |
# hpimage_header = data[:HPIMAGE_HDR_SIZE] | |
# data = data[HPIMAGE_HDR_SIZE:] | |
# offsets_map["HPIMAGE_HDR"] = global_offset | |
# global_offset += HPIMAGE_HDR_SIZE | |
# print "[+] iLO HPIMAGE header :" | |
# with open(outdir + "/hpimage.hdr", "wb") as fff: | |
# fff.write(hpimage_header) | |
# img_hdr = HpImageHeader.from_buffer_copy(hpimage_header) | |
# img_hdr.dump() | |
#------------------------------------------------------------------------------ | |
# extract target info | |
# not sure where this lives in ilo3s | |
#------------------------------------------------------------------------------ | |
# get signature: should be iLO3, iLO4 or iLO5 | |
ilo_sign = data[:4] | |
ilo_bootloader_header = data[:BOOTLOADER_HDR_SIZE] | |
ilo_bootloader_footer = data[-0x40:] | |
data = data[BOOTLOADER_HDR_SIZE:] | |
print "[+] iLO bootloader header : %s" % (ilo_bootloader_header[:0x1a]) | |
with open(outdir + "/bootloader.hdr", "wb") as fff: | |
fff.write(ilo_bootloader_header) | |
bootloader_header = BootloaderHeader.from_buffer_copy(ilo_bootloader_header) | |
bootloader_header.dump() | |
with open(outdir + "/bootloader.sig", "wb") as fff: | |
fff.write(bootloader_header.to_str(bootloader_header.signature)) | |
#------------------------------------------------------------------------------ | |
# extract Bootloader footer and cryptographic parameters | |
print "[+] iLO Bootloader footer : %s" % (ilo_bootloader_footer[:0x1a]) | |
bootloader_footer = BootloaderFooter.from_buffer_copy(ilo_bootloader_footer) | |
bootloader_footer.dump() | |
total_size = bootloader_header.total_size | |
print "\ntotal size: 0x%08x" % total_size | |
print "payload size: 0x%08x" % len(data) | |
print "kernel offset: 0x%08x\n" % bootloader_footer.kernel_offset | |
ilo_bootloader = data[-bootloader_footer.kernel_offset:-BOOTLOADER_HDR_SIZE] | |
with open(outdir + "/bootloader.bin", "wb") as fff: | |
fff.write(ilo_bootloader) | |
data = data[:total_size-BOOTLOADER_HDR_SIZE] | |
ilo_crypto_params = data[len(data)-((~bootloader_footer.sig_offset + 1) & 0xFFFF): len(data)-0x40] | |
with open(outdir + "/sign_params.raw", "wb") as fff: | |
fff.write(ilo_crypto_params) | |
crypto_params = SignatureParams.from_buffer_copy(ilo_crypto_params) | |
crypto_params.dump() | |
#------------------------------------------------------------------------------ | |
# extract images | |
ilo_num = 0 | |
off = data.find(ilo_sign) | |
while off >= 0: | |
# skip padding | |
if data[:off] != "\xff" * off: | |
with open(outdir + "/failed_assert.bin", "wb") as fff: | |
fff.write(data) | |
assert(data[:off] == "\xff" * off) | |
data = data[off:] | |
# extract header | |
ilo_header = data[:IMG_HDR_SIZE] | |
data = data[IMG_HDR_SIZE:] | |
with open(outdir + "/%s.hdr" % IMG_LIST[ilo_num], "wb") as fff: | |
fff.write(ilo_header) | |
print "[+] iLO Header %d: %s" % (ilo_num, ilo_header[:0x1a]) | |
img_header = ImgHeader.from_buffer_copy(ilo_header) | |
img_header.dump() | |
with open(outdir + "/%s.sig" % IMG_LIST[ilo_num], "wb") as fff: | |
fff.write(img_header.to_str(img_header.signature)) | |
payload_size = img_header.raw_size - IMG_HDR_SIZE | |
data1 = data[:payload_size] | |
data = data[payload_size:] | |
psz, = unpack_from("<L", data1) | |
data1 = data1[4:] | |
assert(psz == payload_size-4) | |
assert(psz == len(data1)) | |
window = ['\0'] * 0x1000 | |
wchar = 0 | |
with open(outdir + "/%s.raw" % IMG_LIST[ilo_num], "wb") as fff: | |
fff.write(data1) | |
print "[+] Decompressing" | |
output_size = decompress_all(data1, outdir + "/%s.bin" % IMG_LIST[ilo_num]) | |
print " decompressed size : 0x%08x\n" % (output_size) | |
print "[+] Extracted %s.bin" % IMG_LIST[ilo_num] | |
off = data.find(ilo_sign) | |
ilo_num += 1 | |
if ilo_num == 3: | |
break | |
#------------------------------------------------------------------------------ | |
# output offsets map | |
# broken | |
print "\n> done\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment