├── .gitignore
├── CS.py
├── KC.py
├── KM.py
├── KM_kernel.py
├── LICENSE
├── README.md
├── dwarf4_fix.py
├── extra_refs.py
├── fix_extMethod.py
├── fix_methodForIndex.py
├── jsymbols.py
├── load_sigatnures.py
├── load_structs.py
├── namespace.py
├── propagate.py
├── screenshots
├── image1.png
├── image10.png
├── image11.png
├── image12.png
├── image2.png
├── image3.png
├── image4.png
├── image5.png
├── image6.png
├── image7.png
├── image8.png
└── image9.png
├── signatures
├── IOBufferMemoryDescriptor.h
├── IOCommandGate.h
├── IODataQueue.h
├── IOEventSource.h
├── IOMemoryDescriptor.h
├── IOMemoryMap.h
├── IORegistryEntry.h
├── IOService.h
├── IOSharedDataQueue.h
├── IOUserClient.h
├── IOWorkLoop.h
├── OSArray.h
├── OSCollection.h
├── OSCollectionIterator.h
├── OSData.h
├── OSDictionary.h
├── OSMetaClassBase.h
├── OSNumber.h
├── OSObject.h
├── OSSerialize.h
├── OSSet.h
├── OSString.h
├── OSSymbol.h
└── kernel.h
└── utils
├── __init__.py
├── custom_kc.py
├── helpers.py
├── iometa.py
├── ios_kc.py
├── kext.py
├── methods.py
└── references.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | .DS_Store
3 | __pycache__/
4 | *.py[cod]
5 | *$py.class
6 |
7 | # C extensions
8 | *.so
9 |
10 | # Distribution / packaging
11 | .Python
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | pip-wheel-metadata/
25 | share/python-wheels/
26 | *.egg-info/
27 | .installed.cfg
28 | *.egg
29 | MANIFEST
30 |
31 | # PyInstaller
32 | # Usually these files are written by a python script from a template
33 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
34 | *.manifest
35 | *.spec
36 |
37 | # Installer logs
38 | pip-log.txt
39 | pip-delete-this-directory.txt
40 |
41 | # Unit test / coverage reports
42 | htmlcov/
43 | .tox/
44 | .nox/
45 | .coverage
46 | .coverage.*
47 | .cache
48 | nosetests.xml
49 | coverage.xml
50 | *.cover
51 | *.py,cover
52 | .hypothesis/
53 | .pytest_cache/
54 |
55 | # Translations
56 | *.mo
57 | *.pot
58 |
59 | # Django stuff:
60 | *.log
61 | local_settings.py
62 | db.sqlite3
63 | db.sqlite3-journal
64 |
65 | # Flask stuff:
66 | instance/
67 | .webassets-cache
68 |
69 | # Scrapy stuff:
70 | .scrapy
71 |
72 | # Sphinx documentation
73 | docs/_build/
74 |
75 | # PyBuilder
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | .python-version
87 |
88 | # pipenv
89 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
90 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
91 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
92 | # install all needed dependencies.
93 | #Pipfile.lock
94 |
95 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
96 | __pypackages__/
97 |
98 | # Celery stuff
99 | celerybeat-schedule
100 | celerybeat.pid
101 |
102 | # SageMath parsed files
103 | *.sage.py
104 |
105 | # Environments
106 | .env
107 | .venv
108 | env/
109 | venv/
110 | ENV/
111 | env.bak/
112 | venv.bak/
113 |
114 | # Spyder project settings
115 | .spyderproject
116 | .spyproject
117 |
118 | # Rope project settings
119 | .ropeproject
120 |
121 | # mkdocs documentation
122 | /site
123 |
124 | # mypy
125 | .mypy_cache/
126 | .dmypy.json
127 | dmypy.json
128 |
129 | # Pyre type checker
130 | .pyre/
131 |
--------------------------------------------------------------------------------
/CS.py:
--------------------------------------------------------------------------------
1 | # Create a custom class
2 | #@category iOS.kernel
3 |
4 | from utils.helpers import *
5 | from utils.custom_kc import *
6 |
7 | if __name__ == "__main__":
8 | default = "/tmp/kernel.txt"
9 | ff = askString("iometa symbol file","Symbol file: ",default)
10 | iom = ParseIOMeta(ff)
11 | Obj = iom.getObjects()
12 |
13 | kc = Custom(Obj)
14 |
15 | #kc.process_class(["IOSurface"])
16 |
17 | kc.process_all_classes()
18 | kc.explore_pac()
19 |
--------------------------------------------------------------------------------
/KC.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #@category iOS.kernel
3 | #@toolbar logos/kc.png
4 | #@keybinding Meta Shift K
5 |
6 | from utils.helpers import *
7 | from utils.ios_kc import *
8 | from utils.iometa import ParseIOMeta
9 |
10 | def fix_map():
11 | prog = currentProgram
12 | memory = prog.getMemory()
13 | blocks = memory.getBlocks()
14 | for b in blocks:
15 | if "__got" in b.getName():
16 | b.setWrite(False)
17 |
18 | def loadAll():
19 | default = "/tmp/kernel.txt"
20 | ff = askString("iometa symbol file","Symbol file: ",default)
21 |
22 | iom = ParseIOMeta(ff)
23 | Obj = iom.getObjects()
24 | kc = kernelCache(Obj)
25 |
26 | #kc.clear_class_structures()
27 |
28 | kc.process_all_classes()
29 |
30 | #kc.process_class("IOUserClient")
31 |
32 | #kc.process_classes_for_bundle("com.apple.iokit.IOSurface")
33 |
34 | #kc.explore_pac()
35 |
36 | if __name__ == "__main__":
37 | #DeclareDataTypes()
38 | prepare()
39 | #fix_map()
40 | loadAll()
41 |
--------------------------------------------------------------------------------
/KM.py:
--------------------------------------------------------------------------------
1 | # symbolication macOS kernel + kexts
2 | #@category iOS.kernel
3 | #@toolbar logos/km.png
4 | #@keybinding Meta Shift M
5 |
6 | from utils.helpers import *
7 | from utils.kext import *
8 |
9 | def main():
10 | default = "/tmp/kernel.txt"
11 | ff = askString("iometa symbol file","Symbol file: ",default)
12 | iom = ParseIOMeta(ff)
13 | Obj = iom.getObjects()
14 | #del Obj['OSKext']
15 |
16 | kc = Kext(Obj,shared_p="macOS_12.1")
17 | kc.depac()
18 | kc.process_kernel_kext()
19 |
20 | kc.explore_pac()
21 |
22 | if __name__ == "__main__":
23 | print("[+] Symbolicating Kext")
24 | main()
25 |
--------------------------------------------------------------------------------
/KM_kernel.py:
--------------------------------------------------------------------------------
1 | # symbolication macOS kernel + kexts
2 | #@category iOS.kernel
3 | #@toolbar logos/km.png
4 | #@keybinding Meta Shift M
5 |
6 | from utils.helpers import *
7 | from utils.kext import *
8 |
9 | def main():
10 | default = "/tmp/kernel.txt"
11 | ff = askString("iometa symbol file","Symbol file: ",default)
12 | iom = ParseIOMeta(ff)
13 | Obj = iom.getObjects()
14 |
15 | kc = Kext(Obj,shared_p="macOS_12.1")
16 |
17 | kc.process_kernel_kext()
18 |
19 | if __name__ == "__main__":
20 | print("Parsing 1 ... ")
21 | main()
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ghidra_kernelcache: a Ghidra iOS kernelcache framework for reverse engineering
2 |
3 | This framework is the end product of my experience in Kernelcache reverse engineering , I usually look for vulnerabilities by manually auditing the kernel and its extensions and have automated most of the things that I really wanted to see in Ghidra to speed up the process of reversing, and this has proven to be effective and saves a lot of time.
4 | The framework works on iOS 12/13/14/15 and on macOS 11/12 (both kernelcache and single KEXT) and has been made to the public with the intention to help people to start researching on iOS kernel without the struggle of preparing their own environment.
5 | As I believe, this framework (including the toolset it provides and with some basic knowledge of IOKit) is sufficient to start hacking into the Kernelcache.
6 |
7 | The framework is entirely written in Python, and can be extended to build other tools, it provides some basic APIs which you can use in almost any project and save time from reading the verbose manual, you're welcome to read the core functionalities in **[utils/](https://github.com/0x36/ghidra_kernelcache/tree/master/utils)** directory.
8 |
9 | Ghidra is good when it comes to analyzing Kernelcaches, but like other RE tools, it requires some manual work, `ghidra_kernelcache` provides a good entry point to fix things up at the start and even while doing reverse engineering, hence providing a good-looking decompiler output.
10 |
11 | There is a similar project made by [@_bazad](https://twitter.com/_bazad) in IDAPro called [ida_kernelcache](https://github.com/bazad/ida_kernelcache) which provides a good entry point for researchers wanting to work with the kernel image in IDA, my framework looks a bit similar to Brandon's work, and goes beyond by providing much more features to make the process of working with the kernelcache less painful.
12 |
13 | ## Features :
14 | - *OS kernelcache symbolication.
15 | - C++ class hierarchy reconstruction and virtual tables.
16 | - Virtual method call references.
17 | - Auto fixing external method's dispatch table for both `::externalMethod()` and `::getTargetAndMethodForIndex()`.
18 | - Applying namespaces to class methods.
19 | - Symbol name and type propagation over a function arguments.
20 | - Applying function signatures for known kernel functions.
21 | - Import old structures and classes from old project to a new project.
22 |
23 | These features are made as a separated tools which can be executed either by key shortcuts or by clicking on their icons in the toolbar.
24 |
25 | ## Installation
26 | Clone the repository :
27 |
28 | ```sh
29 | git clone https://github.com/0x36/ghidra_kernelcache.git
30 | ```
31 |
32 | **Important note**: The project has been tested on Ghidra 10.1_PUBLIC and 10.2_DEV and it is not backward compatible.
33 |
34 | Go to *`Windows → Script Manager`,* click on *`script Directory` ,* then add *`ghidra_kernelcache`* to the directory path list.
35 | Go to *`Windows → Script Manager`,* in *scripts* listing, go to *`iOS→kernel`* category and check the plugins seen there, they will appear in GHIDRA Toolbar .
36 |
37 | in [logos/](https://github.com/0x36/ghidra_kernelcache/tree/master/logos) directory, you can put you own logos for each tool.
38 |
39 | ## iOS kernelcache symbolication
40 |
41 | `ghidra_kernelcache` requires at the first stage [iometa](https://github.com/Siguza/iometa/) (made by [@s1guza](https://twitter.com/s1guza)), a powerful tool providing C++ class information in the kernel binary, the great thing is that it works as a standalone binary, so the output can be imported to your favorite RE framework by just parsing it. My framework takes iometa's output and parses it to symbolicate and fix virtual tables.
42 |
43 | ### Usage
44 | After decompressing the kernel, run the following commands :
45 |
46 | ```sh
47 | $ iometa -n -A /tmp/kernel A10-legacy.txt > /tmp/kernel.txt
48 | # if you want also to symbolicate using jtool2
49 | $ jtool2 --analyze /tmp/kernel
50 |
51 | ```
52 |
53 | Load the kernelcache in Ghidra, ***DO NOT USE BATCH import*** , load it as Mach-O image.
54 | After the Kernelcache being loaded and auto-analyzed, click on the icon shown in the toolbar or just press **Meta-Shift-K**, then put the full path of iometa output which is `/tmp/kernel.txt` in our case.
55 |
56 | if you want to use `jtool2` symbols, you can use `jsymbol.py` located `iOS→kernel` category as well.
57 |
58 | ### iOS kernelcache API
59 | Full API examples are in [`ghidra_kernelcache/kc.py`](https://github.com/0x36/ghidra_kernelcache/blob/master/KC.py)
60 |
61 | → Here are some examples of manipulating class objects :
62 | ```py
63 | from utils.helpers import *
64 | from utils.class import *
65 | from utils.iometa import ParseIOMeta
66 |
67 | ff = "/Users/mg/ghidra_ios/kernel.txt"
68 | iom = ParseIOMeta(ff)
69 | Obj = iom.getObjects()
70 | kc = kernelCache(Obj)
71 |
72 |
73 | # symbolicate the kernel
74 | kc.process_all_classes()
75 |
76 | # symbolicate the classes under com.apple.iokit.IOSurface bundle
77 | kc.process_classes_for_bundle("com.apple.iokit.IOSurface")
78 |
79 | # symbolicate the classes under __kernel__ bundle
80 | kc.process_classes_for_bundle("__kernel__")
81 |
82 | # Process one class (including its parents)
83 | kc.process_class("IOGraphicsAccelerator2")
84 |
85 | # Clears the content of the class structures (vtables are excluded)
86 | kc.clear_class_structures()
87 |
88 | # Overwrite the old vtable structure definition and resymbolicate it again
89 | kc.update_classes_vtable()
90 |
91 | # Reconstructing function call trees by enumerating all pac references and find their corresponding virtual method call
92 | kc.explore_pac()
93 | ```
94 |
95 | As you can see, you can fully or partially symbolicate the kernelcache, if partial symbolication was chosen, `ghidra_kernelcache` will automatically construct all class dependencies before proceeding.
96 | If you run the script against the whole kernelcache (full symbolication), `ghidra_kernelcache` will take several minutes to analyze the kernel image.
97 |
98 | One finished, Ghidra will provide the following :
99 |
100 | → A new category has been added in Bookmark Filter called "iOS":
101 |
102 |
103 |
104 |
105 | → IOKit class virtual tables are added to 'iOS' Bookmark for better and faster virtual table lookup, you can just look for a kext or a class by providing letters, words or kext bundle in the search bar.
106 |
107 |
108 |
109 |
110 | → Fixing the virtual table : disassembles/compiles unknown code, fixes namespaces, re-symbolicates the class methods and applies function definition to each method:
111 |
112 |
113 |
114 | → Creation of class namespaces and put each method to its own corresponding namespace:
115 |
116 |
117 |
118 | → Creating class structure with the respect of class hierarchy :
119 |
120 |
121 |
122 | → Creating class vtables, and each method has its own method definition for better decompilation output:
123 |
124 |
125 |
126 | Full implementation can be found in [`utils/class.py.`](https://github.com/0x36/ghidra_kernelcache/blob/master/utils/class.py)
127 |
128 | Here are some screenshots of before/after symbolicating using `ghidra_kernelcache` :
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | ## macOS Kext symbolication
138 | ---
139 | `ghidra_kernelcache` macOS support is for both kernelcache and single KEXT symbolication for ARM64e and x86_64 architectures.
140 | **IMPORTANT:** At the time of writing Ghidra is unable to parse the whole macOS kernelcache, but it's possible to load it in IDA for initial analysis then import the database (idb to xml) to Ghidra later, but this is out of scope. If you manage to do so, `ghidra_kernelcache` will take care of the rest.
141 |
142 | There are some few steps which have to be taken before symbolicating any macOS Kernel Extension, as `ghidra_kernelcache`'s main aim is to reconstruct the class hierarchy and to manage all class structures into a single database, a kernel extension does not fulfill those requirements, which means that the symbolication of a single KEXT does require a symbolication of the kernel and perhaps other Kernel Extensions that depends on, hence some extra work needs to be done here.
143 | `ghidra_kernelcache` now provides a powerful way to symbolicate Kernel Extensions including the kernel by managing and sharing class structures and virtual method definitions via Ghidra's powerful *DataType Project Archive*
144 |
145 | ### Steps to symbolicate a Kernel Extension
146 | - Create a new folder in your Ghidra project, then load ` /System/Library/Kernels/kernel.release.XXXXX` into that folder and let Ghidra analyzes it.
147 | - Create a new *Project Archive* : Go to `DataType Provider` → Click on the arrow in the top right of the window → `New Project Archive` → Place it inside the newly created Folder → Name it to something (i.e macOS_12.1).
148 | - Now symbolicate the kernel using `ghidra_kernelcache`, the process is quite similar to iOS *kernelcache* symbolication.
149 |
150 | ```bash
151 | $ iometa -n -A /System/Library/Kernels/kernel.release.t8101 > /tmp/kernel.txt
152 | ```
153 | - In python console, or you can find the full script implementation in `KM.py` script :
154 | ```py
155 | >>> from utils.helpers import *
156 | >>> from utils.kext import *
157 | >>> iom = ParseIOMeta("/tmp/kernel.txt")
158 | >>> Obj = iom.getObjects()
159 | >>> kc = Kext(Obj,shared_p="macOS_12.1")
160 | >>> kc.process_kernel_kext()
161 |
162 | ```
163 | - Once finished, a database association has been created between kernel's archive and `macOS_12.1` archive. Now, right click on the `kernel.release.t8001` → `Commit DataTypes To` → `macOS_12.1`.
164 | - Then `Right Click` →`Select All` → `Commit`.
165 | - Save the project archive : `Right click` → `Save Archive`.
166 | We've just created a project archive which can be shared across all Kernel Extensions.
167 | Let's take an example of `IOSurface` Kext for Apple Silicon :
168 | ```bash
169 | $ lipo /System/Library/Extensions/IOSurface.kext/Contents/MacOS/IOSurface -thin arm64e -output /tmp/iosurface.arm64e
170 | $ iometa -n -A /tmp/iosurface.arm64e > /tmp/iosurface.txt
171 | ```
172 |
173 | - Load the Kext into the same folder path where the kernel database and the project archive are located and let Ghidra finishes the analysis
174 | - Load the project archive we've created earlier `macOS_12.1` : go to `Data Type Manager` → `Open Project Archive` , then select the `macOS_12.1`
175 | - Run the following methods, full script can be found in `KM.py`:
176 | ```python
177 | from utils.helpers import *
178 | from utils.kext import *
179 |
180 | kc = Kext(Obj,shared_p="macOS_12.1")
181 |
182 | # This method fixes LC_DYLD_CHAINED_FIXUPS for M1 Kernel extension
183 | kc.depac()
184 |
185 | # This method reconstructs class hierarchy and builds virtual table for each class
186 | kc.process_kernel_kext()
187 |
188 | ```
189 |
190 | **Important Note** : sometimes `kc.process_kernel_kext()` fails because Ghidra was not able to demangle some C++ symbols. To fix this, go to the script manager and run `DemangleAllScript.java` script then restart `kc.process_kernel_kext()` again.
191 |
192 | ### Custom classes
193 | There are some cases where some C++ classes where `ghidra_kernelcache` and `iometa` cannot symbolicate, so a new feature has been added to handle this.
194 | `Custom()` class reconstruction iterates through all the `::vtable` symbols and checks wether the class is already defined or not, if not, it automatically creates a class structure, function definitions for each identified class method, a namespace and a virtual table for each class.
195 |
196 | Custom class creation is supported on macOS only at the moment.
197 |
198 | ```bash
199 | $ iometa -n -A /System/Library/Kernels/kernel.release.t8101 > /tmp/kernel.txt
200 | $ iometa -n -A >> /tmp/kernel.txt
201 | ```
202 |
203 | ```py
204 |
205 | from utils.helpers import *
206 | from utils.custom_kc import *
207 |
208 | if __name__ == "__main__":
209 | default = "/tmp/kernel.txt"
210 | ff = askString("iometa symbol file","Symbol file: ",default)
211 | iom = ParseIOMeta(ff)
212 | Obj = iom.getObjects()
213 |
214 | kc = Custom(Obj)
215 |
216 | kc.process_all_classes()
217 | kc.explore_pac()
218 |
219 |
220 | ```
221 |
222 | ## Miscellaneous scripts
223 | ---
224 | ### Importing KDK's Dwarf4
225 | Ghidra somehow fails to load the corresponding `.dsym` directory, I made a small script to fix this. It can be found [here](https://github.com/0x36/ghidra_kernelcache/blob/master/dwarf4_fix.py).
226 | **Usage** : load the kernel from your KDK path, let Ghidra finishes the analysis, then run `dwarf_fix.py`, it will load the symbols and the process may take several minutes.
227 |
228 |
229 | ### Resolving virtual method calls references
230 | `ghidra_kernelcache` provides two ways to resolve virtual calls by `kernelCache.explore_pac` or `fix_extra_refs`
231 |
232 | **kernelCache.explore_pac()**
233 | If you're working on arm64e binary, `ghidra_kernelcache` can recognize virtual method calls by looking for the `Pointer Authentication Code` value. The process is straightforward and unlike `fix_extra_refs()`, `kernelCache.explore_pac` does not rely on the `Pcode` or `varnode` identification, it just iterates through all the instructions in the program, searches for `MOVK` instructions, fetches the second operand and looks for its corresponding value in the database.
234 | Usage :
235 | Create a *KernelCache* instance via **kernelCache** , **Kext** or **Custom**, then call `explore_pac()` method.
236 | ```py
237 | from utils.helpers import *
238 | from utils.kext import *
239 |
240 | if __name__ == "__main__":
241 | default = "/tmp/kernel.txt"
242 | ff = askString("iometa symbol file","Symbol file: ",default)
243 | iom = ParseIOMeta(ff)
244 | Obj = iom.getObjects()
245 |
246 | kc = Kext(Obj)
247 |
248 | kc.explore_pac()
249 |
250 | ```
251 |
252 | **fix_extra_refs()**
253 | This function is based on a basic data flow analysis to find all virtual call methods and to resolve their implementations automatically, it works across all architectures and has the ability to recognize the source data type from the decompiler output and resolve all the virtual call references inside the function, so the user is able to jump forward/backward directly to/from the implementation without manually looking for it.
254 | The most useful feature provided by `fix_extra_refs` is that it keeps the references synchronized on each execution. For example, you changed a variable data type to a class data type, `fix_extra_refs` will automatically recognize the change, and will recursively go through all call sites to resolve their references, and it will stop only when the call site queue became empty.
255 |
256 | There are some other features provided by `fix_extra_refs` such as:
257 | - It auto-detects `_ptmf2ptf()` calls and resolves their call method for both offsets and full function address
258 | - It identifies the namespace of an unresolved function name (functions which start with FUN_ ), and resolve it by putting the target function into its own namespace (e.g adding **this** pointer of the corresponding class).
259 |
260 | You can find the implementation in **utils/references.py,** `fix_extra_refs` parses the [pcode](https://ghidra.re/ghidra_docs/api/ghidra/program/model/pcode/package-summary.html) operations and looks for `CALLIND` and `CALL` opcodes, then gets all involved [varnodes](https://ghidra.re/ghidra_docs/api/ghidra/program/model/pcode/Varnode.html) in the operation, once a Varnode definition was identified, it retrieves its [HighVariable](https://ghidra.re/ghidra_docs/api/ghidra/program/model/pcode/HighVariable.html) to identify the class object type, if the type is unknown (i.e does not appear to be a class structure) it just ignores it, otherwise it will take the class name, looks up its virtual call table, using the offset provided by the Varnode, it can fetch the right virtual method call and puts a reference on the call instruction.
261 |
262 | ```py
263 | fix_extra_refs(toAddr(address))
264 | ```
265 | Here is an output example of using `fix_extra_refs` :
266 |
267 |
268 |
269 | Note that it has successfully resolved **IOService::isOpen()**, **OSArray:getNextIndexOfObject()** and **IOStream::removeBuffer()** virtual calls without any manual modification.
270 |
271 | Next, `fix_extra_refs` will decompile **IOStream::removeBuffer()**, gets all HighVariables of this method, then it resolves their references like the previous method ... and so on.
272 |
273 |
274 | ### Auto fixing external method tables
275 |
276 | I believe that every researcher has some script to deal with this part, as it is the main attack surface of IOKit, doing it manually is a burden, and it must be automated in a way the researcher wants to dig into multiple external method tables.
277 | There are two scripts provided by the`ghidra_kernelcache` : **fix_methodForIndex.py** and **fix_extMethod.py.** You can enable them like the other scripts as shown above.
278 |
279 | ***Usage***: Put the cursor at the start of the external dispatch table, run the script: provide the target, and the number of selectors.
280 | Example for `IOStreamUserClient::getTargetAndMethodForIndex()` :
281 |
282 |
283 |
284 |
285 | ### namespace.py : fix method namespaces …
286 | This is a useful script to populate the class type to all encountered methods, and it's a dependency for `extra_refs.py` script in order to recursively explore the callee functions and to resolve their references.
287 |
288 | ***Usage***: Put the cursor in the decompiler output of the wanted function, run the script from the toolbar or press **Meta-Shift-N** .
289 |
290 | ### Symbol name and type propagation
291 | `ghidra_kernelcache` provides type propagation support for basic Pcode operations, but it will likely fails for some variables that using complex casting .
292 | If someone wants to help, or wants to start working with low level stuff in Ghidra, this is the opportunity to do so.
293 | Implementation can be found in [ghidra_kernelcache/propagate.py](https://github.com/0x36/ghidra_kernelcache/blob/master/propagate.py)
294 |
295 | ### Loading function signatures
296 |
297 | Parsing C++ header files in Ghidra is not possible, and having kernel function signatures in kernelcache can improve many things in the decompiler output.
298 | For example, let's say we have added `virtual IOMemoryMap * map(IOOptionBits options = 0 );`, Ghidra will automatically re-type the return value into `IOMemoryMap` pointer automatically for both function definition and function signatures.
299 | You can add any C++ symbol into **signatures/** directory with the respect of the syntax and you can find defined function signatures in this directory.
300 |
301 | ```c++
302 | // Defining an instance class method
303 | IOMemoryDescriptor * withPersistentMemoryDescriptor(IOMemoryDescriptor *originalMD);
304 |
305 | // Defining a virtual method, it must start with "virtual" keyword
306 | virtual IOMemoryMap * createMappingInTask(task_t intoTask, mach_vm_address_t atAddress, IOOptionBits options, mach_vm_size_t offset = 0, mach_vm_size_t length = 0);
307 |
308 | // Defining a structure
309 | struct task_t;
310 |
311 | // typedef'ing a type
312 | typedef typedef uint IOOptionBits;
313 |
314 | // Lines begining with '//' are ignored
315 |
316 | ```
317 |
318 | ***Usage***: After symbolicating the kernel, it is highly recommended to run the script `load_sigatnures.py` to load all available function signatures. As most of the previous tools, run this script by adding it in the toolbar or from the Plugin manager or just press **Meta-Shift-S** .
319 |
320 | ### Loading old structures:
321 |
322 | This script is straight-froward, it imports all structures, classes, typedefs, and function definitions and everything with `SourceType.USER_DEFINED` from an old project to a new one.
323 |
324 | ***Usage***: Open the old and the new Ghidra projects on the same tool, go to [`load_structs.py`](https://github.com/0x36/ghidra_kernelcache/blob/master/load_structs.py) script, put the old program name to **src_prog_string** variable, and the new one to **dst_prog_string** variable, then run the script.
325 |
326 | ## Contribute
327 | If you see the project interesting and want to contribute, just do a PR and I will review it, meanwhile, I would like to see some contribution in the following areas:
328 | * [ghidra_kernelcache/signatures/kernel.txt](https://github.com/0x36/ghidra_kernelcache/tree/master/signatures): keep importing XNU kernel functions, it is so simple just copy/paste the function definition.
329 | * [ghidra_kernelcache/propagate.py](https://github.com/0x36/ghidra_kernelcache/blob/master/propagate.py) : support un-handled opcodes for better symbol propagation.
330 |
331 | ## Credit
332 | I would like to thank [@s1guza](https://twitter.com/s1guza) for his awesome [iometa](https://github.com/Siguza/iometa.git) which ghidra_kernelcache depends on.
333 |
--------------------------------------------------------------------------------
/dwarf4_fix.py:
--------------------------------------------------------------------------------
1 | #@category iOS.kernel
2 |
3 | from ghidra.program.model.listing import CodeUnit
4 | from ghidra.app.util.bin.format.dwarf4.next import DWARFImportOptions,DWARFProgram,DWARFParser
5 | from ghidra.program.model.data import BuiltInDataTypeManager
6 | from ghidra.app.util.bin.format.dwarf4.next.sectionprovider import DSymSectionProvider
7 | from java.io import File
8 |
9 |
10 | if __name__=='__main__':
11 | if (DWARFProgram.isDWARF(currentProgram) == False):
12 | popup("Unable to find DWARF information, aborting")
13 | exit(1)
14 |
15 | importOptions = DWARFImportOptions()
16 | importOptions.setPreloadAllDIEs(True)
17 | importOptions.setImportLimitDIECount(0x1000000);
18 |
19 | dwarfProg = DWARFProgram(currentProgram, importOptions, monitor)
20 | dtms = BuiltInDataTypeManager.getDataTypeManager()
21 | dp = DWARFParser(dwarfProg, dtms, monitor);
22 | importSummary = dp.parse()
23 | importSummary.logSummaryResults();
24 | print("[+] We're done")
25 |
--------------------------------------------------------------------------------
/extra_refs.py:
--------------------------------------------------------------------------------
1 | # Fix a method's vtable calls + reference making
2 |
3 | #@author simo
4 | #@category iOS.kernel
5 | #@keybinding R
6 | #@toolbar logos/refs.png
7 | #@description Resolve references for better CFG
8 | # -*- coding: utf-8 -*-
9 |
10 | """
11 | script which does the following:
12 | - adds references to virtual method calls
13 | - Identifies methods belong to a specific namespace
14 | - Handles multi value vtable reference (multi-nodes)
15 | """
16 |
17 | from utils.references import *
18 |
19 | if __name__ == "__main__":
20 | fix_extra_refs(currentAddress)
21 |
--------------------------------------------------------------------------------
/fix_extMethod.py:
--------------------------------------------------------------------------------
1 | # Fix IOExternalMethodDispatch for externalMethod()
2 | #@author simo
3 | #@category iOS.kernel
4 | #@keybinding Meta Shift B
5 | #@menupath
6 | #@toolbar logos/ext.png
7 | #@description test
8 |
9 | # -*- coding: utf-8 -*-
10 |
11 | from utils.helpers import *
12 | from utils.methods import *
13 | import json
14 |
15 | logger = None
16 |
17 | def fix_extMethod(class_struct ,func):
18 | dtm = currentProgram.getDataTypeManager()
19 | IOArgs_dt = find_struct("IOExternalMethodArguments")
20 | assert(IOArgs_dt != None)
21 |
22 |
23 | this = ParameterImpl("this",PointerDataType(class_struct),currentProgram)
24 | reference = ParameterImpl("reference",PointerDataType(VoidDataType()),currentProgram)
25 | IOArgs = ParameterImpl("args",PointerDataType(IOArgs_dt),currentProgram)
26 |
27 | params = [this,reference,IOArgs]
28 |
29 | func.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,
30 | True,
31 | SourceType.USER_DEFINED,
32 | params)
33 |
34 | IOExternalMethodDispatch_size = 24
35 |
36 | external_methods = {}
37 | def fix_externalMethods(target,selectors,sMethods):
38 |
39 | logger.info("target=%s selectors=%d ,sMethod=%s" %(target,selectors, sMethods))
40 | _sMethods = sMethods
41 | className = target
42 | symbolTable = currentProgram.getSymbolTable()
43 | listing = currentProgram.getListing()
44 |
45 | namespace = symbolTable.getNamespace(className,None)
46 |
47 | if namespace == None:
48 | popup("[-] %s class not found " %(className))
49 | exit(-1)
50 | class_struct = find_struct(className)
51 |
52 | em_infos = {}
53 | for sel in range(selectors):
54 | #off = sel * 24
55 | function_off = int(sMethods,16)
56 | checkScalarInputCount_off = function_off + 8
57 | checkStructureInputSize_off = checkScalarInputCount_off + 4
58 | checkScalarOutputCount_off = checkStructureInputSize_off + 4
59 | checkStructureOutputSize_off = checkScalarOutputCount_off +4
60 |
61 | smAddr = toAddr(sMethods)
62 |
63 | function_ptr = toAddr(hex(function_off).replace("L",""))
64 | function_end = toAddr(hex(function_off+25).replace("L",""))
65 |
66 | scalarInput_addr = toAddr(hex(checkScalarInputCount_off).replace("L",""))
67 | structureInput_addr = toAddr(hex(checkStructureInputSize_off).replace("L",""))
68 | scalarOutput_addr = toAddr(hex(checkScalarOutputCount_off).replace("L",""))
69 | structureOutput_addr = toAddr(hex(checkStructureOutputSize_off).replace("L",""))
70 |
71 | listing.clearCodeUnits(function_ptr,function_end,False)
72 |
73 | func = makeFunction(function_ptr)
74 | func_addr = getDataAt(function_ptr).getValue()
75 |
76 | func = getFunctionAt(func_addr)
77 | if func != None:
78 | symName = "extMethod_%d" %(sel)
79 | fix_namespace(className,func,symName)
80 | fix_extMethod(class_struct,func)
81 |
82 | setEOLComment(function_ptr,"sel %d" %(sel))
83 | makeUint(scalarInput_addr,"scalarInput")
84 | makeUint(structureInput_addr,"structureInput")
85 | makeUint(scalarOutput_addr,"scalarOutput")
86 | makeUint(structureOutput_addr,"structureInput")
87 |
88 | sMethods = hex(int(sMethods,16) + 24).replace("L","")
89 |
90 | scalarInputCnt = getDataAt(scalarInput_addr).getValue()
91 | structureInputCnt = getDataAt(structureInput_addr).getValue()
92 | scalarOutputCnt = getDataAt(scalarOutput_addr).getValue()
93 | structureOutputCnt = getDataAt(structureOutput_addr).getValue()
94 |
95 | if func == None:
96 | continue
97 |
98 | function_name = func.getName(False)
99 | call_info = {
100 | "selector" : sel,
101 | "scalarInputCnt" : scalarInputCnt.getValue(),
102 | "structInputCnt" : structureInputCnt.getValue(),
103 | "scalarOutputCnt" : scalarOutputCnt.getValue(),
104 | "structOutputCnt" : structureOutputCnt.getValue(),
105 | "async" : False,
106 | "address": func_addr.toString()
107 | }
108 |
109 | if function_name in em_infos:
110 | function_name = function_name + str(sel)
111 | em_infos[function_name] = call_info
112 |
113 | external_methods['externalMethods'] = em_infos # externalMethods
114 | external_methods['target'] = className # userclient
115 | external_methods['user_client_type'] = 0 # connection type (-1 means undefiend)
116 | external_methods['sMethods'] = _sMethods
117 | out_file = "/tmp/%s.json"%(className)
118 | with open(out_file, 'w') as json_file:
119 | json.dump(external_methods, json_file,indent=4, sort_keys=True)
120 | logger.info("%s file created" %(out_file))
121 |
122 | if __name__ == "__main__":
123 | sMethods = currentAddress
124 | if sMethods == None :
125 | popup("Select a The first External Method address")
126 | exit(-1)
127 |
128 | logger = setup_logging("external_method")
129 | addr_str = sMethods.toString()
130 | target = askString("Namespace","Target name: ") # how to track the history of strings ?
131 | selectors = askInt("sMethod " + addr_str,"Selector count: ")
132 |
133 | fix_externalMethods(target,selectors,addr_str)
134 |
--------------------------------------------------------------------------------
/fix_methodForIndex.py:
--------------------------------------------------------------------------------
1 | # Fix IOExternalMethod for getTargetAndMethodForIndex
2 | #@author simo
3 | #@category iOS.kernel
4 | #@keybinding Meta Shift B
5 | #@menupath
6 | #@toolbar logos/in.png
7 | #@description test
8 |
9 | # -*- coding: utf-8 -*-
10 |
11 | from utils.helpers import *
12 | from utils.methods import *
13 |
14 | import json
15 |
16 | def handle_kIOUCScalarIScalarO(func,count0,count1):
17 | logger.debug("kIOUCScalarIScalar func=%s, count0=%d, count1=%d" %(func.getName(),count0,count1))
18 | tool = state.getTool()
19 | service = tool.getService(DataTypeManagerService)
20 |
21 | o = 0
22 | signature = ""
23 | if count0 == 0:
24 | if count1 != 0:
25 | signature = "%s %s("
26 | for i in range(0,count1):
27 | signature += "uint32_t *scalarOut%d, " %(i)
28 |
29 | signature = signature[:-2]
30 | signature+= ")"
31 | else:
32 | signature = "%s %s(void)"
33 | else:
34 | signature = "%s %s("
35 | for i in range(0,count0):
36 | if i < count0:
37 | signature += "uint32_t scalar%d, " %(i)
38 |
39 | signature = signature[:-2]
40 |
41 | signature+= ")"
42 |
43 | name = func.getName()
44 | ret = func.getReturnType()
45 | signature = signature %(ret.toString(),name)
46 |
47 | fdef = parseSignature(service,currentProgram,signature)
48 | return fdef
49 |
50 | def handle_kIOUCStructIStructO(func,count0,count1):
51 | # if count0 and count 1 are set (input,output,inputCnt,outputCnt)
52 | # else (input,inputCnt)
53 | logger.debug("kIOUCStructIStructO func=%s, count0=%d, count1=%d" %(func.getName(),count0,count1))
54 | tool = state.getTool()
55 | service = tool.getService(DataTypeManagerService)
56 |
57 | signature = ""
58 | if count1 != 0 :
59 | if count0 != 0:
60 | signature = "%s %s(char *input,char *output,uint64_t inputCnt,uint64_t *outputCnt)"
61 | else:
62 | signature = "%s %s(char *output,uint64_t *outputCnt)"
63 |
64 | else:
65 | signature = "%s %s(char *input,uint64_t inputCnt)"
66 |
67 | name = func.getName()
68 | ret = func.getReturnType()
69 | signature = signature %(ret.toString(),name)
70 |
71 | #print signature
72 | fdef = parseSignature(service,currentProgram,signature)
73 | return fdef
74 |
75 |
76 | def handle_kIOUCScalarIStructO(func,count0,count1):
77 | logger.debug("kIOUCScalarIStructO func=%s, count0=%d, count1=%d" %(func.getName(),count0,count1))
78 | tool = state.getTool()
79 | service = tool.getService(DataTypeManagerService)
80 |
81 | signature = ""
82 |
83 | if count0 == 0:
84 | if count1 != 0:
85 | signature = "%s %s(char *output,uint32_t *outputCnt)"
86 | else:
87 | signature = "%s %s(void)"
88 | else:
89 | signature = "%s %s("
90 | for i in range(count0):
91 | signature+= "uint32_t scalar%d, " %(i)
92 |
93 | signature+="char *output,uint32_t *outputCnt)"
94 |
95 | name = func.getName()
96 | ret = func.getReturnType()
97 | signature = signature %(ret.toString(),name)
98 | fdef = parseSignature(service,currentProgram,signature)
99 | return fdef
100 |
101 |
102 | def handle_kIOUCScalarIStructI(func,count0,count1):
103 | logger.debug("kIOUCScalarIStructI func=%s, count0=%d, count1=%d" %(func.getName(),count0,count1))
104 | tool = state.getTool()
105 | service = tool.getService(DataTypeManagerService)
106 |
107 | signature = ""
108 |
109 | if count0 == 0:
110 | if count1 != 0:
111 | signature = "%s %s(char *input,uint32_t inputCnt)"
112 | else:
113 | signature = "%s %s(void)"
114 | else:
115 | signature = "%s %s("
116 | for i in range(count0):
117 | signature+= "uint32_t scalar%d, " %(i)
118 |
119 | signature+="char *input,uint32_t inputCnt)"
120 |
121 | name = func.getName()
122 | ret = func.getReturnType()
123 | signature = signature %(ret.toString(),name)
124 | fdef = parseSignature(service,currentProgram,signature)
125 |
126 | return fdef
127 |
128 |
129 | def fix_getTargetAndMethodForIndex(target,selectors,sMethods):
130 | logger.info("target=%s selectors=%d ,sMethod=%s" %(target,selectors, sMethods))
131 | manager = currentProgram.getSymbolTable()
132 | symbolTable = currentProgram.getSymbolTable()
133 | listing = currentProgram.getListing()
134 | refMgr = currentProgram.getReferenceManager()
135 | kIOUCTypeMask = 0x0000000f
136 | kIOUCScalarIScalarO = 0
137 | kIOUCScalarIStructO = 2
138 | kIOUCStructIStructO = 3
139 | kIOUCScalarIStructI = 4
140 | kIOUCForegroundOnly = 0x00000010
141 | kIOUCVariableStructureSize = 0xffffffff
142 |
143 | d = {
144 | kIOUCScalarIScalarO : "kIOUCScalarIScalarO",
145 | kIOUCScalarIStructO : "kIOUCScalarIStructO",
146 | kIOUCStructIStructO : "kIOUCStructIStructO",
147 | kIOUCScalarIStructI : "kIOUCScalarIStructI"
148 | }
149 |
150 | namespace = symbolTable.getNamespace(target,None)
151 | addr = toAddr(sMethods)
152 | assert(namespace != None)
153 | for sel in range(selectors):
154 | object_ptr = addr
155 | func_ptr = addr.add(8)
156 | off_ptr = addr.add(16)
157 | flags_ptr = addr.add(24)
158 | count0_ptr = addr.add(32)
159 | count1_ptr = addr.add(40)
160 |
161 | listing.clearCodeUnits(addr,addr.add(48),False,monitor)
162 | addr = addr.add(48)
163 | makeULongLong(object_ptr,"object")
164 | makeULongLong(flags_ptr,"function")
165 | makeULongLong(off_ptr,"is offset")
166 | makeULongLong(count0_ptr,"count0")
167 | makeULongLong(count1_ptr,"count1")
168 |
169 |
170 | setEOLComment(object_ptr,"sel %d" %(sel))
171 | isOffset = getDataAt(off_ptr).getValue().getValue()
172 |
173 | if isOffset == 0:
174 | func = makeFunction(func_ptr)
175 | func_addr = getDataAt(func_ptr).getValue()
176 | func = getFunctionAt(func_addr)
177 |
178 | else:
179 | # function referenced as offset
180 | listing.clearCodeUnits(func_ptr,func_ptr,False,monitor)
181 | makeULongLong(func_ptr,"object")
182 | logger.debug("Function is Offset")
183 | off = getDataAt(func_ptr).getValue().getValue()
184 |
185 | ns = namespace.getName() +"_vtable"
186 |
187 | symbol = manager.getSymbol(ns,None)
188 | assert(symbol != None)
189 | ptr = symbol.getAddress().add(off)
190 | ref_addr = getDataAt(ptr).getValue()
191 |
192 | func = getFunctionAt(ref_addr)
193 |
194 | ref = refMgr.addMemoryReference(func_ptr, ref_addr,
195 | RefType.COMPUTED_CALL, SourceType.DEFAULT, 0)
196 | setEOLComment(func_ptr,"offset=0x%x" %(off))
197 |
198 | flags = getDataAt(flags_ptr).getValue()
199 | count0 = getDataAt(count0_ptr).getValue().getValue()
200 | count1 = getDataAt(count1_ptr).getValue().getValue()
201 |
202 | if func == None:
203 | continue
204 | flags = flags.getValue() & kIOUCTypeMask
205 |
206 | if flags == kIOUCScalarIScalarO:
207 | fdef = handle_kIOUCScalarIScalarO(func,count0,count1)
208 | elif flags == kIOUCScalarIStructO:
209 | fdef = handle_kIOUCScalarIStructO(func,count0,count1)
210 | elif flags == kIOUCStructIStructO:
211 | fdef = handle_kIOUCStructIStructO(func,count0,count1)
212 | elif flags == kIOUCScalarIStructI:
213 | fdef = handle_kIOUCScalarIStructI(func,count0,count1)
214 | else:
215 | raise Exception("Unknown flag %d" %(flags))
216 |
217 | setEOLComment(flags_ptr,d[flags])
218 | if "FUN_" in func.getName() or "FN_" in func.getName():
219 | func.setName("extMethod_%d" %(sel),SourceType.USER_DEFINED)
220 |
221 | func.setParentNamespace(namespace)
222 | cmd = ApplyFunctionSignatureCmd(func.getEntryPoint(),fdef,SourceType.USER_DEFINED)
223 | cmd.applyTo(func.getProgram())
224 | func.setCallingConvention("__thiscall")
225 |
226 | if __name__ == "__main__":
227 | sMethods = currentAddress
228 | if sMethods == None :
229 | popup("Select a The first External Method address")
230 | exit(-1)
231 |
232 | logger = setup_logging("getTargetAndMethodForIndex")
233 |
234 | addr_str = sMethods.toString()
235 | target = askString("Namespace","Target name: ") # how to track the history of strings ?
236 | selectors = askInt("sMethod " + addr_str,"Selector count: ")
237 | fix_getTargetAndMethodForIndex(target,selectors,addr_str)
238 |
239 | pass
240 |
--------------------------------------------------------------------------------
/jsymbols.py:
--------------------------------------------------------------------------------
1 | # Symbolicate the kernelcache from jtool2
2 | #@author simo
3 | #@category iOS.kernel
4 | from utils.methods import *
5 |
6 | if __name__ == "__main__":
7 |
8 | default_file = "test"
9 | fname = askString("Kernelcache symbol file","Symbol file: ",default_file)
10 | f = open(fname,"rb+")
11 | buf = f.read().split('\n')
12 | i = 0
13 | for line in buf:
14 | if len(line) == 0:
15 | continue
16 | addr , symbol , empty = line.split("|")
17 | if len(symbol) == 0:
18 | continue
19 |
20 | if "func_" in symbol:
21 | continue
22 | print addr,symbol
23 | symbol = symbol.strip()#.replace(" ","_")
24 | symbolicate(addr,symbol)
25 | i+= 1
26 |
--------------------------------------------------------------------------------
/load_sigatnures.py:
--------------------------------------------------------------------------------
1 | #@category iOS.kernel
2 | #@toolbar logos/sign.png
3 | #@keybinding Meta Shift S
4 |
5 | from utils.helpers import *
6 | from utils.methods import *
7 | import glob
8 |
9 | dtm = void = this = manager = None
10 |
11 | def getHeaderFiles():
12 | return glob.glob("/Users/mg/ghidra_kernelcache/signatures/*")
13 |
14 | def load_signatures_from_file(filename):
15 | funcs = open(filename,"r").read().strip().split('\n')
16 | tool = state.getTool()
17 | service = tool.getService(DataTypeManagerService)
18 | dtm = currentProgram.getDataTypeManager()
19 | funcDefs = []
20 | text = ""
21 |
22 | for func in funcs:
23 | vtable = False
24 | if len(func) == 0:
25 | continue
26 | elif func[0:2] == "//":
27 | continue
28 | elif func[0:8] == "virtual ":
29 | vtable = True
30 | text = func[8:]
31 |
32 | elif func[0:7] == "struct ":
33 | structName = func.split(" ")[1].replace(";","")
34 | structDt = find_struct(structName)
35 | if structDt != None:
36 | continue
37 | structDt = StructureDataType(structName,0)
38 | currentProgram.getDataTypeManager().addDataType(structDt,None)
39 | currentProgram.getDataTypeManager().addDataType(PointerDataType(structDt),None)
40 | continue
41 | elif func[0:8] == "typedef ":
42 | kw, old, new = func.split(" ")
43 | addTypeDef(new[:-1],old)
44 | continue
45 |
46 | else:
47 | text = func
48 |
49 | try:
50 | funcDef = parseSignature(service,currentProgram,text,True)
51 | except ghidra.app.util.cparser.C.ParseException as e:
52 | print e
53 | raise Exception("Failed to parse the signature")
54 |
55 | if vtable == True:
56 | funcDef.setGenericCallingConvention(GenericCallingConvention.thiscall)
57 |
58 | funcDefs.append(funcDef)
59 |
60 | return funcDefs
61 |
62 | # this fixes directly the function signature of a given function
63 | def fix_function_signatures(namespace,fdefs):
64 | tool = state.getTool()
65 | service = tool.getService(DataTypeManagerService)
66 | manager = currentProgram.getSymbolTable()
67 | for fdef in fdefs:
68 | symbol = fdef.getName()
69 | if namespace == "kernel":
70 | symbols = manager.getSymbols(symbol)
71 | for s in symbols:
72 | defineSymbol(s,fdef)
73 |
74 | ns = manager.getNamespace(namespace,None)
75 | symbols = manager.getSymbols(symbol,ns)
76 | if len(symbols) == 0 or ns == None:
77 | continue
78 | if symbols == None:
79 | continue
80 | if len(symbols) == 1:
81 | defineSymbol(symbols[0],fdef)
82 | continue
83 |
84 | #TODO : handle multi symbols below
85 | # a very bad workaround, but it's sufficient
86 | for sym in symbols:
87 | addr = sym.getAddress()
88 |
89 | plate = getPlateComment(addr)
90 | if plate == None:
91 | continue
92 |
93 | plate = plate.replace("const","")
94 | retType = fdef.getReturnType()
95 | try:
96 | df = parseSignature(service,currentProgram,plate,True)
97 | except ghidra.app.util.cparser.C.ParseException as e:
98 | print e
99 | exit(0)
100 |
101 | if df == None:
102 | plate = retType.toString()+ " " + plate
103 | try:
104 | df = parseSignature(service,currentProgram,plate,True)
105 | except ghidra.app.util.cparser.C.ParseException as e:
106 | print e
107 | exit(0)
108 |
109 | if df == None:
110 | continue
111 |
112 | defineSymbol(sym,df)
113 |
114 | def fix_method_definitions(namespace,fdefs):
115 | if namespace == "kernel":
116 | for fdef in fdefs:
117 | name = fdef.getName()
118 | symbols = manager.getSymbols(name)
119 | for symbol in symbols:
120 | full_name = symbol.getName(True)
121 | dt = find_funcdef(full_name)
122 | if dt == None:
123 | continue
124 | dt.setReturnType(fdef.getReturnType())
125 | args = fdef.getArguments()
126 | args.insert(0,this)
127 | dt.setArguments(args)
128 |
129 | return
130 |
131 | for fdef in fdefs:
132 | name = fdef.getName()
133 | full_name = namespace + '::'+ name
134 | dt = find_funcdef(full_name)
135 | if dt == None:
136 | continue
137 |
138 | dt.setReturnType(fdef.getReturnType())
139 | args = fdef.getArguments()
140 | args.insert(0,this)
141 | dt.setArguments(args)
142 |
143 | if __name__ == "__main__":
144 | DeclareDataTypes()
145 | dtm = currentProgram.getDataTypeManager()
146 | void = currentProgram.getDataTypeManager().findDataType("/void")
147 | this = ParameterDefinitionImpl("this",PointerDataType(void),"")
148 | manager = currentProgram.getSymbolTable()
149 |
150 | files = getHeaderFiles()
151 | for file in files:
152 | print ("[+] Processing %s" %(file))
153 | namespace = file.split(".h")[0].split("/")[-1]
154 | fdefs= load_signatures_from_file(file)
155 | fix_function_signatures(namespace,fdefs)
156 | fix_method_definitions(namespace,fdefs)
157 |
--------------------------------------------------------------------------------
/load_structs.py:
--------------------------------------------------------------------------------
1 | #import structures and typedefs from old kernelcache to a new one
2 | #@author simo
3 | #@category iOS.kernel
4 | #@toolbar logos/load_structs.png
5 | #@keybinding Meta Shift L
6 | #@menupath
7 |
8 | from ghidra.app.services import DataTypeManagerService
9 | from ghidra.program.model.data import StructureDataType,PointerDataType
10 | from ghidra.app.services import ProgramManager
11 |
12 | """
13 | - Get all structures from source program and copy them into destination program
14 | - It avoids taking "_vtable" structures because fix_kernelcache will handle it
15 | - If struct is already there, just skip it
16 | """
17 |
18 |
19 | src_prog_string = ""
20 | dst_prog_string = ""
21 |
22 | def isThere(name,programDT):
23 |
24 | if "MetaClass" in name:
25 | return True
26 |
27 | if "_vtable" in name:
28 | return True
29 |
30 | dataType = programDT.getDataType(name)
31 |
32 | if dataType :
33 | return True
34 |
35 | return False
36 |
37 | if __name__ == "__main__":
38 | tool = state.getTool()
39 | service = tool.getService(DataTypeManagerService)
40 | dataTypeManagers = service.getDataTypeManagers();
41 |
42 | programManager = state.getTool().getService(ProgramManager)
43 | progs =programManager.getAllOpenPrograms()
44 | if len(progs) < 2 :
45 | popup ("You must open at least two programs")
46 | exit(1)
47 |
48 | src = dst = None
49 | for prog in progs:
50 | if src_prog_string == prog.getName():
51 | src = prog
52 | elif dst_prog_string == prog.getName():
53 | dst = prog
54 |
55 | if src == None or dst == None:
56 | popup("Could not get src/dst program")
57 | exit(0)
58 |
59 | print src,dst
60 |
61 | src_dtm = src.getDataTypeManager()
62 | dst_dtm = dst.getDataTypeManager()
63 |
64 | structs = src_dtm.getAllStructures()
65 |
66 | for s in structs:
67 | name = s.getName()
68 | res = isThere('/'+name,dst_dtm)
69 | if res == True:
70 | continue
71 |
72 | res = isThere('/Demangler/'+name,dst_dtm)
73 | if res == True:
74 | continue
75 |
76 | struct = StructureDataType(name,0)
77 | dst_dtm.addDataType(struct,None)
78 | dst_dtm.addDataType(PointerDataType(struct),None)
79 |
--------------------------------------------------------------------------------
/namespace.py:
--------------------------------------------------------------------------------
1 | #@author simo
2 | #@category iOS.kernel
3 | #@keybinding Meta Shift N
4 | # -*- coding: utf-8 -*-
5 |
6 | from utils.helpers import *
7 | from utils.methods import *
8 |
9 | if __name__ == "__main__":
10 |
11 | targetFunction = getSymbolAt(currentAddress)
12 |
13 | if targetFunction == None :
14 | targetFunction = askString("You didn't select a method", "Method name:")
15 | exit(-1)
16 |
17 | # how to track the history of strings ?
18 | className = askString("Fix Namespace","namespace of "+ targetFunction.toString())
19 | symbolTable = currentProgram.getSymbolTable()
20 |
21 | namespace = symbolTable.getNamespace(className,None)
22 | if namespace == None:
23 | popup("%s class not found" %(className))
24 | exit(-1)
25 |
26 | fix_namespace(className,getFunctionAt(targetFunction.getAddress()))
27 | print "Done"
28 |
--------------------------------------------------------------------------------
/propagate.py:
--------------------------------------------------------------------------------
1 | # Propagate variable symbol + type over a function
2 | #@author simo
3 | #@category iOS.kernel
4 | #@keybinding Alt X
5 | #@menupath
6 | #@toolbar logos/sdsdlogo.png
7 | #@description propagate the new symbol name/type across function arguments
8 | # -*- coding: utf-8 -*-
9 |
10 | # interesting link : https://github.com/NationalSecurityAgency/ghidra/issues/2236#issuecomment-685204563
11 | from utils.helpers import *
12 | from ghidra.app.decompiler.component import DecompilerUtils
13 | from ghidra.app.decompiler import ClangVariableToken,ClangFieldToken
14 | from ghidra.program.database.data import StructureDB
15 | #from ghidra.app.decompiler import ClangToken as clang
16 | """
17 | ClangOpToken: ex return, if , else ..etc
18 | ClangSyntaxToken : {} ()
19 | ClangFuncNameToken : a function call
20 | """
21 |
22 | datatypes = {}
23 |
24 | def setup_datatypes():
25 | global datatypes
26 | dtm = currentProgram.getDataTypeManager()
27 | uchar = dtm.getDataType("/uchar")
28 | ushort = dtm.getDataType("/ushort")
29 | uint = dtm.getDataType("/uint")
30 | ulonglong = dtm.getDataType("/ulonglong")
31 |
32 | datatypes[1] = uchar
33 | datatypes[2] = ushort
34 | datatypes[4] = uint
35 | datatypes[8] = ulonglong
36 | assert (uchar and ushort and uint and ulonglong)
37 | #exit(0)
38 | structure = None
39 |
40 |
41 | def validate_token_store(token):
42 | """
43 | Checks the source target token
44 | Support : STORE , (LOAD later)
45 | """
46 | # the token must be a variable and has an operation code
47 | if token.isVariableRef() == False or token.getPcodeOp() == None:
48 | return False
49 |
50 | op = token.getPcodeOp()
51 | if op.getOpcode() != PcodeOp.STORE:
52 | return False
53 | return True
54 |
55 | def get_struct_fild(struct,fields):
56 | pass
57 |
58 | # returns (datatype,size) of the variable token
59 | def handle_source_token(token):
60 | op = token.getPcodeOp()
61 | if (op.getOpcode() == PcodeOp.STORE):
62 | inputs = op.getInputs()
63 | dst,src = inputs[1], inputs[2]
64 | #print op
65 |
66 | if src.isConstant():
67 | size = src.getSize()
68 | dt = None
69 | elif src.isRegister() or src.isUnique():
70 | size = src.getSize()
71 | high = src.getHigh()
72 |
73 | if (isinstance(high,ghidra.program.model.pcode.HighOther) == True):
74 | high = None
75 | return (None,size)
76 | dt = high.getDataType()
77 |
78 | # elif src.isUnique():
79 | # print "UNIQ"
80 | # size = src.getSize()
81 | # high = src.getHigh()
82 | # print size,high
83 | # raise Exception
84 | else:
85 | print("hndle_source_token(): varnode type not supported [IGNORE] ")
86 | return (None,src.getSize())
87 |
88 | return (dt,size)
89 |
90 | #returns the target variable to be modified
91 | def handle_dest_vartoken(line,src_dt,src_size):
92 | var = None
93 | fields = []
94 | for tok in line.getAllTokens():
95 | if tok.toString() == "=":
96 | break
97 |
98 | if(isinstance(tok,ClangVariableToken) == True):
99 | if var != None:
100 | continue
101 | sym = tok.getHighVariable().getSymbol()
102 | if sym: var = tok
103 |
104 | elif(isinstance(tok,ClangFieldToken) == True):
105 | fields.append(tok)
106 | # now we have "this [IOBluetoothDeviceUserClient, field_0x10]"
107 | #if isinstance(this)
108 | var_dt = var.getHighVariable().getSymbol().getDataType()
109 | path = var_dt.getDataTypePath()
110 | mgr = var_dt.getDataTypeManager()
111 | n = var_dt.getName().replace("*","").strip()
112 | st = find_struct(n)
113 | if (st == None):
114 | raise Exception("Could not find %s structure"% n)
115 | #var_name =
116 | # fields tokens are taken recursively : dt->field1.field2. .. .fieldN
117 | if (isinstance(st,StructureDB) == False):
118 | return None
119 |
120 | cps = st.getComponents()
121 | struct = st
122 | if cps == None:
123 | return None
124 | for field in fields:
125 | cps = struct.getComponents()
126 | if cps == None:
127 | break
128 | fld_name = field.toString()
129 | # if we hit "field_name", it does mean the field member is still undefined
130 | # and we reach the end of the structure parsing
131 | if "field_" in fld_name:
132 | try:
133 | f,idx = fld_name.split("_")
134 | except ValueError:
135 | f,idx,_ = fld_name.split("_")
136 | target = struct.getDataTypeAt(int(idx,16))
137 | fld_name = f + "_" + str(idx)
138 | try:
139 | if src_dt: dt = src_dt
140 | else: dt = datatypes[src_size]
141 | struct.replaceAtOffset(int(idx,16),dt,src_size,fld_name+"_","")
142 |
143 | # sometimes the variable is not aligned and is conflicting with other struct member
144 | # must be handled manually
145 | except java.lang.IllegalArgumentException as e:
146 | print (e)
147 | break
148 |
149 | for cp in cps:
150 | if cp.getFieldName() == fld_name:
151 | if(isinstance(cp.getDataType(),StructureDB)):
152 | struct = cp.getDataType()
153 | break
154 |
155 | # token: is the source target token
156 | def handle_line_store(line,token):
157 | global structure
158 | src_dt, src_sz = handle_source_token(token)
159 | handle_dest_vartoken(line,src_dt,src_sz)
160 | """
161 | op = token.getPcodeOp()
162 | assert(op.getOpcode() == PcodeOp.STORE)
163 | inputs = op.getInputs()
164 | dst,src = inputs[1], inputs[2]
165 |
166 | if src.isConstant() == False:
167 | sym = src.getHigh().getSymbol()
168 | if (sym == None):
169 | return
170 | dt = sym.getDataType()
171 | print dt.getLength()
172 | print("Unable to handle no constant values")
173 | exit(0)
174 | return
175 | """
176 | return
177 |
178 | # now get variableRef
179 | var = None
180 | var_name = None
181 | fields = []
182 | f_done = True
183 |
184 | for t in line.getAllTokens():
185 | #print t,type(t)
186 | if(isinstance(t,ClangVariableToken) == True):
187 | if var != None:
188 | continue
189 | sym = t.getHighVariable().getSymbol()
190 | if sym: var = t
191 |
192 | elif(isinstance(t,ClangFieldToken) == True):
193 | fields.append(t)
194 |
195 | if t == token:
196 | print "We are done"
197 | break
198 |
199 | var_dt = var.getHighVariable().getSymbol().getDataType()
200 | path = var_dt.getDataTypePath()
201 | mgr = var_dt.getDataTypeManager()
202 | n = var_dt.getName().replace("*","").strip()
203 | st = find_struct(n)
204 | if (st == None):
205 | raise Exception("Could not find %s structure"% n)
206 |
207 | # fields tokens are taken recursively : dt->field1.field2...fieldn
208 | cps = st.getComponents()
209 | struct = st
210 | if cps == None:
211 | return
212 | for field in fields:
213 | cps = struct.getComponents()
214 | if cps == None:
215 | break
216 | fld_name = field.toString()
217 | # if we hit "field_name", it does mean the field member is still undefined
218 | # and we reach the end of the structure parsing
219 | if "field_" in fld_name:
220 | f,idx = fld_name.split("_")
221 | #print f,idx
222 | target = struct.getDataTypeAt(int(idx,16))
223 | #target.setFieldName("f_"+idx)
224 | try:
225 | struct.replaceAtOffset(int(idx,16),datatypes[target_size],target_size,"f_"+idx,"")
226 | except java.lang.IllegalArgumentException as e:
227 | print (e)
228 | break
229 | for cp in cps:
230 | if cp.getFieldName() == fld_name:
231 | if(isinstance(cp.getDataType(),StructureDB)):
232 | struct = cp.getDataType()
233 | break
234 |
235 | def debug_line(lines,linum):
236 | for line in lines:
237 | if line.getLineNumber() != linum:
238 | continue
239 |
240 | print (line)
241 | tokens = line.getAllTokens()
242 | for token in tokens:
243 | print token, type(token),"opcode :", token.getPcodeOp()
244 |
245 |
246 |
247 | def handle_line(line):
248 | tokens = line.getAllTokens()
249 | for token in tokens:
250 | if validate_token_store(token) == True:
251 | handle_line_store(line,token)
252 | pass
253 | else: # handle other opcodes here
254 | pass
255 |
256 | def do_assign(addr):
257 | entry = addr
258 | setup_datatypes()
259 | print(entry)
260 | func = getFunctionContaining(entry)
261 | assert(func != None)
262 | print func
263 | decompInterface = DecompInterface()
264 | decompInterface.openProgram(currentProgram)
265 | decompiled = decompInterface.decompileFunction(func, 120, monitor)
266 |
267 | lines = DecompilerUtils.toLines(decompiled.getCCodeMarkup())
268 |
269 | for line in lines:
270 | handle_line(line)
271 |
272 | decompInterface.dispose()
273 | print("Done")
274 |
275 | if __name__ == "__main__":
276 | listing = currentProgram.getListing()
277 | do_assign(currentAddress)
278 |
--------------------------------------------------------------------------------
/screenshots/image1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image1.png
--------------------------------------------------------------------------------
/screenshots/image10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image10.png
--------------------------------------------------------------------------------
/screenshots/image11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image11.png
--------------------------------------------------------------------------------
/screenshots/image12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image12.png
--------------------------------------------------------------------------------
/screenshots/image2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image2.png
--------------------------------------------------------------------------------
/screenshots/image3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image3.png
--------------------------------------------------------------------------------
/screenshots/image4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image4.png
--------------------------------------------------------------------------------
/screenshots/image5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image5.png
--------------------------------------------------------------------------------
/screenshots/image6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image6.png
--------------------------------------------------------------------------------
/screenshots/image7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image7.png
--------------------------------------------------------------------------------
/screenshots/image8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image8.png
--------------------------------------------------------------------------------
/screenshots/image9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/screenshots/image9.png
--------------------------------------------------------------------------------
/signatures/IOBufferMemoryDescriptor.h:
--------------------------------------------------------------------------------
1 | IOBufferMemoryDescriptor * inTaskWithOptions(task_t inTask, IOOptionBits options, vm_size_t capacity, vm_offset_t alignment, uint32_t kernTag, uint32_t userTag);
2 | IOBufferMemoryDescriptor * inTaskWithOptions(task_t inTask, IOOptionBits options, vm_size_t capacity, vm_offset_t alignment);
3 | IOBufferMemoryDescriptor * inTaskWithPhysicalMask(task_t inTask, IOOptionBits options, mach_vm_size_t capacity, mach_vm_address_t physicalMask);
4 | IOBufferMemoryDescriptor * withBytes(const void *bytes, vm_size_t withLength, IODirection withDirection, bool withContiguousMemory);
5 | IOBufferMemoryDescriptor * withCapacity(vm_size_t capacity, IODirection withDirection, bool withContiguousMemory);
6 | IOBufferMemoryDescriptor * withCopy(task_t inTask, IOOptionBits options, vm_map_t sourceMap, mach_vm_address_t source, mach_vm_size_t size);
7 | IOBufferMemoryDescriptor * withOptions(IOOptionBits options, vm_size_t capacity, vm_offset_t alignment);
8 | virtual void setLength(vm_size_t length);
9 | virtual void setDirection(IODirection direction);
10 | virtual bool initWithPhysicalMask(task_t inTask, IOOptionBits options, mach_vm_size_t capacity, mach_vm_address_t alignment, mach_vm_address_t physicalMask);
11 | virtual vm_size_t getCapacity(void);
12 | virtual void * getBytesNoCopy(vm_size_t start, vm_size_t withLength);
13 | virtual void * getBytesNoCopy(void);
14 | virtual bool appendBytes(const void *bytes, vm_size_t withLength);
15 | kern_return_t SetLength(uint64_t length, void * supermethod);
16 | kern_return_t GetAddressRange(IOAddressSegment *range);
17 |
--------------------------------------------------------------------------------
/signatures/IOCommandGate.h:
--------------------------------------------------------------------------------
1 | IOCommandGate * commandGate(void *owner, void *action);
2 | virtual void setWorkLoop(IOWorkLoop *inWorkLoop);
3 | virtual IOReturn runCommand(void *arg0, void *arg1, void *arg2, void *arg3);
4 | virtual IOReturn runAction(void *action, void *arg0, void *arg1, void *arg2, void *arg3);
5 | virtual void commandWakeup(void *event, bool oneThread);
6 | //virtual IOReturn commandSleep(void *event, AbsoluteTime deadline, UInt32 interruptible);
7 | //virtual IOReturn commandSleep(void *event, UInt32 interruptible);
8 | virtual IOReturn attemptCommand(void *arg0, void *arg1, void *arg2, void *arg3);
9 |
--------------------------------------------------------------------------------
/signatures/IODataQueue.h:
--------------------------------------------------------------------------------
1 | IODataQueue * withEntries(UInt32 numEntries, UInt32 entrySize);
2 | IODataQueue * withCapacity(UInt32 size);
3 | virtual void setNotificationPort(ipc_port *port);
4 | virtual void sendDataAvailableNotification(void);
5 | virtual bool initWithEntries(UInt32 numEntries, UInt32 entrySize);
6 | virtual bool initWithCapacity(UInt32 size);
7 | virtual IOMemoryDescriptor * getMemoryDescriptor(void);
8 | virtual bool enqueue(void *data, UInt32 dataSize);
9 |
--------------------------------------------------------------------------------
/signatures/IOEventSource.h:
--------------------------------------------------------------------------------
1 | virtual const OSMetaClass * getMetaClass();
2 | virtual bool init();
3 | virtual void free();
4 | virtual bool init_1(OSObject *owner, void *action);
5 | virtual bool checkForWork();
6 | virtual void setWorkLoop(IOWorkLoop *workLoop);
7 | virtual void setNext(IOEventSource *next);
8 | virtual IOEventSource *getNext()
9 | virtual void * getAction();
10 | virtual void enable();
11 | virtual void disable();
12 | virtual bool isEnabled();
13 | virtual IOWorkLoop *getWorkLoop();
14 | virtual bool onThread();
15 |
16 |
--------------------------------------------------------------------------------
/signatures/IOMemoryDescriptor.h:
--------------------------------------------------------------------------------
1 | //https://developer.apple.com/documentation/kernel/iomemorydescriptor?language=objc
2 | IOMemoryDescriptor * withPhysicalAddress(IOPhysicalAddress address, IOByteCount withLength, IODirection withDirection);
3 | //IOMemoryDescriptor *(mach_vm_address_t address, mach_vm_size_t length, IOOptionBits options, task_t task);
4 | IOMemoryDescriptor * withOptions(void *buffers, UInt32 count, UInt32 offset, task_t task, IOOptionBits options, IOMapper *mapper);
5 | IOMemoryDescriptor * withAddressRanges(IOAddressRange *ranges, UInt32 rangeCount, IOOptionBits options, task_t task);
6 | IOMemoryDescriptor * withAddressRange(void *address, mach_vm_size_t withLength, IOOptionBits options, task * task);
7 | IOMemoryDescriptor * withPersistentMemoryDescriptor(IOMemoryDescriptor *originalMD);
8 | virtual IOReturn complete(IODirection forDirection);
9 | virtual IOMemoryMap * createMappingInTask(task_t intoTask, mach_vm_address_t atAddress, IOOptionBits options, mach_vm_size_t offset = 0, mach_vm_size_t length = 0);
10 | virtual IODirection getDirection();
11 | virtual IOByteCount getLength();
12 | virtual IOReturn getPageCounts(IOByteCount *residentPageCount, IOByteCount *dirtyPageCount);
13 | virtual IOPhysicalAddress getPhysicalAddress();
14 | virtual bool initWithOptions(void *buffers,UInt32 count, UInt32 offset, task_t task, IOOptionBits options, IOMapper *mapper = 0);
15 | virtual IOMemoryMap * map(IOOptionBits options = 0 );
16 | virtual IOReturn performOperation( IOOptionBits options, IOByteCount offset, IOByteCount length );
17 | virtual IOReturn prepare(IODirection forDirection = 0);
18 | virtual IOByteCount readBytes(IOByteCount offset, void *bytes, IOByteCount withLength);
19 | virtual IOMemoryMap * setMapping( task_t task, IOVirtualAddress mapAddress, IOOptionBits options = 0 );
20 | virtual IOByteCount writeBytes( IOByteCount offset, void * bytes, IOByteCount withLength);
21 | virtual void addMapping(IOMemoryMap *mapping);
22 | virtual IOReturn doMap(vm_map_t addressMap, IOVirtualAddress *atAddress, IOOptionBits options, IOByteCount sourceOffset, IOByteCount length);
23 | virtual IOReturn doUnmap(vm_map_t addressMap, IOVirtualAddress logical, IOByteCount length);
24 | virtual uint64_t getPhysicalSegment( IOByteCount offset, IOByteCount *length, IOOptionBits options = 0 );
25 | virtual const OSMetaClass * getMetaClass();
26 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
27 | virtual kern_return_t Dispatch(const IORPC rpc);
28 | virtual void free();
29 | virtual IOReturn setPurgeable( IOOptionBits newState,IOOptionBits * oldState );
30 | virtual uint64_t getPreparationID( void );
31 | virtual void setTag( IOOptionBits tag );
32 | virtual IOOptionBits getTag( void );
33 | virtual IOReturn redirect( task_t safeTask, bool redirect );
34 | virtual IOMemoryMap * makeMapping(IOMemoryDescriptor * owner,task_t intoTask,IOVirtualAddress atAddress,IOOptionBits options,IOByteCount offset,IOByteCount length );
35 | virtual void removeMapping(IOMemoryMap * mapping );
36 | typedef undefined4 DMACommandOps;
37 | virtual IOReturn dmaCommandOperation(DMACommandOps op, void *vData, int dataSize);
38 |
--------------------------------------------------------------------------------
/signatures/IOMemoryMap.h:
--------------------------------------------------------------------------------
1 | virtual uint64_t getAddress();
2 | virtual task_t getAddressTask();
3 | virtual IOByteCount getLength();
4 | virtual IOOptionBits getMapOptions();
5 | virtual IOMemoryDescriptor * getMemoryDescriptor();
6 | virtual IOPhysicalAddress getPhysicalAddress();
7 | virtual uint64_t getPhysicalSegment( IOByteCount offset, IOByteCount *length, IOOptionBits options = 0);
8 | virtual IOVirtualAddress getVirtualAddress();
9 | virtual IOReturn redirect( IOMemoryDescriptor *newBackingMemory, IOOptionBits options, IOByteCount offset = 0);
10 | virtual IOReturn unmap();
11 | virtual IOReturn wireRange(uint32_t options, mach_vm_size_t offset, mach_vm_size_t length);
12 |
--------------------------------------------------------------------------------
/signatures/IORegistryEntry.h:
--------------------------------------------------------------------------------
1 | virtual const OSMetaClass * getMetaClass();
2 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
3 | virtual bool init_1( OSDictionary * dictionary );
4 | virtual void setPropertyTable( OSDictionary * dict );
5 | virtual bool setProperty(const OSSymbol * aKey,OSObject * anObject);
6 | virtual bool setProperty_1(const OSString * aKey, OSObject * anObject);
7 | virtual bool setProperty_2(const char * aKey, OSObject * anObject);
8 | virtual bool setProperty_3(const char * aKey, const char * aString);
9 | virtual bool setProperty_4(const char * aKey, bool aBoolean);
10 | virtual bool setProperty_5( const char * aKey,unsigned long long aValue,unsigned int aNumberOfBits);
11 | virtual bool setProperty_6( const char * aKey,void * bytes,unsigned int length);
12 | virtual void removeProperty( const OSSymbol * aKey);
13 | virtual void removeProperty_1( const OSString * aKey);
14 | virtual void removeProperty_2( const char * aKey);
15 | virtual OSObject * getProperty( const OSSymbol * aKey);
16 | virtual OSObject * getProperty_1( const OSString * aKey);
17 | virtual OSObject * getProperty_2( const char * aKey);
18 | virtual OSObject * getProperty_3( const OSSymbol * aKey,const IORegistryPlane * plane,IOOptionBits options);
19 | virtual OSObject * getProperty_4( const OSString *aKey,const IORegistryPlane * plane,IOOptionBits options);
20 | virtual OSObject * getProperty_5( const char *aKey,const IORegistryPlane * plane,IOOptionBits options);
21 | virtual OSObject * copyProperty_2( const OSSymbol * aKey,const IORegistryPlane * plane );
22 | virtual OSObject * copyProperty_1( const OSString * aKey,const IORegistryPlane * plane );
23 | virtual OSObject * copyProperty( const char * aKey,const IORegistryPlane * plane );
24 | virtual OSObject * copyProperty_3( const OSSymbol * aKey);
25 | virtual OSObject * copyProperty_4( const OSString * aKey);
26 | virtual OSObject * copyProperty_5( const char * aKey);
27 | virtual OSDictionary * dictionaryWithProperties( void );
28 | virtual bool serializeProperties( OSSerialize * serialize );
29 | virtual IOReturn setProperties( OSObject * properties );
30 | virtual OSIterator * getParentIterator( const IORegistryPlane * plane );
31 | virtual void applyToParents( void * applier,void * context,const IORegistryPlane * plane );
32 | virtual IORegistryEntry * getParentEntry( const IORegistryPlane * plane );
33 | virtual OSIterator * getChildIterator( const IORegistryPlane * plane );
34 | virtual void applyToChildren( void * applier,void * context,const IORegistryPlane * plane );
35 | virtual IORegistryEntry * getChildEntry( const IORegistryPlane * plane );
36 | virtual bool isChild( IORegistryEntry * child,const IORegistryPlane * plane,bool onlyChild );
37 | virtual bool isParent( IORegistryEntry * parent,const IORegistryPlane * plane,bool onlyParent);
38 | virtual bool inPlane( const IORegistryPlane * plane);
39 | virtual unsigned int getDepth( const IORegistryPlane * plane );
40 | virtual bool attachToParent( IORegistryEntry * parent,const IORegistryPlane * plane );
41 | virtual void detachFromParent( IORegistryEntry * parent,const IORegistryPlane * plane );
42 | virtual bool attachToChild( IORegistryEntry * child,const IORegistryPlane * plane );
43 | virtual void detachFromChild( IORegistryEntry * child,const IORegistryPlane * plane );
44 | virtual void detachAbove( const IORegistryPlane * plane );
45 | virtual void detachAll( const IORegistryPlane * plane );
46 | virtual const char * getName( const IORegistryPlane * plane );
47 | virtual const OSSymbol * copyName(const IORegistryPlane * plane);
48 | virtual bool compareNames( OSObject * name, OSString ** matched );
49 | virtual bool compareName( OSString * name, OSString ** matched);
50 | virtual void setName( const OSSymbol * name,const IORegistryPlane * plane);
51 | virtual void setName_1( const char * name,const IORegistryPlane * plane);
52 | virtual const char * getLocation( const IORegistryPlane * plane);
53 | virtual const OSSymbol * copyLocation(const IORegistryPlane * plane);
54 | virtual void setLocation( const OSSymbol * location,const IORegistryPlane * plane );
55 | virtual void setLocation_1( const char * location,const IORegistryPlane * plane);
56 | virtual bool getPath( char * path, int * length,const IORegistryPlane * plane);
57 | virtual bool getPathComponent( char * path, int * length,const IORegistryPlane * plane );
58 | virtual IORegistryEntry * childFromPath( const char * path,const IORegistryPlane * plane,char * residualPath,int * residualLength );
59 | virtual bool init_2( IORegistryEntry * from,const IORegistryPlane * inPlane );
60 | virtual IORegistryEntry * copyParentEntry( const IORegistryPlane * plane );
61 | virtual IORegistryEntry * copyChildEntry( const IORegistryPlane * plane );
62 | virtual IOReturn runPropertyAction(void * action, OSObject *target,void *arg0 , void *arg1,void *arg2 , void *arg3);
63 | virtual void free();
--------------------------------------------------------------------------------
/signatures/IOService.h:
--------------------------------------------------------------------------------
1 | virtual const OSMetaClass * getMetaClass();
2 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
3 | virtual kern_return_t Dispatch(const IORPC rpc);
4 | virtual bool init();
5 | virtual void free();
6 | virtual bool serializeProperties( OSSerialize * s );
7 | virtual bool requestTerminate( IOService * provider, IOOptionBits options );
8 | virtual bool willTerminate( IOService * provider, IOOptionBits options );
9 | virtual bool didTerminate( IOService * provider, IOOptionBits options, bool * defer );
10 | virtual SInt32 nextIdleTimeout(AbsoluteTime currentTime,AbsoluteTime lastActivity, unsigned int powerState);
11 | virtual void systemWillShutdown( IOOptionBits specifier );
12 | virtual IOService * copyClientWithCategory( const OSSymbol * category );
13 | typedef void IOReportChannelList;
14 | virtual IOReturn configureReport(IOReportChannelList *channels,void *action,void * result,void *destination);
15 | virtual IOReturn updateReport(IOReportChannelList*channels,void * action,void *result,void *destination);
16 | virtual IOOptionBits getState( void );
17 | virtual void registerService( IOOptionBits options);
18 | virtual bool start( IOService * provider );
19 | virtual void stop( IOService * provider );
20 | virtual bool open( IOService * forClient,IOOptionBits options,void * arg );
21 | virtual void close( IOService * forClient,IOOptionBits options);
22 | virtual bool isOpen( const IOService * forClient);
23 | virtual bool handleOpen(IOService * forClient,IOOptionBits options,void * arg );
24 | virtual void handleClose(IOService * forClient,IOOptionBits options );
25 | virtual bool handleIsOpen( const IOService * forClient );
26 | virtual bool terminate( IOOptionBits options);
27 | virtual bool finalize( IOOptionBits options );
28 | virtual bool init_1( OSDictionary * dictionary );
29 | virtual bool init_2( IORegistryEntry * from,const IORegistryPlane * inPlane );
30 | virtual void free( void );
31 | virtual bool lockForArbitration( bool isSuccessRequired);
32 | virtual void unlockForArbitration( void );
33 | virtual bool terminateClient( IOService * client, IOOptionBits options );
34 | virtual UInt32 getBusyState( void );
35 | virtual void adjustBusy( SInt32 delta );
36 | virtual bool matchPropertyTable( OSDictionary * table,SInt32 * score );
37 | virtual bool matchPropertyTable_1( OSDictionary * table );
38 | virtual IOService * matchLocation( IOService * client );
39 | virtual bool addNeededResource( const char * key );
40 | virtual bool compareProperty( OSDictionary * matching,const char * key );
41 | virtual bool compareProperty_1( OSDictionary * matching,const OSString * key );
42 | virtual bool compareProperties( OSDictionary * matching,OSCollection * keys );
43 | virtual bool attach( IOService * provider );
44 | virtual void detach( IOService * provider );
45 | virtual IOService * getProvider( void );
46 | virtual IOWorkLoop * getWorkLoop();
47 | virtual OSIterator * getProviderIterator( void );
48 | virtual OSIterator * getOpenProviderIterator( void );
49 | virtual IOService * getClient( void );
50 | virtual OSIterator * getClientIterator( void );
51 | virtual OSIterator * getOpenClientIterator( void );
52 | virtual IOReturn callPlatformFunction( const OSSymbol * functionName,bool waitForFunction,void *param1, void *param2,void *param3, void *param4 );
53 | virtual IOReturn callPlatformFunction_1( const char * functionName,bool waitForFunction,void *param1, void *param2,void *param3, void *param4 );
54 | virtual IOReturn getResources( void );
55 | typedef uint IOItemCount;
56 | virtual IOItemCount getDeviceMemoryCount( void );
57 | //typedef char IODeviceMemory;
58 | virtual IODeviceMemory * getDeviceMemoryWithIndex( unsigned int index );
59 | virtual IOMemoryMap * mapDeviceMemoryWithIndex( unsigned int index,IOOptionBits options );
60 | virtual OSArray * getDeviceMemory( void );
61 | virtual void setDeviceMemory( OSArray * array );
62 | virtual IOReturn registerInterrupt(int source, OSObject *target,void * handler,void *refCon);
63 | virtual IOReturn unregisterInterrupt(int source);
64 | virtual IOReturn getInterruptType(int source, int *interruptType);
65 | virtual IOReturn enableInterrupt(int source);
66 | virtual IOReturn disableInterrupt(int source);
67 | virtual IOReturn causeInterrupt(int source);
68 | virtual IOReturn requestProbe( IOOptionBits options );
69 | virtual IOReturn message( UInt32 type, IOService * provider,void * argument);
70 | virtual IOReturn messageClient( UInt32 messageType, OSObject * client,void * messageArgument , vm_size_t argSize );
71 | virtual IOReturn messageClients( UInt32 type,void * argument, vm_size_t argSize);
72 | virtual IONotifier * registerInterest( const OSSymbol * typeOfInterest,void * handler,void * target, void * ref);
73 | virtual void applyToProviders( void * applier,void * context );
74 | virtual void applyToClients( void * applier,void * context );
75 | virtual void applyToInterested( const OSSymbol * typeOfInterest, void * applier,void * context );
76 | virtual IOReturn acknowledgeNotification( void *notification,IOOptionBits response );
77 | virtual IOReturn newUserClient( task_t owningTask, void * securityID,UInt32 type, OSDictionary * properties,IOUserClient ** handler );
78 | virtual IOReturn newUserClient_1( task_t owningTask, void * securityID,UInt32 type,IOUserClient ** handler );
79 | virtual const char * stringFromReturn( IOReturn rtn );
80 | virtual int errnoFromReturn( IOReturn rtn );
81 | virtual bool serializeProperties( OSSerialize * s );
82 | virtual void PMinit( void );
83 | virtual void PMstop( void );
84 | virtual void joinPMtree( IOService * driver );
85 | //typedef char IOPMPowerState;
86 | typedef int IOPMPowerFlags;
87 | virtual IOReturn registerPowerDriver(IOService * controllingDriver,IOPMPowerState * powerStates,unsigned long numberOfStates );
88 | virtual IOReturn requestPowerDomainState(IOPMPowerFlags desiredState,IOPowerConnection * whichChild,unsigned long specificationFlags );
89 | virtual bool activityTickle(unsigned long type,unsigned long stateNumber);
90 | virtual IOReturn setAggressiveness(unsigned long type,unsigned long newLevel );
91 | virtual IOReturn getAggressiveness(unsigned long type,unsigned long * currentLevel );
92 | virtual IOReturn addPowerChild( IOService * theChild );
93 | virtual IOReturn removePowerChild( IOPowerConnection * theChild );
94 | virtual IOReturn setIdleTimerPeriod( unsigned long period );
95 | virtual IOReturn setPowerState(unsigned long powerStateOrdinal,IOService * whatDevice );
96 | virtual unsigned long maxCapabilityForDomainState( IOPMPowerFlags domainState );
97 | virtual unsigned long initialPowerStateForDomainState( IOPMPowerFlags domainState );
98 | virtual unsigned long powerStateForDomainState( IOPMPowerFlags domainState );
99 | virtual IOReturn powerStateWillChangeTo(IOPMPowerFlags capabilities,unsigned long stateNumber,IOService * whatDevice );
100 | virtual IOReturn powerStateDidChangeTo(IOPMPowerFlags capabilities,unsigned long stateNumber,IOService * whatDevice );
101 | virtual bool askChangeDown( unsigned long );
102 | virtual bool tellChangeDown( unsigned long );
103 | virtual void tellNoChangeDown( unsigned long );
104 | virtual void tellChangeUp( unsigned long );
105 | virtual IOReturn allowPowerChange( unsigned long refcon );
106 | virtual IOReturn cancelPowerChange( unsigned long refcon );
107 | virtual void powerChangeDone( unsigned long stateNumber );
108 | IOService * probe( IOService *provider,SInt32 *score );
109 |
--------------------------------------------------------------------------------
/signatures/IOSharedDataQueue.h:
--------------------------------------------------------------------------------
1 | IOSharedDataQueue * withEntries(UInt32 numEntries, UInt32 entrySize);
2 | IOSharedDataQueue * withCapacity(UInt32 size);
3 | virtual bool setQueueSize(UInt32 size);
4 | virtual void * peek(void);
5 | virtual bool initWithCapacity(UInt32 size);
6 | virtual UInt32 getQueueSize(void);
7 | virtual IOMemoryDescriptor * getMemoryDescriptor(void);
8 | virtual bool enqueue(void *data, UInt32 dataSize);
9 | virtual bool dequeue(void *data, UInt32 *dataSize);
10 |
--------------------------------------------------------------------------------
/signatures/IOUserClient.h:
--------------------------------------------------------------------------------
1 | IOReturn releaseAsyncReference64(uint64_t * reference);
2 | void setAsyncReference64(uint64_t * asyncRef, ipc_port * wakePort, mach_vm_address_t callback, uint64_t * refcon, task_t task);
3 | IOReturn releaseNotificationPort( ipc_port * ipc_port);
4 | IOMemoryMap * removeMappingForDescriptor( IOMemoryDescriptor *memory);
5 | IOReturn sendAsyncResult64WithOptions(uint64_t * reference, IOReturn result, uint64_t *args, UInt32 numArgs, IOOptionBits options);
6 | OSObject * copyClientEntitlement(task_t task, const char *entitlement);
7 | virtual kern_return_t Dispatch(const IORPC rpc);
8 | virtual bool init();
9 | virtual void free();
10 | virtual const OSMetaClass * getMetaClass();
11 | virtual bool init_1( OSDictionary * dictionary );
12 | virtual bool initWithTask(task_t owningTask, void * securityToken, UInt32 type,OSDictionary * properties);
13 | virtual bool initWithTask_1(task_t owningTask, void * securityToken, UInt32 type);
14 | virtual IOReturn clientClose( void );
15 | virtual IOReturn clientDied( void );
16 | virtual IOService * getService( void );
17 | virtual IOReturn registerNotificationPort_1(ipc_port * port, UInt32 type, UInt32 refCon );
18 | virtual IOReturn getNotificationSemaphore( UInt32 notification_type,void * semaphore );
19 | virtual IOReturn connectClient( IOUserClient * client );
20 | virtual IOReturn clientMemoryForType( UInt32 type,IOOptionBits * options,IOMemoryDescriptor ** memory );
21 | virtual IOReturn exportObjectToClient(task_t task, OSObject *obj, void *clientObj);
22 | virtual IOExternalMethod * getExternalMethodForIndex( UInt32 index );
23 | virtual IOExternalAsyncMethod * getExternalAsyncMethodForIndex( UInt32 index );
24 | virtual IOExternalMethod * getTargetAndMethodForIndex( IOService ** targetP, UInt32 index );
25 | virtual IOExternalAsyncMethod * getAsyncTargetAndMethodForIndex( IOService ** targetP, UInt32 index );
26 | virtual IOExternalTrap * getExternalTrapForIndex( UInt32 index );
27 | virtual IOExternalTrap * getTargetAndTrapForIndex( IOService **targetP, UInt32 index );
28 | virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArguments *arguments,IOExternalMethodDispatch *dispatch,OSObject *target, void *reference);
29 | virtual IOReturn registerNotificationPort(ipc_port * port, UInt32 type, uint64_t refCon);
--------------------------------------------------------------------------------
/signatures/IOWorkLoop.h:
--------------------------------------------------------------------------------
1 | IOWorkLoop * workLoopWithOptions(IOOptionBits options);
2 | IOWorkLoop * workLoop(void);
3 | void threadMainContinuation(IOWorkLoop *self);
4 | virtual IOReturn addEventSource(IOEventSource *newEvent);
5 | virtual void closeGate(void);
6 | virtual void disableAllEventSources(void);
7 | virtual void disableAllInterrupts(void);
8 | virtual void enableAllEventSources(void);
9 | virtual void enableAllInterrupts(void);
10 | virtual bool eventSourcePerformsWork(IOEventSource *inEventSource);
11 | virtual bool inGate(void);
12 | virtual bool init(void);
13 | virtual bool onThread(void);
14 | virtual void openGate(void);
15 | virtual IOReturn removeEventSource(IOEventSource *toRemove);
16 | virtual IOReturn runAction(void *action, void *target, void *arg0, void *arg1, void *arg2, void *arg3);
17 | virtual IOReturn runActionBlock(void * action);
18 | virtual bool runEventSources(void);
19 | virtual void setMaximumLockTime(uint64_t interval, uint32_t options);
20 | virtual void signalWorkAvailable(void);
21 | virtual int sleepGate(void *event, UInt32 interuptibleType);
22 | virtual int sleepGate(void *event, AbsoluteTime deadline, UInt32 interuptibleType);
23 | virtual void threadMain(void);
24 | virtual bool tryCloseGate(void);
25 | virtual void wakeupGate(void *event, bool oneThread);
26 | virtual const OSMetaClass * getMetaClass();
--------------------------------------------------------------------------------
/signatures/OSArray.h:
--------------------------------------------------------------------------------
1 | OSArray * withArray(OSArray *array, uint32_t capacity);
2 | OSArray * withCapacity(uint32_t capacity);
3 | OSArray * withObjects( OSObject **values, uint32_t count, uint32_t capacity);
4 | virtual unsigned int getCapacity();
5 | virtual unsigned int getCount();
6 | virtual unsigned int getNextIndexOfObject(void *anObject, unsigned intindex);
7 | virtual OSObject * getObject( unsigned intindex);
8 | virtual bool initWithArray(OSArray *anArray, unsigned int capacity = 0);
9 | virtual bool initWithCapacity( unsigned intcapacity);
10 | virtual bool initWithObjects(OSObject **objects, unsigned int count, unsigned int capacity = 0);
11 | virtual bool isEqualTo(void *anArray);
12 | virtual bool merge(OSArray *otherArray);
13 | virtual void removeObject( unsigned intindex);
14 | virtual void replaceObject( unsigned intindex, void *anObject);
15 | virtual bool serialize( OSSerialize *serializer);
16 | virtual unsigned int setCapacityIncrement( unsigned increment);
17 | virtual bool init();
18 | virtual void free();
19 | virtual unsigned int iteratorSize();
20 | virtual bool initIterator(void * iterator);
21 | virtual bool getNextObjectForIterator(void * iterator, OSObject ** ret);
22 | virtual unsigned int getCapacityIncrement();
23 | virtual unsigned int setCapacityIncrement(unsigned increment);
24 | void flushCollection();
25 | virtual unsigned setOptions(unsigned options,unsigned mask,void * context);
26 | OSCollection * copyCollection(OSDictionary * cycleDict);
27 | virtual bool setObject(void *anObject);
28 | virtual bool setObject_1(unsigned int index,const OSMetaClassBase * anObject);
29 | virtual bool isEqualTo_1(const OSArray * anArray);
30 | OSObject * getLastObject();
31 | virtual const OSMetaClass * getMetaClass();
32 | virtual unsigned int ensureCapacity(unsigned int newCapacity);
33 |
34 |
35 |
--------------------------------------------------------------------------------
/signatures/OSCollection.h:
--------------------------------------------------------------------------------
1 | virtual unsigned int iteratorSize();
2 | virtual bool initIterator(void * iterationContext);
3 | virtual bool getNextObjectForIterator(void * iterationContext,OSObject ** nextObject);
4 | virtual bool init();
5 | virtual unsigned int getCount();
6 | virtual unsigned int getCapacity();
7 | virtual unsigned int getCapacityIncrement();
8 | virtual unsigned int setCapacityIncrement(unsigned increment);
9 | virtual unsigned int ensureCapacity(unsigned int newCapacity);
10 | virtual void flushCollection();
11 | virtual unsigned setOptions(unsigned options,unsigned mask,void * context);
12 | OSCollection * copyCollection(OSDictionary * cycleDict);
13 | virtual const OSMetaClass * getMetaClass();
14 | virtual bool isEqualTo(OSMetaClassBase *col);
15 |
--------------------------------------------------------------------------------
/signatures/OSCollectionIterator.h:
--------------------------------------------------------------------------------
1 | OSCollectionIterator withCollection(void *inColl);
2 | virtual bool initWithCollection(OSCollection *inColl);
3 | virtual void * getNextObject(void);
4 |
--------------------------------------------------------------------------------
/signatures/OSData.h:
--------------------------------------------------------------------------------
1 | OSData * withData(OSData *inData, unsigned int start, unsigned int numBytes);
2 | OSData * withData(OSData *inData);
3 | OSData * withCapacity(unsigned int capacity);
4 | OSData * withBytesNoCopy(void *bytes, unsigned int numBytes);
5 | OSData * withBytes(void *bytes, unsigned int numBytes);
6 | virtual bool initWithBytes(void *bytes, unsigned int numBytes);
7 | virtual unsigned int getLength(void);
8 | virtual unsigned int getCapacityIncrement(void);
9 | virtual unsigned int getCapacity(void);
10 | virtual unsigned int ensureCapacity(unsigned int newCapacity);
11 | virtual bool initWithBytesNoCopy(void *bytes, unsigned int numBytes);
12 | virtual bool initWithCapacity(unsigned int capacity);
13 | virtual bool serialize(OSSerialize *serializer);
14 | virtual void free();
15 | virtual const OSMetaClass * getMetaClass();
16 | virtual bool initWithData(const OSData * inData);
17 | bool initWithData_1(const OSData *inData,unsigned int start, unsigned int inLength);
18 | virtual unsigned int getLength();
19 | virtual unsigned int getCapacity();
20 | virtual unsigned int getCapacityIncrement();
21 | virtual unsigned int setCapacityIncrement(unsigned increment);
22 | virtual bool appendByte(unsigned char byte, unsigned int numBytes);
23 | virtual bool appendBytes(void *bytes, unsigned int numBytes);
24 | virtual bool appendBytes_1(const OSData * aDataObj);
25 | virtual const void * getBytesNoCopy()
26 | virtual void * getBytesNoCopy_1(unsigned int start, unsigned int numBytes);
27 | virtual bool isEqualTo_1(const OSData * aDataObj);
28 | virtual bool isEqualTo_2(const void * bytes,unsigned int numBytes);
29 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
30 | virtual bool isEqualTo_3(const OSString * aString);
31 | //typedef void (*DeallocFunction)(void * ptr, unsigned int length);
32 | virtual void setDeallocFunction(void * func);
33 |
34 |
--------------------------------------------------------------------------------
/signatures/OSDictionary.h:
--------------------------------------------------------------------------------
1 | OSDictionary * withObjects(void **objects,OSString **keys, unsigned int count, unsigned int capacity);
2 | OSDictionary * withCapacity(uint32_t capacity);
3 | OSDictionary * withDictionary(OSDictionary *dict, unsigned int capacity);
4 | virtual bool serialize(OSSerialize *serializer);
5 | virtual bool initWithObjects(OSObject **objects,OSString **keys, unsigned int count, unsigned int capacity = 0);
6 | virtual const OSMetaClass * getMetaClass();
7 | virtual bool isEqualTo_2(const OSDictionary * aDictionary);
8 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
9 | virtual bool isEqualTo_1(const OSDictionary * aDictionary,const OSCollection * keys);
10 | virtual unsigned setOptions(unsigned options,unsigned mask,void * context);
11 | OSCollection * copyCollection(OSDictionary * cycleDict);
12 | virtual void flushCollection();
13 | virtual unsigned int ensureCapacity(unsigned int newCapacity);
14 | virtual unsigned int setCapacityIncrement(unsigned increment);
15 | virtual unsigned int getCapacityIncrement();
16 | virtual unsigned int getCapacity();
17 | virtual unsigned int getCount();
18 | virtual void free();
19 | virtual bool initWithDictionary(const OSDictionary * dict,unsigned int capacity);
20 | virtual bool initWithObjects(void **objects, OSSymbol **keys, unsigned int count, unsigned int capacity);
21 | virtual bool initWithObjects_1(void **objects, OSString **keys, unsigned int count, unsigned int capacity);
22 | virtual unsigned int iteratorSize();
23 | virtual bool initIterator(void * iterator);
24 | virtual bool getNextObjectForIterator(void * iterator, OSObject ** ret);
25 | virtual bool setObject(const OSSymbol * aKey,const OSMetaClassBase * anObject);
26 | virtual bool setObject_1(OSString *aKey, void *anObject);
27 | virtual bool setObject_2(OSSymbol *aKey, void *anObject);
28 | virtual void removeObject(const OSSymbol *aKey)
29 | virtual void removeObject_1(const OSString *aKey);
30 | virtual void removeObject_2(const char *aKey);
31 | virtual bool merge(const OSDictionary * aDictionary);
32 | virtual OSObject * getObject(const OSSymbol * aKey);
33 | virtual OSObject * getObject_1(const OSString * aKey);
34 | virtual OSObject * getObject_2(const char * aKey);
35 | virtual bool initWithCapacity(unsigned int capacity);
--------------------------------------------------------------------------------
/signatures/OSMetaClassBase.h:
--------------------------------------------------------------------------------
1 | virtual void release(int freeWhen);
2 | virtual void taggedRelease(const void * tag, const int freeWhen);
3 | virtual bool init();
4 | virtual void free();
5 | virtual int getRetainCount();
6 | virtual void retain();
7 | virtual void release_1();
8 | virtual void taggedRetain(const void * tag);
9 | virtual void taggedRelease_1(const void * tag);
10 | virtual bool serialize(OSSerialize * serializer);
11 | virtual kern_return_t Dispatch(const IORPC rpc);
12 | virtual const OSMetaClass * getMetaClass();
13 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
14 |
--------------------------------------------------------------------------------
/signatures/OSNumber.h:
--------------------------------------------------------------------------------
1 | OSNumber * withNumber(unsigned long long value, unsigned int numberOfBits);
2 | OSNumber * withNumber(char *valueString, unsigned int numberOfBits);
3 | virtual uint16_t unsigned16BitValue(void);
4 | virtual uint32_t unsigned32BitValue(void);
5 | virtual uint64_t unsigned64BitValue(void);
6 | virtual uint8_t unsigned8BitValue(void);
7 | virtual void setValue(unsigned long long value);
8 | virtual bool serialize(OSSerialize *serializer);
9 | virtual unsigned int numberOfBytes(void);
10 | virtual unsigned int numberOfBits(void);
11 | virtual void addValue(long long value);
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/signatures/OSObject.h:
--------------------------------------------------------------------------------
1 | virtual void release(int freeWhen);
2 | virtual void taggedRelease(const void * tag, const int freeWhen);
3 | virtual bool init();
4 | virtual void free();
5 | virtual int getRetainCount();
6 | virtual void retain();
7 | virtual void release_1();
8 | virtual void taggedRetain(const void * tag);
9 | virtual void taggedRelease_1(const void * tag);
10 | virtual bool serialize(OSSerialize * serializer);
11 | virtual kern_return_t Dispatch(const IORPC rpc);
12 | virtual const OSMetaClass * getMetaClass();
13 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
14 |
15 |
--------------------------------------------------------------------------------
/signatures/OSSerialize.h:
--------------------------------------------------------------------------------
1 | OSSerialize * binaryWithCapacity(unsigned int inCapacity, void * editor, void *reference);
2 | OSSerialize * withCapacity(unsigned int capacity);
3 | virtual char * text(void);
4 | virtual bool initWithCapacity(unsigned int inCapacity);
5 | virtual void endBinaryCollection(uint32_t startCollection);
6 | virtual void clearText(void);
7 | virtual bool binarySerializeInternal(void *o);
8 | virtual bool addString(char *cString);
9 | virtual bool addBinaryObject(void *o, uint32_t key, void *_bits, size_t size, uint32_t *startCollection);
10 | virtual bool addBinary(void *data, size_t size);
11 | virtual bool previouslySerialized(const OSMetaClassBase *o);
12 | virtual bool addXMLStartTag(const OSMetaClassBase * object,const char * tagString);
13 | virtual bool addXMLEndTag(const char * tagString);
14 | virtual bool addChar(const char aChar);
15 | virtual bool addString(const char * cString);
16 | virtual bool initWithCapacity(unsigned int inCapacity);
17 | virtual unsigned int getLength();
18 | virtual unsigned int getCapacity();
19 | virtual unsigned int getCapacityIncrement() ;
20 | virtual unsigned int setCapacityIncrement(unsigned increment);
21 | virtual unsigned int ensureCapacity(unsigned int newCapacity);
22 | virtual void free();
23 | virtual const OSMetaClass * getMetaClass();
24 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
--------------------------------------------------------------------------------
/signatures/OSSet.h:
--------------------------------------------------------------------------------
1 | OSSet * withArray(OSArray *array, unsigned int capacity);
2 | OSSet * withCapacity(unsigned int capacity);
3 | OSSet * withObjects(OSObject **objects, unsigned int count, unsigned int capacity);;
4 | OSSet * withSet(OSSet *set, unsigned int capacity);
5 | virtual bool setObject(void *anObject);
6 | virtual bool initWithSet(OSSet *set, unsigned int capacity);
7 | virtual bool initWithObjects(OSObject **objects, unsigned int count, unsigned int capacity);
8 | virtual bool initWithCapacity(unsigned int capacity);
9 | virtual bool initWithArray(OSArray *array, unsigned int capacity);
10 | virtual unsigned int ensureCapacity(unsigned int newCapacity);
11 | virtual void flushCollection(void);
12 | virtual unsigned int iteratorSize();
13 | virtual bool initIterator(void * iterator);
14 | virtual bool getNextObjectForIterator(void * iterator, OSObject ** ret);
15 | virtual void free();
16 | virtual unsigned int getCapacity();
17 | virtual unsigned int getCount();
18 | virtual unsigned int getCapacityIncrement();
19 | virtual unsigned int setCapacityIncrement(unsigned increment);
20 | OSCollection * copyCollection(OSDictionary * cycleDict);
21 | virtual unsigned setOptions(unsigned options,unsigned mask,void * context);
22 | virtual unsigned int ensureCapacity(unsigned int newCapacity);
23 | virtual bool merge(const OSArray * array);
24 | virtual bool merge_1(const OSSet * set);
25 | virtual void removeObject(const OSMetaClassBase * anObject);
26 | virtual bool containsObject(const OSMetaClassBase * anObject);
27 | virtual bool member(const OSMetaClassBase * anObject);
28 | virtual OSObject * getAnyObject();
29 | virtual bool isEqualTo_1(const OSSet * aSet);
30 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
31 | virtual bool serialize(OSSerialize * serializer);
32 | virtual const OSMetaClass * getMetaClass();
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/signatures/OSString.h:
--------------------------------------------------------------------------------
1 | OSString * withCString(char *cString);
2 | OSString * withCStringNoCopy(char *cString);
3 | OSString * withString(OSString *aString);
4 | virtual bool initWithString( OSString *aString);
5 | virtual bool initWithCStringNoCopy( char *cString);
6 | virtual bool initWithCString( char *cString);
7 | virtual unsigned int getLength(void);
8 | virtual char * getCStringNoCopy(void);
9 | virtual bool serialize( OSSerialize *serializer);
10 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
11 | virtual void free();
12 | virtual unsigned int getLength(void);
13 | virtual bool isEqualTo_1(const OSString * aString);
14 | virtual bool isEqualTo_2(const char * cString);
15 | virtual bool isEqualTo(const OSData * aDataObject);
16 | virtual char getChar(unsigned int index);
17 | virtual bool setChar(char aChar, unsigned int index);
18 |
--------------------------------------------------------------------------------
/signatures/OSSymbol.h:
--------------------------------------------------------------------------------
1 | OSSymbol * withString(OSString *aString);
2 | OSSymbol * withCStringNoCopy(char *cString);
3 | OSSymbol * withCString(char *cString);
4 | OSSymbol * existingSymbolForString(OSString *aString);
5 | OSSymbol * existingSymbolForCString(char *aCString);
6 | virtual bool initWithCString( char *cString);
7 | virtual bool initWithCStringNoCopy(char *cString);
8 | virtual bool initWithString(OSString *aString);
9 | virtual bool isEqualTo(const OSMetaClassBase * anObject);
10 | virtual void free();
11 | virtual unsigned int getLength(void);
12 | virtual bool isEqualTo_1(const OSString * aString);
13 | virtual bool isEqualTo_2(const char * cString);
14 | virtual bool isEqualTo_4(const OSSymbol * aSymbol);
15 | virtual char getChar(unsigned int index);
16 | virtual bool setChar(char aChar, unsigned int index);
17 | virtual void taggedRelease_1(const void * tag,const int freeWhen);
18 | virtual void taggedRelease(const void * tag);
19 | virtual const OSMetaClass * getMetaClass();
20 |
21 |
--------------------------------------------------------------------------------
/signatures/kernel.h:
--------------------------------------------------------------------------------
1 | typedef u64 vm_size_t;
2 | int _memcmp(const void *s1, const void *s2, size_t ssize);
3 | void * _memcpy(void *dst, void *src, size_t ssize);
4 | void * _memmove(void *dst, void *src, size_t ssize);
5 | //void * ___memcpy_chk(void *dst, void *src, size_t ssize,size_t max);
6 | void _IOFreeAligned(void *address, vm_size_t size);
7 | void _IOFree(void *address, vm_size_t size);
8 | void * _IOLockAlloc(void);
9 | void _IOLockFree(void *lock);
10 | void _IOLockLock(void *locks);
11 | void _bzero(void *, size_t);
12 | void * _IOMallocAligned(vm_size_t size, vm_offset_t alignment);
13 | void * _IOMalloc(vm_size_t size);
14 | void * _IOMallocZero(vm_size_t size);
15 | void * _IOMallocData(vm_size_t size);
16 | void _IORecursiveLockUnlock(void *lock);
17 | void _IOLockUnlock(void *lock);
18 | void _IORecursiveLockLock(void *lock);
19 | void _IORWLockRead(void *lock);
20 | void _IORWLockWrite(void *lock);
21 | void _IORWLockUnlock(void *lock);
22 | void * _IOSimpleLockAlloc(void);
23 | void _IOSimpleLockDestroy(void *lock);
24 | void _IOSimpleLockFree(void *lock);
25 | void _IOSimpleLockLock(void *lock);
26 | void _IOSimpleLockInit(void *lock);
27 | void * _IOSimpleLockGetMachLock(void *lock);
28 | uint _IOSimpleLockLockDisableInterrupt(void *lock);
29 | bool _IOSimpleLockTryLock(void *lock);
30 | virtual IOWorkLoop * getWorkLoop();
31 | virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArguments *arguments, IOExternalMethodDispatch *dispatch, OSObject *target, void *reference);
32 | virtual IOReturn registerNotificationPort(ipc_port *port, UInt32 type, uint64_t * refCon);
33 | virtual IOReturn clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory);
34 | virtual IOReturn setProperties(OSDictionary *properties );
35 | //virtual IOExternalMethod * getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
36 | void * _ptmf2ptf(void *this,void *self, void *func);
37 | int _IORecursiveLockSleep(void *_lock, void *event, UInt32 interType);
38 | void IORecursiveLockWakeup(void *_lock, void *event, bool oneThread);
39 | void * kalloc_canblock (vm_size_t * size, boolean_t canblock, void * site);
40 |
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x36/ghidra_kernelcache/b0961b3cdfb96e8b86c89d73fdedf84affc01c77/utils/__init__.py
--------------------------------------------------------------------------------
/utils/custom_kc.py:
--------------------------------------------------------------------------------
1 | from helpers import *
2 | from __main__ import *
3 | import logging
4 | from utils.ios_kc import *
5 | from utils.iometa import ParseIOMeta
6 | from kext import *
7 | from iometa import ParseIOMeta
8 |
9 | def create_class_structures(vtab):
10 | pass
11 |
12 | class Custom(kernelCache):
13 | def __init__(self,objects,isKernel=False):
14 | print "Custom Kernel Creation"
15 | kernelCache.__init__(self,objects,macOS=True)
16 | self.sym_project = "macOS11.2.3"
17 | mn,mx = currentProgram.getMinAddress(),currentProgram.getMaxAddress()
18 | self.addrRange = AddressRangeImpl(mn,mx)
19 | self.ns = {}
20 | f = File( currentProgram.getExecutablePath())
21 | if f.exists() == False:
22 | f = askFile("Could not find the executable path","give a path:")
23 | self.read64 = lambda off: struct.unpack("> 32) & 0xffff
82 | meth_info = self._collect_method_info(cname,addr,None,tag,off)
83 | if meth_info == None:
84 | break
85 | setEOLComment(addr,hex(off))
86 | methods.append(meth_info)
87 | off+=8
88 | addr = addr.add(8)
89 |
90 | if external == False:
91 | self.vtables[cname].append(methods)
92 |
93 | def _collect_method_info(self,className,addr_ptr,methAddr,tag,offset):
94 | meth = {}
95 | meth["off"] = offset
96 | meth["pac"] = tag
97 | print className,addr_ptr,methAddr
98 | if methAddr == None:
99 | methAddr = getDataAt(addr_ptr)
100 | if methAddr == None:
101 | return None
102 | methAddr = methAddr.getValue()
103 | assert methAddr != None
104 | meth["methodAddr"] = int(methAddr.toString(),16)
105 |
106 |
107 | func = getFunctionAt(methAddr)
108 | signature = None
109 | funcName = None
110 | if func == None :
111 | fixLabel(methAddr)
112 | func = getFunctionAt(methAddr)
113 | if func == None:
114 | return None
115 |
116 | funcName = func.getName(True)
117 | sig = func.getSignature(True)
118 | sg = FunctionDefinitionDataType(sig)
119 | sg.setName(funcName)
120 | signature = sg.getPrototypeString(False)
121 | signature = signature[signature.find(" ")+1:]
122 | if "___cxa_pure_virtual" in signature:
123 | signature = "%s::virtual_method(void)" %(className)
124 | funcName = "%s::virtual_method"
125 |
126 | curr_ns = None
127 | mthod_ns = None
128 |
129 | if self.ns.has_key(className) == True:
130 | curr_ns = self.ns[className]
131 | else:
132 | curr_ns = self.symbolTable.getNamespace(className,None)
133 | self.ns[className] = curr_ns
134 | if curr_ns == None:
135 | curr_ns = self.create_namespace_custom(className)
136 | self.ns[className] = curr_ns
137 |
138 | assert curr_ns != None
139 | try:
140 | x = len(signature.split("::"))
141 | fns = signature.split("::")[x-2:x-1][0]
142 | except:
143 | return None
144 |
145 | if self.ns.has_key(fns) == True:
146 | meth_ns = self.ns[fns]
147 | else:
148 | meth_ns = self.symbolTable.getNamespace(fns,None)
149 | self.ns[fns] = meth_ns
150 |
151 | meth["signature"] = signature
152 | meth["name"] = funcName
153 | if meth_ns == None:
154 | meth["overriden"] = False
155 | return meth
156 |
157 | if curr_ns.toString() == meth_ns.toString():
158 | meth["overriden"] = True
159 | else :
160 | meth["overriden"] = False
161 |
162 | return meth
163 |
164 | def create_namespace_custom(self,name):
165 | new = self.symbolTable.createNameSpace(None,name,SourceType.USER_DEFINED)
166 | return new
167 |
168 | def prepare_iometa(self):
169 | names = self.vtables.keys()
170 | for name in names:
171 | print name, self.vtables[name]
172 |
--------------------------------------------------------------------------------
/utils/helpers.py:
--------------------------------------------------------------------------------
1 | from ghidra.app.services import DataTypeManagerService
2 | from ghidra.program.model.symbol import SourceType,SymbolTable,Namespace,RefType
3 | from ghidra.app.services import BlockModelService
4 | from ghidra.app.cmd.function import ApplyFunctionSignatureCmd
5 | from ghidra.app.decompiler import DecompileOptions,DecompInterface
6 | from ghidra.app.util.cparser.C.CParserUtils import parseSignature,handleParseProblem
7 | from ghidra.program.model.listing import Program, Parameter, ParameterImpl
8 | from ghidra.program.model.data import FunctionDefinition,GenericCallingConvention, \
9 | ParameterDefinitionImpl
10 | from ghidra.program.model.data import IntegerDataType, StructureDataType, UnsignedLongLongDataType, \
11 | PointerDataType,FunctionDefinitionDataType,TypedefDataType,VoidDataType
12 | from ghidra.framework.plugintool.util import OptionsService
13 | from ghidra.program.model.listing.Function import FunctionUpdateType
14 | from ghidra.program.model.pcode import PcodeOp,HighFunctionDBUtil
15 | #from ghidra.program.database.function import FunctionManager
16 | from ghidra.app.cmd.function import CreateFunctionCmd
17 | from generic.continues import RethrowContinuesFactory
18 | from ghidra.app.script import GhidraScript
19 | from ghidra.app.util.bin import ByteProvider
20 | from ghidra.app.util.bin import RandomAccessByteProvider
21 | from ghidra.app.util.bin import BinaryReader
22 | from ghidra.app.util.bin.format.macho import MachHeader
23 | from ghidra.app.util.bin.format.macho import Section
24 | from ghidra.app.util.bin.format.macho import commands
25 | from ghidra.program.model.address import Address
26 | from ghidra.program.model.address import AddressRangeImpl
27 |
28 | from java.io import File
29 | from java.io import ByteArrayInputStream;
30 | import struct
31 |
32 | import os,logging
33 | from __main__ import *
34 |
35 | def handle_tagged_pointer(ptr_addr,raw_ptr,className=None):
36 | func = getFunctionContaining(raw_ptr)
37 | if func == None:
38 | print("function is None at 0x%s 0x%s" %(ptr_addr,raw_ptr))
39 | func = createFunction(raw_ptr,className)
40 |
41 | currentProgram.getReferenceManager().removeAllReferencesFrom(ptr_addr)
42 | ref = currentProgram.getReferenceManager().addMemoryReference(ptr_addr,func.getEntryPoint(),
43 | RefType.COMPUTED_CALL,SourceType.USER_DEFINED,0)
44 | currentProgram.getReferenceManager().setPrimary(ref,True)
45 |
46 | return func
47 |
48 | def get_datatype_manager_by_name(name):
49 | tool = state.getTool()
50 | service = tool.getService(DataTypeManagerService)
51 | dataTypeManagers = service.getDataTypeManagers();
52 |
53 | for manager in dataTypeManagers:
54 | if manager.name == name:
55 | return manager
56 |
57 | return None
58 |
59 | def get_shared_dt_mgr(name):
60 | tool = state.getTool()
61 | service = tool.getService(DataTypeManagerService)
62 | dataTypeManagers = service.getDataTypeManagers();
63 |
64 | for manager in dataTypeManagers:
65 | if manager.name == name:
66 | return manager
67 |
68 | return None
69 |
70 | def get_decompiler():
71 | ifc = DecompInterface()
72 | DecOptions = DecompileOptions()
73 | service = state.getTool().getService(OptionsService)
74 |
75 | opt = service.getOptions("Decompiler")
76 | DecOptions.grabFromToolAndProgram(None, opt, currentProgram)
77 | ifc.setOptions(DecOptions)
78 |
79 | ifc.toggleCCode(True)
80 | ifc.toggleSyntaxTree(True)
81 | ifc.setSimplificationStyle("decompile")
82 |
83 | ifc.openProgram(currentProgram)
84 | return ifc
85 |
86 | def decompile_func(ifc,func):
87 | res = ifc.decompileFunction(func,ifc.options.defaultTimeout,monitor)
88 | if not res.decompileCompleted():
89 | print res.getErrorMessage()
90 | raise Exception("Decompilation is not completed")
91 |
92 | hfunc = res.getHighFunction()
93 | if hfunc == None:
94 | raise Exception("Cannot get HighFunction")
95 | return hfunc
96 |
97 | def debug_clangLine(lines,linum):
98 | for line in lines:
99 | if line.getLineNumber() != linum:
100 | continue
101 |
102 | print (line)
103 | tokens = line.getAllTokens()
104 | for token in tokens:
105 | print token, type(token),"opcode :", token.getPcodeOp()
106 |
107 | def addTypeDef(name,nametype):
108 | isPtr = False
109 | dtm = currentProgram.getDataTypeManager()
110 | if "*" in nametype:
111 | nametype = nametype.replace("*","")
112 | isPtr = True
113 |
114 | aType = find_dt(nametype)
115 | if aType == None:
116 | return
117 | category = aType.getCategoryPath()
118 | if isPtr:
119 | newtype = TypedefDataType(category,name,PointerDataType(aType),dtm)
120 | else:
121 | newtype = TypedefDataType(category,name,aType,dtm)
122 |
123 | dtm.addDataType(newtype,None)
124 |
125 | def DeclareDataTypes():
126 | addTypeDef("IOOptionBits","uint")
127 | addTypeDef("UInt32","uint")
128 | addTypeDef("IOReturn","uint")
129 | addTypeDef("IODirection","ulonglong")
130 | addTypeDef("IOVirtualAddress","ulonglong")
131 | addTypeDef("IOByteCount","ulonglong")
132 | #addTypeDef("task","pointer64")
133 | addTypeDef("task","void")
134 | addTypeDef("OSMetaClassBase","ulonglong")
135 | addTypeDef("DestinationOrSource","uint")
136 | addTypeDef("socVersion","uint")
137 | addTypeDef("tUSBHostPortType","uint")
138 | addTypeDef("IOHIDReportType","uint")
139 | addTypeDef("IOReportChannelType","uint")
140 | addTypeDef("tUSBLinkState","uint")
141 | addTypeDef("IO80211LinkState","uint")
142 | addTypeDef("IOMbufServiceClass","ulonglong")
143 | addTypeDef("ChromaOrLuma","uint")
144 | addTypeDef("VerticalOrHorizontal","uint")
145 | addTypeDef("CCTimestamp","uint")
146 | addTypeDef("IORPC","uint")
147 | addTypeDef("IOPhysicalAddress","ulonglong")
148 | addTypeDef("IOAddressSegment","ulonglong")
149 | addTypeDef("IOAddressRange","ulonglong")
150 | addTypeDef("IOByteCount","ulonglong")
151 | addTypeDef("AbsoluteTime","ulonglong")
152 | addTypeDef("IOLock","ulonglong")
153 | addTypeDef("size_t","ulonglong")
154 | addTypeDef("u64","ulonglong")
155 | addTypeDef("ipc_port","ulonglong")
156 | addTypeDef("IOExternalMethodDispatch","void")
157 | addTypeDef("u32","uint")
158 | addTypeDef("IOReturn","uint")
159 |
160 | def get_symbols_of(name):
161 | mgr = currentProgram.getSymbolTable()
162 | return mgr.getSymbols(name)
163 |
164 | # Better Load Them from old projects
165 | def defineIOExternalMethodArguments():
166 |
167 | dtm = currentProgram.getDataTypeManager()
168 | dt = find_struct("IOExternalMethodArguments")
169 | IOMemoryDescriptor = find_struct("IOMemoryDescriptor")
170 | if IOMemoryDescriptor == None:
171 | IOMemoryDescriptor = dtm.getDataType("/ulonglong")
172 |
173 | new = None
174 | if dt == None:
175 | dt = StructureDataType("IOExternalMethodArguments",0)
176 | new = dt
177 | """
178 | elif dt.getLength() > 1:
179 | yes = askYesNo("IOExternalMethodArguments",
180 | "[-] Looks like IOExternalMethodArguments is already defined, continue ?")
181 | if yes == False:
182 | exit()
183 | """
184 | uint = dtm.getDataType("/uint")
185 | ulonglong= dtm.getDataType("/ulonglong")
186 |
187 | st = dt
188 | st.add(uint,"version","")
189 | st.add(uint,"selector","")
190 |
191 | st.add(ulonglong,"asyncWakePort","")
192 | st.add(PointerDataType(uint),"asyncReference","")
193 | st.add(uint,"asyncReferenceCount","")
194 |
195 | st.add(PointerDataType(ulonglong),"scalarInput","")
196 | st.add(uint,"scalarInputCount","")
197 | st.add(PointerDataType(ulonglong),"structureInput","")
198 | st.add(uint,"structureInputSize","")
199 |
200 | st.add(PointerDataType(IOMemoryDescriptor),"StructureInputDescriptor","")
201 |
202 | st.add(PointerDataType(ulonglong),"scalarOutput","")
203 | st.add(uint,"scalarOutputCount","")
204 |
205 | st.add(PointerDataType(ulonglong),"structureOutput","")
206 | st.add(uint,"structureOutputSize","")
207 |
208 | st.add(PointerDataType(IOMemoryDescriptor),"structureOutputDescriptor","")
209 | st.add(uint,"structureOutputDescriptorSize","")
210 |
211 | st.add(uint,"__reservedA","")
212 | st.add(PointerDataType(ulonglong),"structureVariableOutputData","")
213 | #st.setInternallyAligned(True)
214 | if new :
215 | dtm.addDataType(new,None)
216 | dtm.addDataType(PointerDataType(new),None)
217 |
218 | def defineIOExternalTrap():
219 | dtm = currentProgram.getDataTypeManager()
220 | dt = dtm.findDataType(currentProgram.getName()+ "/"+"IOExternalTrap")
221 |
222 |
223 | uint = dtm.getDataType("/uint")
224 | IOService = dtm.getDataType("/IOService")
225 | IOTrap_def = "IOService::IOTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)"
226 |
227 | fdef = FunctionDefinitionDataType(IOTrap_def)
228 | fdef.setReturnType(uint)
229 | fdef.setGenericCallingConvention(GenericCallingConvention.thiscall)
230 |
231 | st = StructureDataType("IOExternalTrap", 0)
232 | #st.setToMachineAlignment()
233 | st.setExplicitPackingValue(8)
234 | st.setExplicitPackingValue(8)
235 | st.add(PointerDataType(IOService),"object","")
236 | st.add(PointerDataType(fdef),"func","")
237 |
238 | dtm.addDataType(PointerDataType(st),None)
239 |
240 | def defineIOExternalMethod():
241 | dtm = currentProgram.getDataTypeManager()
242 | dt = dtm.findDataType(currentProgram.getName()+ "/"+"IOExternalMethod")
243 |
244 | IOService = dtm.getDataType("/IOService")
245 | IOMethod_def = "uint IOService::IOMethod(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)"
246 | uint = dtm.getDataType("/uint")
247 | ulonglong= dtm.getDataType("/ulonglong")
248 |
249 | fdef = parseCSignature(IOMethod_def)
250 | st = StructureDataType("IOExternalMethod", 0)
251 |
252 | # st.setToMachineAlignment()
253 | st.setExplicitPackingValue(8)
254 | st.add(PointerDataType(IOService),"object","")
255 | st.add(PointerDataType(fdef),"func","")
256 | st.add(uint,"flags","")
257 | st.add(ulonglong,"count0","")
258 | st.add(ulonglong,"count1","")
259 |
260 | dtm.addDataType(PointerDataType(st),None)
261 |
262 | def defineIOExternalAsyncMethod():
263 | dtm = currentProgram.getDataTypeManager()
264 | dt = dtm.findDataType(currentProgram.getName()+ "/"+"IOExternalAsyncMethod")
265 |
266 | IOService = dtm.getDataType("/IOService")
267 | IOAsyncMethod_def = "uint IOService::IOAsyncMethod(uint asyncRef[8], void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)"
268 |
269 | uint = dtm.getDataType("/uint")
270 | ulonglong= dtm.getDataType("/ulonglong")
271 | fdef = parseCSignature(IOAsyncMethod_def)
272 | st = StructureDataType("IOExternalAsyncMethod", 0)
273 |
274 | st.setExplicitPackingValue(8)
275 | st.add(PointerDataType(IOService),"object","")
276 | st.add(PointerDataType(fdef),"func","")
277 | st.add(uint,"flags","")
278 | st.add(ulonglong,"count0","")
279 | st.add(ulonglong,"count1","")
280 |
281 | dtm.addDataType(PointerDataType(st),None)
282 |
283 | def fixLabel(data):
284 | name = getSymbolAt(data).getName()
285 | labelAddress = getSymbolAt(data).getAddress()
286 | # ghidra refers to some functions as data, I've seen only one case
287 | labelName = name.replace("LAB_","FUN_")
288 | if disassemble(labelAddress) == False:
289 | popup("This Label "+ labelAddress + "cannot be disassembled !")
290 | return -1
291 | ret = createFunction(labelAddress,labelName)
292 | func = getFunctionAt(labelAddress)
293 | if func == None:
294 | # Calling CreateFunction twice will force function creation
295 | # Don't ask me,ask NSA
296 | ret = createFunction(labelAddress,labelName)
297 |
298 | func = getFunctionAt(labelAddress)
299 | if(func == None):
300 | listing = currentProgram.getListing()
301 | blockModelService = state.getTool().getService(BlockModelService)
302 | cbm = blockModelService.getActiveSubroutineModel()
303 | cbIter = cbm.getCodeBlocksContaining(labelAddress, monitor)
304 | l = labelAddress
305 | currentProgram.getListing().clearCodeUnits(l,l.add(8),True)
306 | createFunction(labelAddress,"FUN_"+name)
307 |
308 | func = getFunctionAt(labelAddress)
309 | if(func == None):
310 | return
311 | func.setCustomVariableStorage(False)
312 | df = FunctionDefinitionDataType(func,False)
313 |
314 | # TODO : remove the below line , no need to change calling convention
315 | #df.setGenericCallingConvention(GenericCallingConvention.thiscall)
316 | df.setReturnType(func.getReturnType())
317 |
318 | #df = FunctionDefinitionDataType(func,False)
319 | """
320 | func.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,#CUSTOM_STORAGE,
321 | True,
322 | SourceType.USER_DEFINED,
323 | params)
324 | """
325 | x = ApplyFunctionSignatureCmd(func.getEntryPoint(),df,SourceType.USER_DEFINED)
326 | x.applyTo(func.getProgram())
327 | return func
328 |
329 | def defineLabel(symtab,namespace,addr,methodName):
330 | sym = getSymbolAt(addr)
331 | if sym == None:
332 | return
333 | src = sym.getSource()
334 | #The method assumes it's already defined a function
335 | if "FUN_" not in sym.getName():
336 | return
337 | symtab.createLabel(addr,methodName,namespace,SourceType.ANALYSIS)
338 |
339 | def makePTR(addr):
340 | PTR = currentProgram.getDataTypeManager().getDataType("/pointer")
341 | currentProgram.getListing().createData(addr, PTR)
342 |
343 | def makeUint(addr,comment):
344 | uint_dt = currentProgram.getDataTypeManager().getDataType("/uint")
345 | currentProgram.getListing().createData(addr, uint_dt)
346 | #setEOLComment(addr,comment)
347 |
348 | def makeULongLong(addr,comment= None):
349 | #addr = toAddr(addr)
350 | #uint_dt = currentProgram.getDataTypeManager().getDataType("/ulonglong")
351 | uint_dt = currentProgram.getDataTypeManager().getDataType("/qword")
352 | currentProgram.getListing().createData(addr, uint_dt)
353 |
354 |
355 | def prepareClassName(className,classSize):
356 | locs = ["/","/Demangler/"]
357 | for location in locs:
358 | res = findDataTypeByName(location+className)
359 | if res:
360 | return
361 |
362 | class_struct = StructureDataType(className,0)
363 | currentProgram.getDataTypeManager().addDataType(class_struct,None)
364 |
365 |
366 | def parseCSignature(text):
367 | tool = state.getTool()
368 | service = tool.getService(DataTypeManagerService)
369 | dtm = currentProgram.getDataTypeManager()
370 | df = None
371 |
372 | try:
373 | df =parseSignature(service,currentProgram,text,False)
374 | except ghidra.app.util.cparser.C.ParseException as e:
375 | # Loosy workaround , i will get back to it later
376 | off = text.find("(")
377 | logger.warnign("[!] Please fix the definition of %s" % (text))
378 | text = text[:off]+"()"
379 |
380 | df = parseSignature(service,currentProgram,text,True)
381 |
382 |
383 | if df == None:
384 | return None
385 | df.setGenericCallingConvention(GenericCallingConvention.thiscall)
386 |
387 | #dtm.addDataType(PointerDataType(df),None)
388 | return df
389 |
390 | def findDataTypeByName(name):
391 | tool = state.getTool()
392 | service = tool.getService(DataTypeManagerService)
393 | dataTypeManagers = service.getDataTypeManagers();
394 |
395 | for manager in dataTypeManagers:
396 | dataType = manager.getDataType(name)
397 | if dataType :
398 | return dataType
399 |
400 | return None
401 |
402 | def find_struct(name):
403 | return find_dt(name)
404 |
405 | def find_dt(name):
406 | locs = ["/","/Demangler/"]
407 | for location in locs:
408 | dt = findDataTypeByName(location+name)
409 | if dt:
410 | return dt
411 |
412 | return None
413 |
414 | def find_funcdef(name):
415 | dt = findDataTypeByName("/functions/"+name)
416 | if dt : return dt
417 | return findDataTypeByName("/"+name)
418 |
419 |
420 | # Defines some mandatory class structures for the kernelcache
421 | def prepare():
422 | DeclareDataTypes()
423 | defineIOExternalMethodArguments()
424 | defineIOExternalTrap()
425 | defineIOExternalMethod()
426 | defineIOExternalAsyncMethod()
427 | #currentProgram.getDataTypeManager().endTransaction(tid)
428 |
429 | def setup_logging(name,level=logging.DEBUG):
430 | #symbolTable = currentProgram.getSymbolTable()
431 | #logging.basicConfig(filename='/tmp/debug.log',level=level)
432 |
433 | log = logging.getLogger(name)
434 | log.setLevel(level)
435 |
436 | ch = logging.StreamHandler()
437 | ch.setLevel(level)
438 | #formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s: %(message)s')
439 | formatter = logging.Formatter('%(levelname)s: %(message)s')
440 | ch.setFormatter(formatter)
441 |
442 | log.addHandler(ch)
443 |
444 | return log
445 |
--------------------------------------------------------------------------------
/utils/iometa.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import re
3 |
4 | class ParseIOMeta(object):
5 | def __init__(self,filename):
6 | self.filename = filename
7 | self.data = []
8 | self.cursor = 0
9 | self.thisObject = "" # current Object Name
10 | self.thisMethodsTable = [] # Hold a list of MethodInfo dictionary
11 | # Holds full information {"thisObject" : ..... }
12 | self.Objects = {}
13 |
14 | self.parseObjects()
15 |
16 | def _getObjectHead(self):
17 | for line in self.data:
18 | if "vtab=" in line: # means a new object to be parsed
19 | # save self.thisMethodsTable to the previous object
20 | if len(self.thisMethodsTable) != 0:
21 | self.Objects[self.thisObject].append(self.thisMethodsTable) # Takes index 1
22 | self.thisMethodsTable = []
23 | self.thisObject = ""
24 |
25 | self._parseVtableInfo()
26 | self.cursor += 1
27 | continue
28 |
29 | self._parseMethod()
30 | self.cursor += 1
31 |
32 | # the last one must be added as well
33 | if len(self.thisMethodsTable) != 0:
34 | self.Objects[self.thisObject].append(self.thisMethodsTable) # Takes index 1
35 | self.thisMethodsTable = []
36 | self.thisObject = ""
37 |
38 | def _printMethod(self,methodDict,overridenOnly=False):
39 | fmt = "0x%x func=0x%lx overrides=0x%lx pac=0x%x %s"
40 | m = methodDict
41 | if overridenOnly == True and m['methodAddr'] != m['overrides']:
42 | print( "OVERRIDEN: ", fmt %(m['off'],m['methodAddr'],m['overrides'],m['pac'],m['name']))
43 | elif overridenOnly == False:
44 | print(fmt %(m['off'],m['methodAddr'],m['overrides'],m['pac'],m['name']))
45 |
46 | def printAll(self,overriden=False):
47 | for className,infos in self.Objects.items():
48 | if len(infos) != 2:
49 | continue
50 | classInfo,methodsInfo = infos[0],infos[1]
51 | classInfo,methodsInfo = infos[0],infos[1]
52 | for methodInfo in methodsInfo:
53 | self._printMethod(methodInfo,overriden)
54 |
55 | def _resolveSymbolName(self,stringName):
56 | name = stringName
57 | if "(" in name:
58 | name = name.split("(")[0]
59 | return name
60 |
61 |
62 | def _parseMethod(self):
63 | line = self.data[self.cursor]
64 | if len(line) == 0:
65 | return
66 | pattern = ".*(\S+)\W+func=(\S+)\W+overrides=(\S+)\W+pac=(\S+)\W+(\S+\(.*\))"
67 | match = re.search(pattern,line)
68 |
69 | idx = line.find("pac=")
70 | idx+= line[idx:].find(" ")
71 | signature = line[idx+1:]
72 | if match == None or len(match.groups()) < 5:
73 | raise Exception("Failed to parse RE")
74 |
75 | off = int(match.group(1),16)
76 | methodAddr = int(match.group(2),16)
77 | overrides = int(match.group(3),16)
78 | pac = int(match.group(4),16)
79 | signature = match.group(5)
80 |
81 | methodName = self._resolveSymbolName(signature) # to be fixed later
82 |
83 | thisMethodDict = {
84 | "name": methodName,
85 | "off" : off,
86 | "methodAddr": methodAddr,
87 | "overriden" : methodAddr != overrides,
88 | "overrides" : overrides,
89 | "pac" : pac,
90 | "signature" : signature
91 | }
92 |
93 | self.thisMethodsTable.append(thisMethodDict)
94 |
95 | def getObjectInfoByName(self,className):
96 | classesIter = self.Objects.keys()
97 | if className not in classesIter:
98 | return
99 |
100 | return self.Objects[className]
101 |
102 |
103 | def printOverridenMethodsByClassName(self,className):
104 |
105 | infos = self.getObjectInfoByName(className)
106 | if len(infos) != 2:
107 | return
108 |
109 | classInfo,methodsInfo = infos[0],infos[1]
110 | for method in methodsInfo:
111 | self._printMethod(method,overridenOnly=True)
112 |
113 |
114 | def printOverridenMethodsByBundle(self,bundle):
115 | classes = []
116 | for name,infos in self.Objects.items():
117 | classInfo = infos[0]
118 | if bundle in classInfo['bundle']:
119 | classes.append(name)
120 |
121 | if len(classes) == 0:
122 | print( "[-] %s is invalid" %(bundle))
123 | return
124 |
125 | for className in classes:
126 | self.printOverridenMethodsByClassName(className)
127 |
128 |
129 | def _parseVtableInfo(self):
130 | c = self.cursor
131 | line = self.data[c]
132 |
133 | pattern = "^vtab=(\S+)\W+size=(\S+)\W+meta=(\S+)\W+parent=(\S+)\W+metavtab=(\S+)\W+(\S+)\W+\((\S+)\)$"
134 | match = re.search(pattern, line)
135 | if match == None or len(match.groups()) != 7 :
136 | raise Exception ("Failed to parse vtable infos")
137 |
138 | try:
139 | vtab = int(match.group(1),16)
140 | except:
141 | #print("[-] Please go and remove '%s' line from iometa output and repeat "
142 | # %(match.group(1)))
143 | return
144 | size = int(match.group(2),16)
145 | meta = int(match.group(3),16)
146 | parent =int(match.group(4),16)
147 | metavtab = int(match.group(5),16)
148 | className = match.group(6)
149 | bundle = match.group(7)
150 | self.thisObject = className
151 |
152 | objectInfoDict = {
153 | "className": self.thisObject,
154 | "vtab" : vtab,
155 | "size" : size,
156 | "meta" : meta,
157 | "parent": parent,
158 | "metavtab" : metavtab,
159 | "bundle" : bundle
160 | }
161 | self.Objects[self.thisObject] = [objectInfoDict]
162 |
163 | def parseObjects(self):
164 | self.f = open(self.filename)
165 | self.data = self.f.read().split("\n")
166 | self._getObjectHead()
167 |
168 | def getObjects(self):
169 | return self.Objects
170 |
171 | def saveObject(self,name):
172 | print( "[+] Save symbol database in %s" %(name))
173 | handle = open('%s' %(name), 'wb')
174 | pickle.dump(self.Objects, handle, protocol=pickle.HIGHEST_PROTOCOL)
175 |
176 | if __name__ == "__main__":
177 |
178 | if len(sys.argv) != 3:
179 | print( "%s