Skip to content

Instantly share code, notes, and snippets.

@astarasikov
Last active April 19, 2024 20:53
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save astarasikov/f47cb7f46b5193872f376fa0ea842e4b to your computer and use it in GitHub Desktop.
Save astarasikov/f47cb7f46b5193872f376fa0ea842e4b to your computer and use it in GitHub Desktop.
Exynos9820 TEEGRIS TZAR unpack script
#!/usr/bin/env python3
# Usage: python convert_teegris_tas.py ~/Downloads/sw/pda/s10/fw/fw_G973FXXU4BTA8/AP/vendor/tee/
import os
import sys
from textwrap import wrap
def teegris_ta_to_elf(path_from, path_to):
with open(path_from, 'rb') as fin:
with open(path_to, 'wb') as fout:
fin_dat = fin.read()
if len(fin_dat) < 8:
return
fout.write(fin_dat[8:])
def hex_to_char(hex_str):
char = chr(int(hex_str, 16))
if char.isalnum():
return char
return '_'
def walk_rename(dir):
for currentpath, folders, files in os.walk(dir):
for file in files:
print(currentpath + ' => ' + file)
# UUID-like
if '-0000-0000-0000-' in file and '.elf' not in file:
components = file.split('-')
print(components)
last_component = components[-1]
if len(last_component) >= 12:
lc_hex_substr = last_component[:12]
lc_hex_comps = wrap(lc_hex_substr, 2)
lc_ascii_comps = map(hex_to_char, lc_hex_comps)
lc_new_string = str.join('', lc_ascii_comps)
new_path = '{}.{}.elf'.format(file, lc_new_string)
print(new_path)
teegris_ta_to_elf(os.path.join(currentpath, file), os.path.join(currentpath, new_path))
def main():
if len(sys.argv) < 2:
print("Usage: {} path_to_dir".format(sys.argv[0]))
return
walk_rename(sys.argv[1])
if __name__ == '__main__':
main()
Exynos9820 G973F Galaxy S10 BL partition layout (s-boot).
0x0: EPBL
0x13C00: ACPM
0x27800: some PM-related code
0x4CC00: some tables with PM parameters
... -> either charger mode code or PMIC firmware
0xA4000: BL2, the actual s-boot
0x19E000: TEEGRIS SPKG (CSMC)
0x19E02B: TEEGRIS SPKG ELF start (cut from here to load into the dissasembler)
This probably stands for "Crypto SMC" or "Checkpoint SMC".
This handles SMC calls.
1ACE00: TEEGRIS SPKG (FP_CSMC)
0x1ACE2B: TEEGRIS SPKG ELF
My guess is that it's related to the Fingerprint sensor because all it does
is set some registers in the GPIO block and USI block (whatever it is).
0x264000: TEEGRIS kernel, relocate to 0xfffffffff0000000 to resolve relocations
0x29e000: EL1 VBAR for TEEGRIS kernel?
fffffffff0041630: syscall table, first entry is zero.
Don't ask me how I figured it out.
To find out which syscall each entry corresponds to, we need to
0x2D4000: startup_loader package
0x2D4028: startup_loader ELF start
1f 20 03 d5 -> a long sequence of NOPs indicates AArch64 Exception Table
"\x00\xc0\x1e\xd5" -> MSR VBAR_EL3, X0; helpful to find the Exception Table
.
└── bin
├── 00000005-0005-0005-0505-050505050505
├── 00000007-0007-0007-0707-070707070707
├── aarch64
│   ├── libc++.so
│   ├── libdlmsl.so
│   ├── libmath.so
│   ├── libpthread.so
│   ├── libringbuf.so
│   ├── librootcert.so
│   ├── libscrypto.so
│   ├── libtee_debugsl.so
│   ├── libteesl.so
│   ├── libtui.so
│   └── libtzsl.so
├── arm
│   ├── libc++.so
│   ├── libdlmsl.so
│   ├── libmath.so
│   ├── libpthread.so
│   ├── libringbuf.so
│   ├── librootcert.so
│   ├── libscrypto.so
│   ├── libtee_debugsl.so
│   ├── libteesl.so
│   ├── libtui.so
│   └── libtzsl.so
├── libtzld.so
├── libtzld64.so
└── root_task
#!/usr/bin/env python3
import struct
import os
from pathlib import Path
def unpack_one_file(fin, dir_out):
file_hdr = fin.read(8)
(fname_len, fdata_len) = struct.unpack('ii', file_hdr)
fname = fin.read(fname_len)
fdata = fin.read(fdata_len)
fname = fname[0:fname_len-1]
fname = fname.decode("utf-8")
if fname[0] == '/':
fname = '.' + fname
print("File name %s length=%d" % (fname, fdata_len))
path_dir = Path(fname).parent
unpack_dir = os.path.join(dir_out, path_dir)
out_fname = os.path.join(dir_out, fname)
try:
os.makedirs(unpack_dir)
except FileExistsError as e:
pass
with open(out_fname, "wb") as fout:
fout.write(fdata)
def unpack_files(fin, num_files, dir_out):
for i in range(num_files):
unpack_one_file(fin, dir_out)
def unpack_tzar(fname, dir_out):
with open(fname, "rb") as fin:
hdr = fin.read(16)
(magic, tzar_count, tzar_len, tzar_num_files) = struct.unpack('iiii', hdr)
print(hex(magic))
print("Total number of files: " + str(tzar_num_files))
unpack_files(fin, tzar_num_files, dir_out)
if __name__ == "__main__":
fname_in = "startup.tzar"
dir_out = "tzar_out"
unpack_tzar(fname_in, dir_out)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment