├── scripts
├── loaders
│ ├── Ghidra
│ │ ├── mclfloader
│ │ │ ├── Module.manifest
│ │ │ ├── ghidra_scripts
│ │ │ │ └── README.txt
│ │ │ ├── .gitignore
│ │ │ ├── src
│ │ │ │ ├── main
│ │ │ │ │ ├── resources
│ │ │ │ │ │ └── images
│ │ │ │ │ │ │ └── README.txt
│ │ │ │ │ ├── help
│ │ │ │ │ │ └── help
│ │ │ │ │ │ │ ├── topics
│ │ │ │ │ │ │ └── mclfloader
│ │ │ │ │ │ │ │ └── help.html
│ │ │ │ │ │ │ ├── TOC_Source.xml
│ │ │ │ │ │ │ └── shared
│ │ │ │ │ │ │ └── Frontpage.css
│ │ │ │ │ └── java
│ │ │ │ │ │ └── mclfloader
│ │ │ │ │ │ ├── MCLFHeader.java
│ │ │ │ │ │ └── MCLFLoader.java
│ │ │ │ └── test
│ │ │ │ │ └── java
│ │ │ │ │ └── README.test.txt
│ │ │ ├── extension.properties
│ │ │ ├── dist
│ │ │ │ └── ghidra_9.1-BETA_DEV_20190926_mclfloader.zip
│ │ │ ├── lib
│ │ │ │ └── README.txt
│ │ │ ├── os
│ │ │ │ ├── linux64
│ │ │ │ │ └── README.txt
│ │ │ │ ├── osx64
│ │ │ │ │ └── README.txt
│ │ │ │ └── win64
│ │ │ │ │ └── README.txt
│ │ │ ├── data
│ │ │ │ └── README.txt
│ │ │ └── build.gradle
│ │ └── tbaseloader
│ │ │ ├── Module.manifest
│ │ │ ├── ghidra_scripts
│ │ │ └── README.txt
│ │ │ ├── .gitignore
│ │ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── resources
│ │ │ │ │ └── images
│ │ │ │ │ │ └── README.txt
│ │ │ │ ├── help
│ │ │ │ │ └── help
│ │ │ │ │ │ ├── topics
│ │ │ │ │ │ └── tbaseloader
│ │ │ │ │ │ │ └── help.html
│ │ │ │ │ │ ├── TOC_Source.xml
│ │ │ │ │ │ └── shared
│ │ │ │ │ │ └── Frontpage.css
│ │ │ │ └── java
│ │ │ │ │ └── tbaseloader
│ │ │ │ │ └── TBaseLoader.java
│ │ │ └── test
│ │ │ │ └── java
│ │ │ │ └── README.test.txt
│ │ │ ├── extension.properties
│ │ │ ├── dist
│ │ │ └── ghidra_9.1-BETA_DEV_20190926_tbaseloader.zip
│ │ │ ├── lib
│ │ │ └── README.txt
│ │ │ ├── os
│ │ │ ├── linux64
│ │ │ │ └── README.txt
│ │ │ ├── osx64
│ │ │ │ └── README.txt
│ │ │ └── win64
│ │ │ │ └── README.txt
│ │ │ ├── data
│ │ │ └── README.txt
│ │ │ └── build.gradle
│ └── IDAPro
│ │ ├── mclf_loader.py
│ │ └── tbase_loader.py
├── README.md
└── scripts
│ ├── Ghidra
│ ├── tl_apis.json
│ ├── FindSymbols.py
│ ├── dr_apis.json
│ └── FindSymbolsMcLib.py
│ └── IDAPro
│ ├── tl_apis.json
│ ├── dr_apis.json
│ ├── find_symbols.py
│ └── find_symbols_mclib.py
├── tainting
├── .gitignore
├── README.md
├── mclf2elf
│ ├── mclf.py
│ └── mclf2elf.py
└── tainter.py
├── bindings
├── .gitignore
├── bin
│ └── pymcclient
├── mcclient
│ ├── __init__.py
│ ├── __main__.py
│ ├── mcclient_const.py
│ ├── mcclient_types.py
│ └── mcclient.py
├── docs
│ ├── Makefile
│ ├── make.bat
│ ├── index.rst
│ └── conf.py
├── test
│ └── test.py
├── setup.py
├── COMPILING.md
└── README.md
├── emulator
├── README.md
└── emulator.py
├── fuzzer
├── README.md
└── fuzzer.py
├── README.md
└── LICENSE.md
/scripts/loaders/Ghidra/mclfloader/Module.manifest:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/Module.manifest:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tainting/.gitignore:
--------------------------------------------------------------------------------
1 | **/mcore_*/
2 | **/coverage*
3 |
--------------------------------------------------------------------------------
/bindings/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | dist/
3 | pymcclient.egg-info/
4 | docs/_build/
5 |
--------------------------------------------------------------------------------
/bindings/bin/pymcclient:
--------------------------------------------------------------------------------
1 | from mcclient import __main__
2 |
3 | __main__.main()
4 |
--------------------------------------------------------------------------------
/bindings/mcclient/__init__.py:
--------------------------------------------------------------------------------
1 | from .mcclient import Error, Device, Trustlet, Buffer
2 | from .mcclient_const import *
3 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/ghidra_scripts/README.txt:
--------------------------------------------------------------------------------
1 | Java source directory to hold module-specific Ghidra scripts.
2 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/ghidra_scripts/README.txt:
--------------------------------------------------------------------------------
1 | Java source directory to hold module-specific Ghidra scripts.
2 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/.gitignore:
--------------------------------------------------------------------------------
1 | .*
2 | *.zip
3 | !dist/*.zip
4 | *.jar
5 | *.log
6 | *.class
7 | bin/*
8 | build/*
9 | !/.gitignore
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/.gitignore:
--------------------------------------------------------------------------------
1 | .*
2 | *.zip
3 | !dist/*.zip
4 | *.jar
5 | *.log
6 | *.class
7 | bin/*
8 | build/*
9 | !/.gitignore
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/src/main/resources/images/README.txt:
--------------------------------------------------------------------------------
1 | The "src/resources/images" directory is intended to hold all image/icon files used by
2 | this module.
3 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/src/main/resources/images/README.txt:
--------------------------------------------------------------------------------
1 | The "src/resources/images" directory is intended to hold all image/icon files used by
2 | this module.
3 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/extension.properties:
--------------------------------------------------------------------------------
1 | name=@extname@
2 | description=The extension description can be customized by editing the extension.properties file.
3 | author=
4 | createdOn=
5 | version=@extversion@
6 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/src/test/java/README.test.txt:
--------------------------------------------------------------------------------
1 | The "test" directory is intended to hold unit test cases. The package structure within
2 | this folder should correspond to that found in the "src" folder.
3 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/extension.properties:
--------------------------------------------------------------------------------
1 | name=@extname@
2 | description=The extension description can be customized by editing the extension.properties file.
3 | author=
4 | createdOn=
5 | version=@extversion@
6 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/src/test/java/README.test.txt:
--------------------------------------------------------------------------------
1 | The "test" directory is intended to hold unit test cases. The package structure within
2 | this folder should correspond to that found in the "src" folder.
3 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/dist/ghidra_9.1-BETA_DEV_20190926_mclfloader.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quarkslab/samsung-trustzone-research/HEAD/scripts/loaders/Ghidra/mclfloader/dist/ghidra_9.1-BETA_DEV_20190926_mclfloader.zip
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/lib/README.txt:
--------------------------------------------------------------------------------
1 | The "lib" directory is intended to hold Jar files which this module
2 | is dependent upon. This directory may be eliminated from a specific
3 | module if no other Jar files are needed.
4 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/dist/ghidra_9.1-BETA_DEV_20190926_tbaseloader.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quarkslab/samsung-trustzone-research/HEAD/scripts/loaders/Ghidra/tbaseloader/dist/ghidra_9.1-BETA_DEV_20190926_tbaseloader.zip
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/lib/README.txt:
--------------------------------------------------------------------------------
1 | The "lib" directory is intended to hold Jar files which this module
2 | is dependent upon. This directory may be eliminated from a specific
3 | module if no other Jar files are needed.
4 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/os/linux64/README.txt:
--------------------------------------------------------------------------------
1 | The "os/linux64" directory is intended to hold Linux native binaries
2 | which this module is dependent upon. This directory may be eliminated for a specific
3 | module if native binaries are not provided for the corresponding platform.
4 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/os/osx64/README.txt:
--------------------------------------------------------------------------------
1 | The "os/osx64" directory is intended to hold macOS (OS X) native binaries
2 | which this module is dependent upon. This directory may be eliminated for a specific
3 | module if native binaries are not provided for the corresponding platform.
4 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/os/linux64/README.txt:
--------------------------------------------------------------------------------
1 | The "os/linux64" directory is intended to hold Linux native binaries
2 | which this module is dependent upon. This directory may be eliminated for a specific
3 | module if native binaries are not provided for the corresponding platform.
4 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/os/osx64/README.txt:
--------------------------------------------------------------------------------
1 | The "os/osx64" directory is intended to hold macOS (OS X) native binaries
2 | which this module is dependent upon. This directory may be eliminated for a specific
3 | module if native binaries are not provided for the corresponding platform.
4 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/os/win64/README.txt:
--------------------------------------------------------------------------------
1 | The "os/win64" directory is intended to hold MS Windows native binaries (.exe)
2 | which this module is dependent upon. This directory may be eliminated for a specific
3 | module if native binaries are not provided for the corresponding platform.
4 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/os/win64/README.txt:
--------------------------------------------------------------------------------
1 | The "os/win64" directory is intended to hold MS Windows native binaries (.exe)
2 | which this module is dependent upon. This directory may be eliminated for a specific
3 | module if native binaries are not provided for the corresponding platform.
4 |
--------------------------------------------------------------------------------
/emulator/README.md:
--------------------------------------------------------------------------------
1 | # Emulator
2 |
3 | This emulator is based on the [Unicorn](https://www.unicorn-engine.org/) engine. It allows executing trustlets and hooking the tlApis/drApis. It can also print the instructions executed, the register values and the content of the stack. It is especially useful to debug exploits for trustlets/drivers.
4 |
5 | ## Installation
6 |
7 | Simply install Unicorn and its Python bindings, are you're all good to go!
8 |
--------------------------------------------------------------------------------
/bindings/mcclient/__main__.py:
--------------------------------------------------------------------------------
1 | from IPython.terminal.embed import InteractiveShellEmbed
2 |
3 | from . import mcclient
4 |
5 |
6 | def main():
7 | banner = "Welcome to the Python mcClient API shell!\n\n"
8 | banner += "(check out the documentation to get started)\n"
9 |
10 | imcsh = InteractiveShellEmbed(banner1=banner, exit_msg="Bye o/\n")
11 | imcsh(local_ns={name: getattr(mcclient, name) for name in dir(mcclient)})
12 |
13 |
14 | if __name__ == "__main__":
15 | main()
16 |
--------------------------------------------------------------------------------
/fuzzer/README.md:
--------------------------------------------------------------------------------
1 | # Fuzzer
2 |
3 | This fuzzer is based on the [`afl-unicorn`](https://github.com/Battelle/afl-unicorn) project. We have only made some slight changes to the emulator code: executing one instruction to start the forkserver, loading the input file and forcing a crash on errors.
4 |
5 | You will need to implement more tlApis/drApis if you intend to do some serious fuzzing, as we couldn't release ours.
6 |
7 | ## Installation
8 |
9 | Follow the instructions in [this blog-post](https://medium.com/hackernoon/afl-unicorn-fuzzing-arbitrary-binary-code-563ca28936bf) to get afl-unicorn up and running.
10 |
--------------------------------------------------------------------------------
/bindings/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SOURCEDIR = .
8 | BUILDDIR = _build
9 |
10 | # Put it first so that "make" without argument is like "make help".
11 | help:
12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13 |
14 | .PHONY: help Makefile
15 |
16 | # Catch-all target: route all unknown targets to Sphinx using the new
17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
18 | %: Makefile
19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/data/README.txt:
--------------------------------------------------------------------------------
1 | The "data" directory is intended to hold data files that will be used by this module and will
2 | not end up in the .jar file, but will be present in the zip or tar file. Typically, data
3 | files are placed here rather than in the resources directory if the user may need to edit them.
4 |
5 | An optional data/languages directory can exist for the purpose of containing various Sleigh language
6 | specification files and importer opinion files.
7 |
8 | The data/buildLanguage.xml is used for building the contents of the data/languages directory.
9 |
10 | The skel language definition has been commented-out within the skel.ldefs file so that the
11 | skeleton language does not show-up within Ghidra.
12 |
13 | See the Sleigh language documentation (docs/languages/index.html) for details Sleigh language
14 | specification syntax.
15 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/data/README.txt:
--------------------------------------------------------------------------------
1 | The "data" directory is intended to hold data files that will be used by this module and will
2 | not end up in the .jar file, but will be present in the zip or tar file. Typically, data
3 | files are placed here rather than in the resources directory if the user may need to edit them.
4 |
5 | An optional data/languages directory can exist for the purpose of containing various Sleigh language
6 | specification files and importer opinion files.
7 |
8 | The data/buildLanguage.xml is used for building the contents of the data/languages directory.
9 |
10 | The skel language definition has been commented-out within the skel.ldefs file so that the
11 | skeleton language does not show-up within Ghidra.
12 |
13 | See the Sleigh language documentation (docs/languages/index.html) for details Sleigh language
14 | specification syntax.
15 |
--------------------------------------------------------------------------------
/bindings/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/bindings/test/test.py:
--------------------------------------------------------------------------------
1 | from mcclient import *
2 |
3 | DEVICE_ID = DEVICE_ID_DEFAULT
4 | TCI_BUFFER_SIZE = 0x1000
5 |
6 | TRUSTLET_UUID = "ffffffff00000000000000000000000e"
7 | TRUSTLET_FILE = "/system/app/mcRegistry/%s.tlbin" % TRUSTLET_UUID
8 |
9 |
10 | def main():
11 | with Device(DEVICE_ID) as dev:
12 | print(dev.id)
13 | print(dev.version())
14 |
15 | with dev.buffer(TCI_BUFFER_SIZE) as tci:
16 | with open(TRUSTLET_FILE, "rb") as fd:
17 | buf = fd.read()
18 |
19 | with Trustlet(dev, tci, buf) as app:
20 | print(app.id)
21 | print(app.error())
22 |
23 | buf = dev.alloc(0x42)
24 | with app.share(buf) as info:
25 | print(info)
26 | dev.free(buf)
27 |
28 | tci.seek(0)
29 | tci.write_dword(1)
30 |
31 | app.notify()
32 | app.wait_notification()
33 |
34 | tci.seek(0)
35 | print(tci.read_dword())
36 |
37 |
38 | if __name__ == "__main__":
39 | main()
40 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/src/main/help/help/topics/mclfloader/help.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 | Skeleton Help File for a Module
13 |
14 |
15 |
16 |
17 |
Skeleton Help File for a Module
18 |
19 |
This is a simple skeleton help topic. For a better description of what should and should not
20 | go in here, see the "sample" Ghidra extension in the Extensions/Ghidra directory, or see your
21 | favorite help topic. In general, language modules do not have their own help topics.
This is a simple skeleton help topic. For a better description of what should and should not
20 | go in here, see the "sample" Ghidra extension in the Extensions/Ghidra directory, or see your
21 | favorite help topic. In general, language modules do not have their own help topics.
22 |
23 |
24 |
--------------------------------------------------------------------------------
/scripts/README.md:
--------------------------------------------------------------------------------
1 | # Scripts
2 |
3 | Here are the various IDA Pro/Ghidra extensions that we have developed.
4 |
5 | ## Loaders
6 |
7 | ## MCLF loader
8 |
9 | The MCLF loader allows loading trustlet/driver binaries in the MCLF file format.
10 |
11 | It parses the header, maps the segments, sets the entry point and renames the mcLib handler.
12 |
13 | - IDA Pro version is at `loaders/IDAPro/mclf_loader.py`
14 | - Ghidra version is in `loaders/Ghidra/mclfloader`
15 |
16 | ##
25 | ```
26 |
27 | ### Tainting a trustlet
28 |
29 | Then we can use the script to perform the symbolic execution of the trustlet binary.
30 |
31 | ```
32 | python tainter.py -s .elf
33 | ```
34 |
35 | Note: use `-v` to display Manticore debug messages.
36 |
37 | ### Exporting coverage
38 |
39 | Use the `-c` flag to write coverage to a file on the disk.
40 |
41 | Use [Lighthouse](https://github.com/gaasedelen/lighthouse) to display coverage into IDA Pro.
42 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/build.gradle:
--------------------------------------------------------------------------------
1 | // Builds a Ghidra Extension for a given Ghidra installation.
2 | //
3 | // An absolute path to the Ghidra installation directory must be supplied either by setting the
4 | // GHIDRA_INSTALL_DIR environment variable or Gradle project property:
5 | //
6 | // > export GHIDRA_INSTALL_DIR=
7 | // > gradle
8 | //
9 | // or
10 | //
11 | // > gradle -PGHIDRA_INSTALL_DIR=
12 | //
13 | // Gradle should be invoked from the directory of the project to build. Please see the
14 | // application.gradle.version property in /Ghidra/application.properties
15 | // for the correction version of Gradle to use for the Ghidra installation you specify.
16 |
17 | //----------------------START "DO NOT MODIFY" SECTION------------------------------
18 | def ghidraInstallDir
19 |
20 | if (System.env.GHIDRA_INSTALL_DIR) {
21 | ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR
22 | }
23 | else if (project.hasProperty("GHIDRA_INSTALL_DIR")) {
24 | ghidraInstallDir = project.getProperty("GHIDRA_INSTALL_DIR")
25 | }
26 |
27 | if (ghidraInstallDir) {
28 | apply from: new File(ghidraInstallDir).getCanonicalPath() + "/support/buildExtension.gradle"
29 | }
30 | else {
31 | throw new GradleException("GHIDRA_INSTALL_DIR is not defined!")
32 | }
33 | //----------------------END "DO NOT MODIFY" SECTION-------------------------------
34 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/build.gradle:
--------------------------------------------------------------------------------
1 | // Builds a Ghidra Extension for a given Ghidra installation.
2 | //
3 | // An absolute path to the Ghidra installation directory must be supplied either by setting the
4 | // GHIDRA_INSTALL_DIR environment variable or Gradle project property:
5 | //
6 | // > export GHIDRA_INSTALL_DIR=
7 | // > gradle
8 | //
9 | // or
10 | //
11 | // > gradle -PGHIDRA_INSTALL_DIR=
12 | //
13 | // Gradle should be invoked from the directory of the project to build. Please see the
14 | // application.gradle.version property in /Ghidra/application.properties
15 | // for the correction version of Gradle to use for the Ghidra installation you specify.
16 |
17 | //----------------------START "DO NOT MODIFY" SECTION------------------------------
18 | def ghidraInstallDir
19 |
20 | if (System.env.GHIDRA_INSTALL_DIR) {
21 | ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR
22 | }
23 | else if (project.hasProperty("GHIDRA_INSTALL_DIR")) {
24 | ghidraInstallDir = project.getProperty("GHIDRA_INSTALL_DIR")
25 | }
26 |
27 | if (ghidraInstallDir) {
28 | apply from: new File(ghidraInstallDir).getCanonicalPath() + "/support/buildExtension.gradle"
29 | }
30 | else {
31 | throw new GradleException("GHIDRA_INSTALL_DIR is not defined!")
32 | }
33 | //----------------------END "DO NOT MODIFY" SECTION-------------------------------
34 |
--------------------------------------------------------------------------------
/bindings/setup.py:
--------------------------------------------------------------------------------
1 | # Always prefer setuptools over distutils
2 | from setuptools import setup
3 |
4 | # To use a consistent encoding
5 | from codecs import open
6 | import os
7 |
8 | here = os.path.abspath(os.path.dirname(__file__))
9 |
10 | # Get the long description from the README file
11 | with open(os.path.join(here, "README.md"), encoding="utf-8") as f:
12 | long_description = f.read()
13 |
14 |
15 | def get_packages(package):
16 | """
17 | Return root package and all sub-packages.
18 | """
19 | return [
20 | dirpath
21 | for dirpath, dirnames, filenames in os.walk(package)
22 | if os.path.exists(os.path.join(dirpath, "__init__.py"))
23 | ]
24 |
25 |
26 | setup(
27 | name="pymcclient",
28 | version="0.2.3",
29 | description="Python bindings for libMcClient",
30 | long_description=long_description,
31 | author="Alexandre Adamski",
32 | author_email="aadamski@quarkslab.com",
33 | license="BSD2",
34 | classifiers=[
35 | "Development Status :: 4 - Beta",
36 | "Intended Audience :: Black rats",
37 | "Topic :: Security :: Hack Tools",
38 | "License :: Theo Approved :: BSD2",
39 | "Programming Language :: Python :: 3",
40 | "Programming Language :: Python :: 3.7",
41 | ],
42 | keywords="android trustzone mobicore libmcclient bindings",
43 | packages=get_packages("mcclient"),
44 | install_requires=["ipython"],
45 | scripts=["bin/pymcclient"],
46 | )
47 |
--------------------------------------------------------------------------------
/bindings/COMPILING.md:
--------------------------------------------------------------------------------
1 | # Capstone/Keystone for Android
2 |
3 | Here are the commands we have used to compile Capstone/Keystone.
4 |
5 | ## Compiling
6 |
7 | ### Capstone
8 |
9 | ```
10 | git clone https://github.com/aquynh/capstone capstone && cd capstone
11 | mkdir build64 && cd build64
12 | cmake -DCMAKE_SYSTEM_NAME=Android -DCMAKE_ANDROID_NDK=/path/to/android-ndk -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release -G"Unix Makefiles" ..
13 | make -j8
14 | ```
15 |
16 | ### Keystone
17 |
18 | ```
19 | git clone https://github.com/keystone-engine keystone && cd keystone
20 | mkdir build64 && cd build64
21 | cmake -DCMAKE_SYSTEM_NAME=Android -DCMAKE_ANDROID_NDK=/path/to/android-ndk -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -G"Unix Makefiles" ..
22 | make -j8
23 | ```
24 |
25 | ## Installing
26 |
27 | Here are the commands we have used to install Capstone/Keystone.
28 |
29 | ### Capstone
30 |
31 | ```
32 | adb push capstone /data/local/tmp
33 | adb shell
34 | $ . /data/local/tmp/python3/tools/env.sh
35 | $ cd /data/local/tmp/capstone/bindings/python
36 | $ cp ../../build64/libcapstone.* prebuilt
37 | $ python3.7 setup.py install
38 | $ cd /data/local/tmp && rm -rf capstone
39 | ```
40 |
41 | ### Keystone
42 |
43 | ```
44 | adb push keystone /data/local/tmp
45 | adb shell
46 | $ . /data/local/tmppython3/tools/env.sh
47 | $ cd /data/local/tmp/keystone/bindings/python
48 | $ cp ../../build64/llvm/lib/libkeystone.so /data/local/tmp/python3/usr/lib
49 | $ python3.7 setup.py install
50 | $ cd /data/local/tmp && rm -rf keystone
51 | ```
52 |
--------------------------------------------------------------------------------
/bindings/README.md:
--------------------------------------------------------------------------------
1 | # Bindings
2 |
3 | ## Introduction
4 |
5 | Python bindings for `libMcClient.so`, the library that is used to communicate with Trusted Applications and Secure Drivers. The bindings can be used as a library, or we also offer a very practical REPL which is based on IPython.
6 |
7 | ## Installation
8 |
9 | First you will need to install Python 3 on your device. To do that we suggest you use the [`python3-android`](https://github.com/yan12125/python3-android) project by @[yan12125](https://github.com/yan12125). Then you can install `pip` on it using [`get-pip.py`](https://bootstrap.pypa.io/get-pip.py) and finally install IPython itself.
10 |
11 | If you're interested in compiling Keystone/Capstone for Android, check out [this guide](COMPILING.md).
12 |
13 | Installation of the project can be done from the sources
14 |
15 | ```
16 | $ python setup.py install
17 | ```
18 |
19 | ## Usage
20 |
21 | To start the REPL, simply enter
22 |
23 | ```
24 | $ pymcclient
25 | ```
26 |
27 | ## Example
28 |
29 | ```python
30 | from mcclient import *
31 |
32 | # Create a device session
33 | with Device() as dev:
34 |
35 | # Allocate a TCI buffer
36 | with dev.buffer(tci_size) as tci:
37 |
38 | # Create a trustlet session
39 | with Trustlet.uuid(dev, tci, uuid) as app:
40 |
41 | # Write the command ID
42 | tci.seek(0)
43 | tci.write_dword(42)
44 |
45 | # Notify the trustlet
46 | app.notify()
47 | # Wait for a notification
48 | app.wait_notification()
49 |
50 | # Display the TCI buffer
51 | tci.seek(0)
52 | tci.hexdump(0x100)
53 | ```
54 |
55 | Thanks to Python's context managers, the sessions are automatically closed and the buffers automatically freed when the "with statements" are exited.
56 |
57 | But you can still go the old fashioned way and call the `open` and `close` methods yourself.
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Security Research on Kinibi
2 |
3 | In this repository, you will find the tools that we have developed during our research to help us reverse engineer and also exploit Samsung's implementation of TrustZone, which is based on a Trusted OS called Kinibi.
4 |
5 | ## Bindings
6 |
7 | In the `bindings/` folder, you will find Python bindings for the `libMcClient.so` library that is used to communicate with Trusted Applications and Secure Drivers. They were developed because we found it easier to write our exploits in Python, and they proved especially useful for the exercises given during our training sessions.
8 |
9 | ## Emulator
10 |
11 | In the `emulator/` folder, you will find a Python script that makes use of the [Unicorn](https://www.unicorn-engine.org/) engine to emulate a trustlet. This tool was mainly used to test our exploits as it can print the instructions executed, register values and stack content.
12 |
13 | ## Fuzzer
14 |
15 | In the `fuzzer/` folder, you will find a Python script that makes use of the [`afl-unicorn`](https://github.com/Battelle/afl-unicorn) project to fuzz trustlets. It is heavily based on the emulator. You will need to implement more tlApis/drApis if you intend to do some serious fuzzing.
16 |
17 | ## Scripts
18 |
19 | In the `scripts/` folder, you will find various things:
20 | - `mclf_loader`, a loader for trustlet binaries using the MCLF file format
21 | - `tbase_loader`, a loader that extracts the various components of a SBOOT image
22 | - `find_symbols`, a script that finds and renames the various tlApis/drApis stubs within trustlets
23 | - `find_symbols_mclib`, a script that finds and renames the various tlApis/drApis functions within the McLib
24 |
25 | The scripts are available both for IDA Pro and Ghidra, as we wanted our trainees to be able to use a free SRE.
26 |
27 | ## Tainting
28 |
29 | In the `tainting/` folder, you will find a Python script that makes use of [Manticore](https://github.com/trailofbits/manticore) to find vulnerabilities in trustlets using symbolic execution. This was just an experiment, so the script is really basic.
30 |
31 | ## Contact
32 |
33 | - Alexandre Adamski <>
34 | - Joffrey Guilbon <>
35 | - Maxime Peterlin <>
36 |
--------------------------------------------------------------------------------
/tainting/mclf2elf/mclf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """
3 | Loader for TLBIN files (MCLF format)
4 |
5 | Layout:
6 | [HDR + textsz] - text, mapped at txt addr
7 | [datasz] - data, mapped at data addr
8 | [0 bytes] - bss, mapped at data addr + datasz ?
9 | [521 bytes] - sig, not mapped
10 | """
11 | import struct
12 |
13 | class Error(Exception) :
14 | pass
15 |
16 | class Readable(object) :
17 | def get(self, fmt, pos=None) :
18 | if pos is not None :
19 | self.f.seek(pos)
20 | sz = struct.calcsize(fmt)
21 | dat = self.f.read(sz)
22 | if len(dat) != sz :
23 | raise Error("short read")
24 | return struct.unpack('<' + fmt, dat)
25 | def __str__(self) :
26 | def fmt(x) :
27 | if isinstance(x, int) :
28 | return '0x%x' % x
29 | else :
30 | return repr(x)
31 | nms = self.__fields__.split(',')
32 | fs = ','.join('%s=%s' % (nm, fmt(getattr(self, nm))) for nm in nms)
33 | return '[%s %s]' % (self.__class__.__name__, fs)
34 | __repr__ = __str__
35 |
36 | class Segment(Readable) :
37 | __fields__ = 'start,len'
38 | def __init__(self, f) :
39 | self.f = f
40 | self.load()
41 | def load(self) :
42 | self.start, self.len = self.get('II')
43 |
44 | class MCLF(Readable) :
45 | __fields__ = 'mag,vmag,vmin,flags,memType,serviceType,ninstances,uuid,driverId,numThreads,text,data,bssLen,entry,serviceVersion'
46 | MAG = 'MCLF'
47 |
48 | def __init__(self, fn) :
49 | self.f = file(fn, 'rb')
50 | self.load()
51 |
52 | def getSegment(self) :
53 | return Segment(self.f)
54 |
55 | def loadV1(self) :
56 | self.flags,self.memType,self.serviceType,self.ninstances = self.get('IIII')
57 | self.uuid = self.get('16s')[0].encode('hex')
58 | self.driverId,self.numThreads = self.get('II')
59 | self.text = self.getSegment()
60 | self.data = self.getSegment()
61 | self.bssLen,self.entry = self.get('II')
62 | self.serviceVersion = None
63 |
64 | def loadV2(self) :
65 | self.serviceVersion = self.get('I')[0]
66 |
67 | def load(self) :
68 | self.mag,self.vmin,self.vmag = self.get("4sHH")
69 | if self.mag != self.MAG :
70 | raise Error("bad magic")
71 | if self.vmag < 1 :
72 | raise Error("unsupported version")
73 | if self.vmag >= 1 :
74 | self.loadV1()
75 | if self.vmag >= 2 :
76 | self.loadV2()
77 |
78 | def test() :
79 | import sys
80 | def sz(f) :
81 | f.seek(0, 2)
82 | return f.tell()
83 | for fn in sys.argv[1:] :
84 | print fn
85 | m = MCLF(fn)
86 | print m
87 | #print 'sz=%x xtra=%x' % (sz(m.f), sz(m.f) - (m.text.len + m.data.len))
88 | print
89 |
90 | if __name__ == '__main__' :
91 | test()
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/src/main/java/mclfloader/MCLFHeader.java:
--------------------------------------------------------------------------------
1 | package mclfloader;
2 |
3 | import java.io.IOException;
4 |
5 | import ghidra.app.util.bin.BinaryReader;
6 | import ghidra.app.util.bin.StructConverter;
7 | import ghidra.program.flatapi.FlatProgramAPI;
8 | import ghidra.program.model.address.Address;
9 | import ghidra.program.model.data.ArrayDataType;
10 | import ghidra.program.model.data.DataType;
11 | import ghidra.program.model.data.Structure;
12 | import ghidra.program.model.data.StructureDataType;
13 |
14 | public class MCLFHeader implements StructConverter {
15 | public String intro;
16 | public long version;
17 | public long flags;
18 | public long memType;
19 | public long serviceType;
20 | public long numInstances;
21 | public byte[] uuid;
22 | public long driverId;
23 | public long numThreads;
24 | public Address textVa;
25 | public long textLen;
26 | public Address dataVa;
27 | public long dataLen;
28 | public long bssLen;
29 | public Address entry;
30 | public long serviceVersion;
31 |
32 | public MCLFHeader(FlatProgramAPI api, BinaryReader reader) throws IOException {
33 | reader.setPointerIndex(0);
34 | intro = reader.readNextAsciiString(4);
35 | version = reader.readNextUnsignedInt();
36 | flags = reader.readNextUnsignedInt();
37 | memType = reader.readNextUnsignedInt();
38 | serviceType = reader.readNextUnsignedInt();
39 | numInstances = reader.readNextUnsignedInt();
40 | uuid = reader.readNextByteArray(16);
41 | driverId = reader.readNextUnsignedInt();
42 | numThreads = reader.readNextUnsignedInt();
43 | textVa = api.toAddr(reader.readNextUnsignedInt());
44 | textLen = reader.readNextUnsignedInt();
45 | dataVa = api.toAddr(reader.readNextUnsignedInt());
46 | dataLen = reader.readNextUnsignedInt();
47 | bssLen = reader.readNextUnsignedInt();
48 | entry = api.toAddr(reader.readNextUnsignedInt());
49 | serviceVersion = reader.readNextUnsignedInt();
50 | }
51 |
52 | @Override
53 | public DataType toDataType() {
54 | Structure struct = new StructureDataType("mclfHeader_t", 0);
55 | struct.add(ASCII, 4, "intro", null);
56 | struct.add(DWORD, 4, "version", null);
57 | struct.add(DWORD, 4, "flags", null);
58 | struct.add(DWORD, 4, "memType", null);
59 | struct.add(DWORD, 4, "serviceType", null);
60 | struct.add(DWORD, 4, "numInstances", null);
61 | struct.add(new ArrayDataType(BYTE, 16, 1), "uuid", null);
62 | struct.add(DWORD, 4, "driverId", null);
63 | struct.add(DWORD, 4, "numThreads", null);
64 | struct.add(POINTER, 4, "textVa", null);
65 | struct.add(DWORD, 4, "textLen", null);
66 | struct.add(POINTER, 4, "dataVa", null);
67 | struct.add(DWORD, 4, "dataLen", null);
68 | struct.add(DWORD, 4, "bssLen", null);
69 | struct.add(POINTER, 4, "entry", null);
70 | struct.add(DWORD, 4, "serviceVersion", null);
71 | return struct;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/src/main/help/help/TOC_Source.xml:
--------------------------------------------------------------------------------
1 |
2 |
49 |
50 |
51 |
52 |
57 |
58 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/src/main/help/help/TOC_Source.xml:
--------------------------------------------------------------------------------
1 |
2 |
49 |
50 |
51 |
52 |
57 |
58 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/src/main/help/help/shared/Frontpage.css:
--------------------------------------------------------------------------------
1 | /* ###
2 | * IP: GHIDRA
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /*
17 | WARNING!
18 | This file is copied to all help directories. If you change this file, you must copy it
19 | to each src/main/help/help/shared directory.
20 |
21 |
22 | Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but
23 | px (pixel) or with no type marking.
24 |
25 | */
26 |
27 | body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
28 | li { font-family:times new roman; font-size:14pt; }
29 | h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
30 | h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
31 | h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
32 | h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
33 |
34 | /*
35 | P tag code. Most of the help files nest P tags inside of blockquote tags (the was the
36 | way it had been done in the beginning). The net effect is that the text is indented. In
37 | modern HTML we would use CSS to do this. We need to support the Ghidra P tags, nested in
38 | blockquote tags, as well as naked P tags. The following two lines accomplish this. Note
39 | that the 'blockquote p' definition will inherit from the first 'p' definition.
40 | */
41 | p { margin-left: 40px; font-family:times new roman; font-size:14pt; }
42 | blockquote p { margin-left: 10px; }
43 |
44 | p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
45 | p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
46 | p.relatedtopic { color:#800080; margin-left: 10px; font-size:14pt; }
47 | p.RelatedTopic { color:#800080; margin-left: 10px; font-size:14pt; }
48 |
49 | /*
50 | We wish for a tables to have space between it and the preceding element, so that text
51 | is not too close to the top of the table. Also, nest the table a bit so that it is clear
52 | the table relates to the preceding text.
53 | */
54 | table { margin-left: 20px; margin-top: 10px; width: 80%;}
55 | td { font-family:times new roman; font-size:14pt; vertical-align: top; }
56 | th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
57 |
58 | code { color: black; font-family: courier new; font-size: 14pt; }
59 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/tbaseloader/src/main/help/help/shared/Frontpage.css:
--------------------------------------------------------------------------------
1 | /* ###
2 | * IP: GHIDRA
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /*
17 | WARNING!
18 | This file is copied to all help directories. If you change this file, you must copy it
19 | to each src/main/help/help/shared directory.
20 |
21 |
22 | Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but
23 | px (pixel) or with no type marking.
24 |
25 | */
26 |
27 | body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
28 | li { font-family:times new roman; font-size:14pt; }
29 | h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
30 | h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
31 | h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
32 | h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
33 |
34 | /*
35 | P tag code. Most of the help files nest P tags inside of blockquote tags (the was the
36 | way it had been done in the beginning). The net effect is that the text is indented. In
37 | modern HTML we would use CSS to do this. We need to support the Ghidra P tags, nested in
38 | blockquote tags, as well as naked P tags. The following two lines accomplish this. Note
39 | that the 'blockquote p' definition will inherit from the first 'p' definition.
40 | */
41 | p { margin-left: 40px; font-family:times new roman; font-size:14pt; }
42 | blockquote p { margin-left: 10px; }
43 |
44 | p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
45 | p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
46 | p.relatedtopic { color:#800080; margin-left: 10px; font-size:14pt; }
47 | p.RelatedTopic { color:#800080; margin-left: 10px; font-size:14pt; }
48 |
49 | /*
50 | We wish for a tables to have space between it and the preceding element, so that text
51 | is not too close to the top of the table. Also, nest the table a bit so that it is clear
52 | the table relates to the preceding text.
53 | */
54 | table { margin-left: 20px; margin-top: 10px; width: 80%;}
55 | td { font-family:times new roman; font-size:14pt; vertical-align: top; }
56 | th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
57 |
58 | code { color: black; font-family: courier new; font-size: 14pt; }
59 |
--------------------------------------------------------------------------------
/scripts/loaders/Ghidra/mclfloader/src/main/java/mclfloader/MCLFLoader.java:
--------------------------------------------------------------------------------
1 | package mclfloader;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.ArrayList;
6 | import java.util.Collection;
7 | import java.util.List;
8 |
9 | import ghidra.app.util.Option;
10 | import ghidra.app.util.bin.BinaryReader;
11 | import ghidra.app.util.bin.ByteProvider;
12 | import ghidra.app.util.importer.MessageLog;
13 | import ghidra.app.util.opinion.AbstractLibrarySupportLoader;
14 | import ghidra.app.util.opinion.LoadSpec;
15 | import ghidra.program.flatapi.FlatProgramAPI;
16 | import ghidra.program.model.address.Address;
17 | import ghidra.program.model.data.DataUtilities;
18 | import ghidra.program.model.data.DataUtilities.ClearDataMode;
19 | import ghidra.program.model.lang.LanguageCompilerSpecPair;
20 | import ghidra.program.model.listing.Program;
21 | import ghidra.program.model.mem.MemoryBlock;
22 | import ghidra.program.model.util.CodeUnitInsertionException;
23 | import ghidra.util.Msg;
24 | import ghidra.util.exception.CancelledException;
25 | import ghidra.util.task.TaskMonitor;
26 |
27 | public class MCLFLoader extends AbstractLibrarySupportLoader {
28 | public MCLFHeader header;
29 |
30 | @Override
31 | public String getName() {
32 | return "MobiCore Loadable Format (MCLF)";
33 | }
34 |
35 | @Override
36 | public Collection findSupportedLoadSpecs(ByteProvider provider) throws IOException {
37 | BinaryReader reader = new BinaryReader(provider, true);
38 | if (reader.readNextAsciiString(4).equals("MCLF"))
39 | return List.of(new LoadSpec(this, 0, new LanguageCompilerSpecPair("ARM:LE:32:v7", "default"), true));
40 | return new ArrayList<>();
41 | }
42 |
43 | @Override
44 | protected void load(ByteProvider provider, LoadSpec loadSpec, List