Created
October 17, 2020 22:08
-
-
Save alexmaloteaux/88a8aaa4c00c87e4532b4b2ff474d6e1 to your computer and use it in GitHub Desktop.
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/env python3 | |
import os, sys | |
#import requests | |
from urllib import request | |
import traceback | |
from shutil import copyfile | |
from hashlib import md5 | |
import binascii | |
supported_version = "9.1.2" | |
class bcolors: | |
OKGREEN = '\033[92m' | |
WARNING = '\033[93m' | |
FAIL = '\033[91m' | |
ENDC = '\033[0m' | |
def print_success(msg): | |
output = bcolors.OKGREEN + msg + bcolors.ENDC | |
print(output) | |
def print_warning(msg): | |
output = bcolors.WARNING + msg + bcolors.ENDC | |
print(output) | |
def print_error(msg): | |
output = bcolors.FAIL + msg + bcolors.ENDC | |
print(output) | |
def print_usage(): | |
print("Usage : %s ghidra_base_folder [-f]" % sys.argv[0]) | |
if len(sys.argv) < 2 or len(sys.argv) > 3: | |
print_usage() | |
sys.exit() | |
ghidra_folder = os.path.join(sys.argv[1], "Ghidra") | |
force = False | |
if len(sys.argv) == 3: | |
if sys.argv[2] == "-f": | |
force = True | |
else: | |
print_usage() | |
sys.exit() | |
if not os.path.exists(ghidra_folder): | |
print_error("ghidra folder not found : %s" % ghidra_folder) | |
sys.exit() | |
manuals = { | |
'6502': [ | |
{ | |
'src' : "http://archive.6502.org/books/mcs6500_family_programming_manual.pdf", | |
'idx' : "6502.idx", | |
'pdf' : "mcs6500_family_programming_manual.pdf", | |
'md5' : "4165237c3c3fa7247714433bacb6ea4e", | |
} | |
], | |
'68000': [ | |
{ | |
'src' : "https://www.nxp.com/files-static/archives/doc/ref_manual/M68000PRM.pdf", | |
'idx' : "68000.idx", | |
'pdf' : "M68000PRM.pdf", | |
'md5' : "c446e98b7f33046f4ed98fcfd4f0a96c", | |
} | |
], | |
'8048': [ | |
{ | |
'src' : "http://www.decadecounter.com/vta/pdf/mcs48.pdf", | |
'idx' : "8048.idx", | |
'pdf' : "8048.pdf", | |
'md5' : "51634c6554dbb072d1956f564f38aa17", | |
} | |
], | |
'8051': [ | |
{ | |
'src' : "https://www.keil.com/dd/docs/datashts/intel/8xc251sx_um.pdf", | |
'idx' : "8051.idx", | |
'pdf' : "8xc251sx_um.pdf", | |
'md5' : "d749e5a0b3186266959dcc2a32b5af3b", | |
} | |
], | |
'AARCH64': [ | |
{ | |
'src' : "http://kib.kiev.ua/x86docs/ARMARM/DDI0487D_b_armv8_arm.pdf", | |
'idx' : "AARCH64.idx", | |
'pdf' : "DDI0487D_b_armv8_arm.pdf", | |
'md5' : "e2a37efc9e942f8260bd021c013c18f4", | |
} | |
], | |
'ARM': [ | |
{ | |
'src' : "https://www.cs.utexas.edu/~simon/378/resources/ARMv7-AR_TRM.pdf", | |
'idx' : "ARM.idx", | |
'pdf' : "Armv7AR_errata.pdf", | |
'md5' : "922f5cc42a25a02d0f737893836e89df", | |
} | |
], | |
'Atmel': [ | |
{ | |
'src' : "https://ww1.microchip.com/downloads/en/devicedoc/doc32000.pdf", | |
'idx' : "AVR32.idx", | |
'pdf' : "doc32000.pdf", | |
'md5' : "886df329eaf6fc184374a7e34cd7c6c6", | |
}, | |
{ | |
'src' : "http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf", | |
'idx' : "AVR8.idx", | |
'pdf' : "atmel-0856-avr-instruction-set-manual.pdf", | |
'md5' : "8e58b391f47a50a831d38a86655ad14d", | |
} | |
], | |
'CR16': [ | |
{ | |
'src' : "https://dump.bitcheese.net/files/zujukix/Prog_16C.pdf", | |
'idx' : "CR16.idx", | |
'pdf' : "prog16c.pdf", | |
'md5' : "c05f0ef53c9c296272410e170d461cbb", | |
} | |
], | |
'HCS08': [ | |
{ | |
'src' : "https://www.nxp.com/docs/en/reference-manual/M68HC05TB.pdf", | |
'idx' : "HC05.idx", | |
'pdf' : "M68HC05TB.pdf", | |
'md5' : "da59a147fdcc43e128f229a557abc327", | |
}, | |
{ | |
'src' : "https://www.nxp.com/files-static/microcontrollers/doc/ref_manual/CPU08RM.pdf", | |
'idx' : "HC08.idx", | |
'pdf' : "CPU08RM.pdf", | |
'md5' : "32ee09771ebb3b9d8689a509555ecd21", | |
}, | |
{ | |
'src' : "https://www.nxp.com/files-static/microcontrollers/doc/ref_manual/HCS08RMV1.pdf", | |
'idx' : "HCS08.idx", | |
'pdf' : "HCS08RMV1.pdf", | |
'md5' : "b31789f3d1d6df8027479c57e0ce53b5", | |
} | |
], | |
'HCS12': [ | |
{ | |
#need to register to obtain that link | |
'src' : "https://www.nxp.com/webapp/Download?colCode=CPU12/CPU12X&location=null", | |
'idx' : "HCS12.idx", | |
'pdf' : "S12XCPUV2.pdf", | |
'md5' : "611672bd85e5ddac66e2cf77d8f46f04", | |
'auth' : True | |
} | |
], | |
'JVM': [ | |
{ | |
'src' : "https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf", | |
'idx' : "JVM.idx", | |
'pdf' : "jvms8.pdf", | |
'md5' : "7665578d886f6d02952137e97d38e8ae", | |
'align' : False, | |
} | |
], | |
'MCS96': [ | |
{ | |
'src' : "http://bitsavers.trailing-edge.com/components/intel/_dataBooks/1991_Intel_16-Bit_Embedded_Controller_Handbook.pdf", | |
'idx' : "MCS96.idx", | |
'pdf' : "1991_Intel_16-Bit_Embedded_Controller_Handbook.pdf", | |
'md5' : "6abaf624673b5307fed14ab99012f135", | |
} | |
], | |
'MIPS': [ | |
{ | |
'src' : "https://scc.ustc.edu.cn/zlsc/lxwycj/200910/W020100308600769158777.pdf", | |
'idx' : "MIPS.idx", | |
'pdf' : "mips64v2.pdf", | |
'md5' : "b3cf0d829ab26af2e38d5735ae4e307f", | |
'align' : False, | |
}, | |
{ | |
'src' : "https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00087-2B-MIPS64BIS-AFP-6.06.pdf", | |
'idx' : "mipsM16.idx", | |
'pdf' : "MD00087-2B-MIPS64BIS-AFP-6.06.pdf", | |
'md5' : "da2d12cddfb7e7c57bedbed385abf9b1", | |
}, | |
#Exactly the same file for this idx | |
# { | |
# 'src' : "https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00087-2B-MIPS64BIS-AFP-6.06.pdf", | |
# 'idx' : "mipsMic.idx", | |
# 'pdf' : "MD00087-2B-MIPS64BIS-AFP-6.06.pdf", | |
# 'md5' : "da2d12cddfb7e7c57bedbed385abf9b1", | |
# }, | |
{ | |
'src' : "https://groups.csail.mit.edu/cag/raw/documents/R4400_Uman_book_Ed2.pdf", | |
'idx' : "r4000.idx", | |
'pdf' : "r4000.pdf", | |
'md5' : "5fb145391e449725c38d362780d104f5", | |
}, | |
], | |
'PA-RISC': [ | |
{ | |
'src' : "http://ftp.parisc-linux.org/docs/arch/pa11_acd.pdf", | |
'idx' : "pa11_acd.idx", | |
'pdf' : "pa11_acd.pdf", | |
'md5' : "1b7616419648bd55389ba64b7b499203", | |
} | |
], | |
'PIC': [ | |
{ | |
'src' : "https://ww1.microchip.com/downloads/en/devicedoc/40139e.pdf", | |
'idx' : "PIC-12.idx", | |
'pdf' : "PIC12_40139e.pdf", | |
'md5' : "a02061138f2cea8d4796c8263f2b34e5", | |
}, | |
{ | |
'src' : "https://ww1.microchip.com/downloads/en/DeviceDoc/40001761E.pdf", | |
'idx' : "PIC-16F.idx", | |
'pdf' : "PIC16F_40001761E.pdf", | |
'md5' : "450a29a5968b35525d2b3e740de2b912", | |
}, | |
{ | |
'src' : "https://ww1.microchip.com/downloads/en/devicedoc/33023a.pdf", | |
'idx' : "PIC-16.idx", | |
'pdf' : "PIC16_33023a.pdf", | |
'md5' : "13f70dba170f82edeae808f9150cf18a", | |
}, | |
{ | |
'src' : "https://ww1.microchip.com/downloads/en/devicedoc/30289b.pdf", | |
'idx' : "PIC-17.idx", | |
'pdf' : "PIC17_30289b.pdf", | |
'md5' : "e39da5d29ef2e86d6f69373cde367fbc", | |
}, | |
{ | |
'src' : "https://www.farnell.com/datasheets/14702.pdf", | |
'idx' : "PIC-18.idx", | |
'pdf' : "PIC18_14702.pdf", | |
'md5' : "9ecb61cb746febec0dddc5ec238bbc81", | |
}, | |
{ | |
'src' : "https://ww1.microchip.com/downloads/en/DeviceDoc/70157D.pdf", | |
'idx' : "PIC24.idx", | |
'pdf' : "PIC24_70157D.pdf", | |
'md5' : "fa5224ed0b19503a2bef2b1b2dc9a048", | |
'align' : False, | |
}, | |
], | |
'PowerPC': [ | |
{ | |
#Description is wrong in 9.1.2 code | |
#more recent here but index on first : http://kib.kiev.ua/x86docs/POWER/PowerISA_V2.06B_V2_PUBLIC.pdf | |
'src' : "https://wiki.raptorcs.com/w/images/1/1a/PowerISA_V2.06_PUBLIC.pdf", | |
'idx' : "PowerISA.idx", | |
'pdf' : "PowerISA_V2.06_PUBLIC.pdf", | |
'md5' : "13eca45bbea1025adc4ccf2384a56334", | |
'align' : False, | |
}, | |
{ | |
'src' : "https://wiki.alcf.anl.gov/images/f/fb/PowerPC_-_Assembly_-_IBM_Programming_Environment_2.3.pdf", | |
'idx' : "PowerPC.idx", | |
'pdf' : "powerpc.pdf", | |
'md5' : "da742a9f2978c01702581f15a290c577", | |
} | |
], | |
'Sparc': [ | |
{ | |
'src' : "https://cr.yp.to/2005-590/sparcv9.pdf", | |
'idx' : "Sparc.idx", | |
'pdf' : "SPARCV9.pdf", | |
'md5' : "8d38c4ff70204cd9056b3f040b100237", | |
}, | |
], | |
'SuperH4': [ | |
{ | |
'src' : "https://www.renesas.com/us/en/doc/products/mpumcu/001/rej09b0318_sh_4sm.pdf", | |
'idx' : "superh4.idx", | |
'pdf' : "rej09b0318_sh_4sm.pdf", | |
'md5' : "4757198e1bb055fa1a3438ca29918b36", | |
}, | |
], | |
'TI_MSP430': [ | |
{ | |
'src' : "https://e2echina.ti.com/cfs-file/__key/telligent-evolution-components-attachments/00-55-01-00-00-00-61-61/MSP430x2xx-Family-User_26002300_39_3B00_s-Guide-_2800_Rev.-E_2900_.pdf", | |
'idx' : "MSP430.idx", | |
'pdf' : "MSP430.pdf", | |
'md5' : "e7b8c653dfae7080a8edee3428aea8ed", | |
}, | |
], | |
'tricore': [ | |
{ | |
'src' : "https://www.infineon.com/dgdl/tc_v131_instructionset_v138.pdf?fileId=db3a304412b407950112b409b6dd0352", | |
'idx' : "tricore.idx", | |
'pdf' : "tc_v131_instructionset_v138.pdf", | |
'md5' : "f1cb5be4e5ba4d614fe7b11313a5b618", | |
}, | |
{ | |
'src' : "https://www.infineon.com/dgdl/Infineon-TC2xx_Architecture_vol2-UM-v01_00-EN.pdf?fileId=5546d46269bda8df0169ca1bf33124a8", | |
'idx' : "tricore2.idx", | |
'pdf' : "Infineon-TC2xx_Architecture_vol2-UM-v01_00-EN.pdf", | |
'md5' : "6a6ceb94889dfba302d8d8cb1bdc2edf", | |
'align' : False, | |
}, | |
], | |
'x86': [ | |
{ | |
'src' : "https://community.intel.com/legacyfs/online/drupal_files/managed/a4/60/325383-sdm-vol-2abcd.pdf", | |
'idx' : "x86.idx", | |
'pdf' : "325383-sdm-vol-2abcd.pdf", | |
'md5' : "063a8e1060e07bb646cccdb49814a0ed", | |
}, | |
], | |
'Z80': [ | |
{ | |
'src' : "http://z80.info/zip/z80cpu_um.pdf", | |
'idx' : "Z80.idx", | |
'pdf' : "UM0080.pdf", | |
'md5' : "6e131738b09d5b30b4d7096bc5092ca5", | |
}, | |
{ | |
'src' : "http://www.bitsavers.org/components/zilog/z180/UM005003-0703_Z8018x_User_Manual_2003.pdf", | |
'idx' : "Z180.idx", | |
'pdf' : "um0050.pdf", | |
'md5' : "e8a08e055d28aacff8acb9fe56f260ce", | |
'align' : False, | |
}, | |
], | |
} | |
def download_file(name, url, fname, md5hash, wget=False) : | |
try: | |
print("Downloading \"%s\" manual into %s" % (name, fname)) | |
f = open(fname, "wb") | |
req = request.Request( | |
url, | |
data=None, | |
headers={ | |
'User-Agent': 'Wget/1.20.3 (linux-gnu)', | |
### 'Accept' : '*.*' | |
}, | |
) | |
infile = request.urlopen(req) | |
while True: | |
buf = infile.read(4096) | |
if not buf: | |
break | |
f.write(buf) | |
f.close() | |
md5_download = binascii.hexlify(md5(open(cache_file, "rb").read()).digest()).decode() | |
if md5_download != md5hash: | |
raise Exception("md5 hash of downloaded file does not match") | |
except: | |
print_error('Could not download file...\n') | |
traceback.print_exc() | |
if os.path.exists(fname): | |
os.unlink(fname) | |
return False | |
return True | |
if __name__ == "__main__": | |
try: | |
version = "" | |
app_prop = os.path.join(ghidra_folder, "application.properties") | |
if not os.path.exists(app_prop): | |
print_warning("application.properties file not found, ghidra version may not be compatible") | |
else: | |
for line in open(app_prop, "r"): | |
if line.startswith("application.version="): | |
version = line.split("=")[1].strip() | |
if version != supported_version: | |
print_error("Version mismatch, this script may not work : %s / %s" % (version, supported_version)) | |
else: | |
print_success("Correct version of ghidra detected : %s" % version) | |
basepath = os.path.dirname(__file__) | |
cache = os.path.join(basepath, "cache") | |
if not os.path.exists(cache): | |
os.mkdir(cache) | |
for l in manuals.keys(): | |
print("Processor : %s" % l ) | |
for m in manuals[l]: | |
pdf_name = m['pdf'] | |
pdf = os.path.join(ghidra_folder, "Processors", l, "data/manuals", pdf_name) | |
idx_path = os.path.join(ghidra_folder, "Processors", l, "data/manuals", m['idx']) | |
if not os.path.exists(idx_path): | |
print_error("Index file not found : %s, skipping" % idx_path) | |
continue | |
#@SPARCV9.pdf[The SPARC Architecture Manual, Version 9 (SAV09R1459912)] | |
pdf_header = open(idx_path, "r").readline().split('[')[0][1:].strip() | |
title_name = open(idx_path, "r").readline().split('[')[1].replace(']','').strip() | |
if pdf_name != pdf_header: | |
print_error("pdf name in index is different : %s / %s" % (pdf_name, pdf_header)) | |
continue | |
if not force and os.path.exists(pdf): | |
print_warning("manual file already exists, skipping : %s" % pdf) | |
continue | |
elif force and os.path.exists(pdf): | |
os.unlink(pdf) | |
cache_file = os.path.join(cache, pdf_name) | |
if not os.path.exists(cache_file): | |
url = m['src'] | |
if 'auth' in m.keys() and m['auth']: | |
print_error("%s requires authentification and has to be manually downloaded and copy in ./cache/%s from : %s" % (title_name, pdf_name, url)) | |
continue | |
if not download_file(title_name, url, cache_file, m['md5']): | |
print_error("Error while downloading manual from : %s" % url) | |
continue | |
else: | |
print("%s file exists in cache, using it..." % pdf_name) | |
else: | |
md5_cache = binascii.hexlify(md5(open(cache_file, "rb").read()).digest()).decode() | |
if md5_cache != m['md5']: | |
print_error("md5 sum of cache file %s mismatch: %s / %s" % (cache_file, md5_cache, m['md5'])) | |
continue | |
copyfile(cache_file, pdf) | |
print_success("Manual deployed in %s" % pdf) | |
if 'align' in m.keys() and not m['align']: | |
print_warning("REM : This version of the pdf doesnt align with the idx, please provide correct link if you find one maching") | |
except: | |
print_error("Error in main, ..") | |
traceback.print_exc() | |
sys.exit() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment