hilda 0.1.2__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hilda/hilda_client.py +55 -35
- hilda/launch_lldb.py +20 -0
- hilda/lldb_entrypoint.py +3 -1
- hilda/objective_c_class.py +3 -2
- hilda/objective_c_symbol.py +3 -3
- hilda/snippets/boringssl.py +26 -0
- hilda/snippets/dyld.py +1 -2
- hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py +58 -9
- hilda/snippets/macho/all_image_infos.py +2 -2
- hilda/snippets/macho/apple_version.py +1 -1
- hilda/snippets/macho/image_info.py +1 -1
- hilda/snippets/macho/macho.py +2 -1
- hilda/snippets/macho/macho_load_commands.py +2 -3
- hilda/snippets/remotepairingd.py +12 -18
- hilda/snippets/uuid.py +1 -1
- hilda/snippets/xpc.py +9 -0
- hilda/symbol.py +9 -5
- hilda/symbols_jar.py +1 -1
- hilda/ui/colors.json +13 -0
- hilda/ui/ui_manager.py +74 -0
- hilda/ui/views.py +217 -0
- hilda-0.3.0.dist-info/LICENSE +20 -0
- {hilda-0.1.2.dist-info → hilda-0.3.0.dist-info}/METADATA +113 -13
- hilda-0.3.0.dist-info/RECORD +44 -0
- {hilda-0.1.2.dist-info → hilda-0.3.0.dist-info}/WHEEL +1 -1
- {hilda-0.1.2.dist-info → hilda-0.3.0.dist-info}/top_level.txt +0 -1
- hilda-0.1.2.dist-info/RECORD +0 -44
- tests/__init__.py +0 -0
- tests/__main__.py +0 -4
- tests/conftest.py +0 -21
- tests/hilda_tests.py +0 -20
- tests/lldb_entrypoint.py +0 -33
- {hilda-0.1.2.dist-info → hilda-0.3.0.dist-info}/entry_points.txt +0 -0
hilda/ui/ui_manager.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections import OrderedDict
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from hilda.ui.views import BackTraceView, DisassemblyView, RegistersView, StackView
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DotDict(OrderedDict):
|
|
9
|
+
""" Extends `OrderedDict` to access items using dot """
|
|
10
|
+
__slots__ = ["__recursion_lock__"]
|
|
11
|
+
|
|
12
|
+
def __getattr__(self, name):
|
|
13
|
+
try:
|
|
14
|
+
if name in self.__slots__:
|
|
15
|
+
return object.__getattribute__(self, name)
|
|
16
|
+
else:
|
|
17
|
+
return self[name]
|
|
18
|
+
except KeyError:
|
|
19
|
+
raise AttributeError(name)
|
|
20
|
+
|
|
21
|
+
def __setattr__(self, name, value):
|
|
22
|
+
try:
|
|
23
|
+
if name in self.__slots__:
|
|
24
|
+
return object.__setattr__(self, name, value)
|
|
25
|
+
else:
|
|
26
|
+
self[name] = value
|
|
27
|
+
except KeyError:
|
|
28
|
+
raise AttributeError(name)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ColorScheme(DotDict):
|
|
32
|
+
def __init__(self, scheme: Path):
|
|
33
|
+
with scheme.open('r') as f:
|
|
34
|
+
data = json.load(f)
|
|
35
|
+
super().__init__(data)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ViewsManager(DotDict):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class UiManager:
|
|
43
|
+
"""
|
|
44
|
+
Manages Hilda's UI.
|
|
45
|
+
|
|
46
|
+
- New views can be added to `ViewManager` (Must be inherent `Views`)
|
|
47
|
+
- Colors can be changed from terminal (Setting `ui_manager.color.title = 'green'` or be modifying `colors.json`)
|
|
48
|
+
- Views can be disabled from terminal (Setting `ui_manager.color.title=False`)
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, hilda_client, scheme_file=Path(__file__).parent / 'colors.json',
|
|
52
|
+
active: bool = True):
|
|
53
|
+
"""
|
|
54
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
55
|
+
:param scheme_file: pathlib.Path
|
|
56
|
+
:param active: bool
|
|
57
|
+
"""
|
|
58
|
+
self.colors = ColorScheme(scheme_file)
|
|
59
|
+
self.views = ViewsManager({
|
|
60
|
+
'registers': RegistersView(hilda_client, self.colors),
|
|
61
|
+
'disassembly': DisassemblyView(hilda_client, self.colors),
|
|
62
|
+
'stack': StackView(hilda_client, self.colors),
|
|
63
|
+
'backtrace': BackTraceView(hilda_client, self.colors)
|
|
64
|
+
})
|
|
65
|
+
self.active = active
|
|
66
|
+
|
|
67
|
+
def show(self, *args) -> None:
|
|
68
|
+
fmt_parts = []
|
|
69
|
+
|
|
70
|
+
for view in self.views.values():
|
|
71
|
+
if view.active is False:
|
|
72
|
+
continue
|
|
73
|
+
fmt_parts.append(str(view))
|
|
74
|
+
print('\n'.join(fmt_parts))
|
hilda/ui/views.py
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from abc import abstractmethod
|
|
3
|
+
from typing import List, Mapping
|
|
4
|
+
|
|
5
|
+
from click import style
|
|
6
|
+
from lldb import SBAddress
|
|
7
|
+
from tabulate import tabulate
|
|
8
|
+
|
|
9
|
+
WORD_SIZE = 8
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def dict_diff(d1: Mapping, d2: Mapping) -> List[str]:
|
|
13
|
+
""" Returns a list of keys whose values have changed """
|
|
14
|
+
changed_keys = []
|
|
15
|
+
if d1 is None or d2 is None:
|
|
16
|
+
return changed_keys
|
|
17
|
+
for k, v in d1.items():
|
|
18
|
+
if k in d2 and d2[k] != v:
|
|
19
|
+
changed_keys.append(k)
|
|
20
|
+
return changed_keys
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class View:
|
|
24
|
+
""" Base class of view"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, hilda_client, title, color_scheme):
|
|
27
|
+
"""
|
|
28
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
29
|
+
:param title: str
|
|
30
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
31
|
+
"""
|
|
32
|
+
self.title = title
|
|
33
|
+
self.hilda = hilda_client
|
|
34
|
+
self.active = True
|
|
35
|
+
self.color_scheme = color_scheme
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def __str__(self) -> str:
|
|
39
|
+
return self._format_title()
|
|
40
|
+
|
|
41
|
+
def _format_title(self) -> str:
|
|
42
|
+
terminal_size = shutil.get_terminal_size()
|
|
43
|
+
fmt = style(self.title.center(terminal_size.columns, '─'), fg=self.color_scheme.title)
|
|
44
|
+
fmt += '\n'
|
|
45
|
+
return fmt
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class StackView(View):
|
|
49
|
+
""" Implements stack view """
|
|
50
|
+
DEFAULT_STACK_DEPTH = 10
|
|
51
|
+
|
|
52
|
+
def __init__(self, hilda_client, color_scheme, depth=DEFAULT_STACK_DEPTH):
|
|
53
|
+
"""
|
|
54
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
55
|
+
:param depth: int
|
|
56
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
57
|
+
|
|
58
|
+
`prev` saves the last stack stats inorder to perform diff check.
|
|
59
|
+
"""
|
|
60
|
+
super().__init__(hilda_client, 'Stack', color_scheme)
|
|
61
|
+
self.depth = depth
|
|
62
|
+
self.prev: Mapping[int, str] = None
|
|
63
|
+
|
|
64
|
+
def __str__(self) -> str:
|
|
65
|
+
""" Format stack view for printing """
|
|
66
|
+
stack_mapping = self._create_mapping()
|
|
67
|
+
diff_in_keys = dict_diff(stack_mapping, self.prev)
|
|
68
|
+
self.prev = stack_mapping.copy()
|
|
69
|
+
fmt_parts = []
|
|
70
|
+
offset = 0
|
|
71
|
+
for k, v in stack_mapping.items():
|
|
72
|
+
data_color = self.color_scheme.stack_data if k not in diff_in_keys else self.color_scheme.diff
|
|
73
|
+
fmt = f'{style(hex(k), fg=self.color_scheme.address)}|+' \
|
|
74
|
+
f'{style(hex(offset), fg=self.color_scheme.stack_offset)}: ' \
|
|
75
|
+
f'{style(v, fg=data_color)}'
|
|
76
|
+
if offset == 0:
|
|
77
|
+
fmt += f'{"<-- $sp":^50}'
|
|
78
|
+
offset += WORD_SIZE
|
|
79
|
+
fmt_parts.append(fmt)
|
|
80
|
+
|
|
81
|
+
return super().__str__() + '\n'.join(fmt_parts)
|
|
82
|
+
|
|
83
|
+
def _create_mapping(self) -> Mapping[int, str]:
|
|
84
|
+
""" Generate mapping of stack address:data"""
|
|
85
|
+
base_addr = self.hilda.frame.sp
|
|
86
|
+
stack_mapping = {}
|
|
87
|
+
for i in range(0, self.depth * WORD_SIZE, WORD_SIZE):
|
|
88
|
+
current = base_addr + i
|
|
89
|
+
stack_mapping[current] = '0x' + self.hilda.symbol(current).peek(WORD_SIZE).hex()
|
|
90
|
+
return stack_mapping
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class RegistersView(View):
|
|
94
|
+
""" Implements registers view """
|
|
95
|
+
DEFAULT_REGISTERS_TYPE = 'general'
|
|
96
|
+
|
|
97
|
+
def __init__(self, hilda_client, color_scheme, rtype=DEFAULT_REGISTERS_TYPE):
|
|
98
|
+
"""
|
|
99
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
100
|
+
:param rtype: str
|
|
101
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
102
|
+
|
|
103
|
+
`prev` saves the last registers stats inorder to perform diff check.
|
|
104
|
+
"""
|
|
105
|
+
super().__init__(hilda_client, 'Registers', color_scheme)
|
|
106
|
+
self.prev: Mapping[str, str] = None
|
|
107
|
+
self.rtype = rtype
|
|
108
|
+
|
|
109
|
+
def __str__(self) -> str:
|
|
110
|
+
""" Format registers view for printing"""
|
|
111
|
+
regs_mapping = self._create_mapping()
|
|
112
|
+
diff_in_keys = dict_diff(regs_mapping, self.prev)
|
|
113
|
+
self.prev = regs_mapping.copy()
|
|
114
|
+
list_of_lists = []
|
|
115
|
+
names = []
|
|
116
|
+
values = []
|
|
117
|
+
i = 0
|
|
118
|
+
|
|
119
|
+
# Divide the registers into columns of 16
|
|
120
|
+
for k, v in regs_mapping.items():
|
|
121
|
+
if i % 16 == 0 and i != 0:
|
|
122
|
+
list_of_lists.append(names.copy())
|
|
123
|
+
list_of_lists.append(values.copy())
|
|
124
|
+
names = []
|
|
125
|
+
values = []
|
|
126
|
+
|
|
127
|
+
names.append(style(k, fg=self.color_scheme.regs_name))
|
|
128
|
+
if k in diff_in_keys:
|
|
129
|
+
values.append(style(v, fg=self.color_scheme.diff))
|
|
130
|
+
else:
|
|
131
|
+
values.append(style(v, fg=self.color_scheme.regs_value))
|
|
132
|
+
i += 1
|
|
133
|
+
|
|
134
|
+
return super().__str__() + tabulate(list(zip(*list_of_lists)), tablefmt='plain', numalign='left')
|
|
135
|
+
|
|
136
|
+
def _create_mapping(self) -> Mapping[str, str]:
|
|
137
|
+
""" Generate mapping of registers name:data"""
|
|
138
|
+
regs = self._get_registers()
|
|
139
|
+
regs_mapping = {}
|
|
140
|
+
for reg in regs:
|
|
141
|
+
regs_mapping[reg.GetName()] = reg.GetValue()
|
|
142
|
+
return regs_mapping
|
|
143
|
+
|
|
144
|
+
def _get_registers(self):
|
|
145
|
+
"""
|
|
146
|
+
Returns list of registers grouped by type.
|
|
147
|
+
Available types: [general,floating]
|
|
148
|
+
:return: lldb.SBValueList
|
|
149
|
+
"""
|
|
150
|
+
registers_set = self.hilda.frame.GetRegisters()
|
|
151
|
+
for value in registers_set:
|
|
152
|
+
if self.rtype.lower() in value.GetName().lower():
|
|
153
|
+
return value
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class DisassemblyView(View):
|
|
158
|
+
""" Implements disassembly view """
|
|
159
|
+
DEFAULT_INSTRUCTION_COUNT = 5
|
|
160
|
+
DEFAULT_DISASSEMBLY_FLAVOR = 'intel'
|
|
161
|
+
|
|
162
|
+
def __init__(self, hilda_client, color_scheme, instruction_count=DEFAULT_INSTRUCTION_COUNT,
|
|
163
|
+
flavor=DEFAULT_DISASSEMBLY_FLAVOR):
|
|
164
|
+
"""
|
|
165
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
166
|
+
:param instruction_count: int
|
|
167
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
168
|
+
"""
|
|
169
|
+
super().__init__(hilda_client, 'Disassembly', color_scheme)
|
|
170
|
+
self.instruction_count = instruction_count
|
|
171
|
+
self.flavor = flavor
|
|
172
|
+
|
|
173
|
+
def __str__(self) -> str:
|
|
174
|
+
""" Format disassembly view for printing """
|
|
175
|
+
pc = self.hilda.frame.pc
|
|
176
|
+
target = self.hilda.target
|
|
177
|
+
|
|
178
|
+
disass = target.ReadInstructions(SBAddress(pc, target), self.instruction_count, self.flavor)
|
|
179
|
+
fmt_parts = []
|
|
180
|
+
for inst in disass:
|
|
181
|
+
load_addr = inst.addr.GetLoadAddress(self.hilda.target)
|
|
182
|
+
base_name = style(inst.addr.module.file.basename, self.color_scheme.basename)
|
|
183
|
+
addr = style(hex(load_addr), fg=self.color_scheme.address)
|
|
184
|
+
mnemonic = style(inst.GetMnemonic(self.hilda.target), fg=self.color_scheme.mnemonic)
|
|
185
|
+
operands = style(inst.GetOperands(self.hilda.target), fg=self.color_scheme.operands)
|
|
186
|
+
fmt = f'{base_name}[{addr}]: {mnemonic} {operands}'
|
|
187
|
+
if load_addr == self.hilda.frame.pc:
|
|
188
|
+
fmt += f'{"<-- $pc":^50}'
|
|
189
|
+
fmt_parts.append(fmt)
|
|
190
|
+
return super().__str__() + '\n'.join(fmt_parts)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class BackTraceView(View):
|
|
194
|
+
""" Implements backtrace view """
|
|
195
|
+
DEFAULT_BACKTRACE_DEPTH = 5
|
|
196
|
+
|
|
197
|
+
def __init__(self, hilda_client, color_scheme, depth=DEFAULT_BACKTRACE_DEPTH):
|
|
198
|
+
"""
|
|
199
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
200
|
+
:param depth: int
|
|
201
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
202
|
+
"""
|
|
203
|
+
super().__init__(hilda_client, 'BackTrace', color_scheme)
|
|
204
|
+
self.depth = depth
|
|
205
|
+
|
|
206
|
+
def __str__(self) -> str:
|
|
207
|
+
""" Format backtrace view for printing"""
|
|
208
|
+
bt = self.hilda.bt(should_print=False, depth=self.depth)
|
|
209
|
+
bt_colored = []
|
|
210
|
+
for pair in bt:
|
|
211
|
+
bt_colored.append(
|
|
212
|
+
[
|
|
213
|
+
style(pair[0], fg=self.color_scheme.address),
|
|
214
|
+
pair[1]
|
|
215
|
+
]
|
|
216
|
+
)
|
|
217
|
+
return super().__str__() + tabulate(bt_colored, tablefmt='plain', numalign='left')
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2012-2023 Doron Zarhi and Metan Perelman
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hilda
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: LLDB wrapped and empowered by iPython's features
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
Author-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>, netanel <matan1008@gmail.com>
|
|
6
|
+
Maintainer-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
|
|
7
|
+
License: Copyright (c) 2012-2023 Doron Zarhi and Metan Perelman
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
10
|
+
a copy of this software and associated documentation files (the
|
|
11
|
+
"Software"), to deal in the Software without restriction, including
|
|
12
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
13
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
14
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
15
|
+
the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be
|
|
18
|
+
included in all copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
21
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
22
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
23
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
24
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
25
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
26
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
27
|
+
Project-URL: Homepage, https://github.com/doronz88/hilda
|
|
28
|
+
Project-URL: Bug Reports, https://github.com/doronz88/hilda/issues
|
|
29
|
+
Keywords: python,debugger,lldb,ipython,ios,debug
|
|
30
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
33
|
Classifier: Programming Language :: Python :: 3.8
|
|
10
34
|
Classifier: Programming Language :: Python :: 3.9
|
|
11
35
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
36
|
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
38
|
+
Requires-Python: >=3.8
|
|
13
39
|
Description-Content-Type: text/markdown
|
|
40
|
+
License-File: LICENSE
|
|
14
41
|
Requires-Dist: tqdm
|
|
15
42
|
Requires-Dist: docstring-parser
|
|
16
43
|
Requires-Dist: coloredlogs
|
|
@@ -20,7 +47,6 @@ Requires-Dist: click
|
|
|
20
47
|
Requires-Dist: objc-types-decoder
|
|
21
48
|
Requires-Dist: construct
|
|
22
49
|
Requires-Dist: pymobiledevice3
|
|
23
|
-
Requires-Dist: cached-property
|
|
24
50
|
Requires-Dist: keystone-engine
|
|
25
51
|
Provides-Extra: test
|
|
26
52
|
Requires-Dist: pytest ; extra == 'test'
|
|
@@ -92,6 +118,16 @@ xcrun python3 -m pip install --user -U hilda
|
|
|
92
118
|
|
|
93
119
|
## Starting a Hilda shell
|
|
94
120
|
|
|
121
|
+
### Attach mode
|
|
122
|
+
|
|
123
|
+
Use the attach sub-command in order to start an LLDB shell attached to given process.
|
|
124
|
+
|
|
125
|
+
```shell
|
|
126
|
+
hilda attach [-p pid] [-n process-name]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
After attaching, simply execute `hilda` command to enter the hilda shell.
|
|
130
|
+
|
|
95
131
|
### Bare mode
|
|
96
132
|
|
|
97
133
|
Use "Bare mode" to get a "bare-bones" lldb shell, whereas hilda plugin is already loaded and ready to start. This mode
|
|
@@ -129,13 +165,17 @@ This mode will auto-connect to the remote device and attach to your target proce
|
|
|
129
165
|
remote jailbroken iOS device.
|
|
130
166
|
|
|
131
167
|
Please note the following:
|
|
132
|
-
|
|
133
|
-
|
|
168
|
+
|
|
169
|
+
* script assumes the connected device already **has a running ssh server**, which doesn't require a password (you can
|
|
170
|
+
use
|
|
171
|
+
`ssh-copy-id` to achieve this).
|
|
134
172
|
|
|
135
173
|
From this point the flow diverges into 2 flows:
|
|
136
174
|
|
|
137
175
|
### The connected device is connected to the network via `internet sharing` with your computer
|
|
176
|
+
|
|
138
177
|
Run the following command:
|
|
178
|
+
|
|
139
179
|
```shell
|
|
140
180
|
hilda remote PROCESS_NAME SSH_PORT
|
|
141
181
|
```
|
|
@@ -143,11 +183,12 @@ hilda remote PROCESS_NAME SSH_PORT
|
|
|
143
183
|
### The connected device is connected via Wi-Fi
|
|
144
184
|
|
|
145
185
|
For this to work, you will need to make sure of the following:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
186
|
+
|
|
187
|
+
* Find your cellphone IP address (Settings -> Wi-Fi -> network info -> IP Address).
|
|
188
|
+
* Once you found it, run the following command:
|
|
189
|
+
```shell
|
|
190
|
+
hilda remote PROCESS_NAME SSH_PORT --hostname <DEVICE_IP_ADDRESS>
|
|
191
|
+
```
|
|
151
192
|
|
|
152
193
|
## Commands
|
|
153
194
|
|
|
@@ -272,6 +313,65 @@ capabilities:
|
|
|
272
313
|
stop?
|
|
273
314
|
```
|
|
274
315
|
|
|
316
|
+
## UI Configuration
|
|
317
|
+
|
|
318
|
+
Hilda contains minimal UI for examining the target state.
|
|
319
|
+
The UI is divided into views:
|
|
320
|
+
|
|
321
|
+
- Registers
|
|
322
|
+
- Disassembly
|
|
323
|
+
- Stack
|
|
324
|
+
- Backtrace
|
|
325
|
+
|
|
326
|
+

|
|
327
|
+
|
|
328
|
+
This UI can be displayed at any time be executing:
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
ui.show()
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
By default `step_into` and `step_over` will show this UI automatically.
|
|
335
|
+
You may disable this behaviour by executing:
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
ui.active = False
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Attentively, if you want to display UI after hitting a breakpoint, you can register `ui.show` as callback:
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
symbol(0x7ff7b97c21b0).bp(ui.show)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Try playing with the UI settings by yourself:
|
|
348
|
+
|
|
349
|
+
```python
|
|
350
|
+
# Disable stack view
|
|
351
|
+
ui.views.stack.active = False
|
|
352
|
+
|
|
353
|
+
# View words from the stack
|
|
354
|
+
ui.views.stack.depth = 10
|
|
355
|
+
|
|
356
|
+
# View last 10 frames
|
|
357
|
+
ui.views.backtrace.depth = 10
|
|
358
|
+
|
|
359
|
+
# Disassemble 5 instructions
|
|
360
|
+
ui.views.disassembly.instruction_count = 5
|
|
361
|
+
|
|
362
|
+
# Change disassembly syntax to AT&T
|
|
363
|
+
ui.views.disassembly.flavor = 'att'
|
|
364
|
+
|
|
365
|
+
# View floating point registers
|
|
366
|
+
ui.views.registers.rtype = 'float'
|
|
367
|
+
|
|
368
|
+
# Change addresses print color
|
|
369
|
+
ui.colors.address = 'red'
|
|
370
|
+
|
|
371
|
+
# Change titles color
|
|
372
|
+
ui.color.title = 'green'
|
|
373
|
+
```
|
|
374
|
+
|
|
275
375
|
## Symbol objects
|
|
276
376
|
|
|
277
377
|
In Hilda, almost everything is wrapped using the `Symbol` Object. Symbol is just a nicer way for referring to addresses
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
hilda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
hilda/__main__.py,sha256=TcX1OCjb1jBnD9cU9Kgidle_OjTv4btagSUIUAChiXU,58
|
|
3
|
+
hilda/command.py,sha256=GTpl7cFuLC7JlPRAulPM0qKxhynnguUFSW3rYqi8Xeg,640
|
|
4
|
+
hilda/exceptions.py,sha256=K1mKQe4ules8-c8BT1Z9sna0e1Fv3POF2qEX-WXNKDY,1818
|
|
5
|
+
hilda/from_ns_to_json.m,sha256=5Ddl0UJLQXlDYwR_yjE4yZk1aOsJGxoy1oRnhZHPrTw,2847
|
|
6
|
+
hilda/get_objectivec_class_description.m,sha256=Emqavl1i_qzVUYhg8b22mFhb0kZXQHPNB6vt_w-SUe0,4777
|
|
7
|
+
hilda/get_objectivec_symbol_data.m,sha256=xoxESO2iyMbTAkQPRste3ZWPYjqiC7QuixE3pHOML04,6421
|
|
8
|
+
hilda/hilda_ascii_art.html,sha256=-9YCjAKdGbjtdd6uoKrxkkcJq7j16r4dGka2bZ27b4o,120119
|
|
9
|
+
hilda/hilda_client.py,sha256=lORoJ3K-few_ivri7PPDWN4IpinG0QE7bhHEvysEjUg,42180
|
|
10
|
+
hilda/launch_lldb.py,sha256=QaA5UFxaLWdLiEK839VbnyGLsY6sY0ODi1ge0-DlJsg,2855
|
|
11
|
+
hilda/lldb_entrypoint.py,sha256=m5cUqnDCcqfgFTdlExMLjcq4F5L0gywuBIfFLnDLy8o,1006
|
|
12
|
+
hilda/lsof.m,sha256=FAtTc76-EFlWq1WTJkxYnNTnj0V8exPsiOH3rzAJAAA,3168
|
|
13
|
+
hilda/objective_c_class.py,sha256=CsvfWEIz8t5ew891DYIgCgf1UFcatiEYlTgpbtKSa44,11403
|
|
14
|
+
hilda/objective_c_symbol.py,sha256=OAH0eL0m__2XpwY-GKuPs-L8KSztWeqrUF8CfUDzGBQ,8611
|
|
15
|
+
hilda/registers.py,sha256=moGS9MXrfm8vmnqDKWZSg4wmZNydGUadui9uwEwzhsI,856
|
|
16
|
+
hilda/symbol.py,sha256=7zIkRViZJkWg2AUMwG6t0exehwnJwHFNEb5og0PpPEc,6791
|
|
17
|
+
hilda/symbols_jar.py,sha256=J30FKaNv-Ojvm6GJO52eDBcKIY2JSQipfba21KFBF_4,6155
|
|
18
|
+
hilda/to_ns_from_json.m,sha256=dEvtIx-cPc0Flth7wfaKuKTWXJI1GtRFDrnjKrf2Bl4,1635
|
|
19
|
+
hilda/snippets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
hilda/snippets/boringssl.py,sha256=GjpOUTptLBIMjf4ImOKF6OOOInr-x87u9_E_SvvUq20,774
|
|
21
|
+
hilda/snippets/collections.py,sha256=8UlJKKLV9ba1IUe9G6qAGZzweeHVVgj_HDf0QUYOTWs,417
|
|
22
|
+
hilda/snippets/dyld.py,sha256=47hGtgHLQX1xF7BGhxZjAIsiH2FkmhrXgdMe-RzI4hA,2161
|
|
23
|
+
hilda/snippets/fs_utils.py,sha256=97BKWXj6yuKxD6tDm3Nlaq6ACfET2oQFVwE2VlArw3E,397
|
|
24
|
+
hilda/snippets/remotepairingd.py,sha256=LxIMyXTl2YFoKMScs16s7vB5b8IFRdWead5tuKd5ZCw,5824
|
|
25
|
+
hilda/snippets/syslog.py,sha256=8qhYHKTElzWifqYAwt72iQ57wf1n0F_au2Vl2L8NPOc,294
|
|
26
|
+
hilda/snippets/uuid.py,sha256=ttw-rq2Wshm7UMZXd5uYP37bi8G_ZE4XcXJbsYIgp1c,273
|
|
27
|
+
hilda/snippets/xpc.py,sha256=GM6AN7UuJ0niE51PXdrh0WzYT-u2V1mPDOUwDTiiAEo,3909
|
|
28
|
+
hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py,sha256=nAFZ4TjjBy0BlffbsKnTneGa0YE_T9bPNv5qhPVR-Hw,4156
|
|
29
|
+
hilda/snippets/mach/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
+
hilda/snippets/macho/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
+
hilda/snippets/macho/all_image_infos.py,sha256=p6jIfJo4AYdAeoqQ0GqwRl5hgfjmAOnBoGpgwaTzyLI,4768
|
|
32
|
+
hilda/snippets/macho/apple_version.py,sha256=TTaqZKMviXJoU1o3OYeUskmxSkhVhh3UG1VbdJ6N-LE,148
|
|
33
|
+
hilda/snippets/macho/image_info.py,sha256=862C3T2-pPCwgdRqJTNNv28gECwGigJiZojUIFGIKqg,1588
|
|
34
|
+
hilda/snippets/macho/macho.py,sha256=X4NQZkO7VCcIMNuPs25ukiBrHM5Kj3UPMJzzeILfuyg,839
|
|
35
|
+
hilda/snippets/macho/macho_load_commands.py,sha256=KF-HCr46iQloOwnLfFPUYi0dn9ehywSoy1R_P-BqMPI,10644
|
|
36
|
+
hilda/ui/colors.json,sha256=f-ITquY3IInQreviTy23JfmxfJrGM1_MivACf1GKGqM,262
|
|
37
|
+
hilda/ui/ui_manager.py,sha256=BmzI1sBx0PYCQDlB9Al7wsTEAMJxaJ7NW0DS4C7g5-0,2265
|
|
38
|
+
hilda/ui/views.py,sha256=Sd0y7I0iQ4HAWJNyDQ6LjvbEtJYolCaC2sAuPWs6-EE,7693
|
|
39
|
+
hilda-0.3.0.dist-info/LICENSE,sha256=M-LVJ0AFAYB82eueyl8brh-QLPe-iLNVgbCi79-3TDo,1078
|
|
40
|
+
hilda-0.3.0.dist-info/METADATA,sha256=ALa5ZPU4GoOsKqZgMATXZMtQj4oSxEfQUonznBxl3xE,22234
|
|
41
|
+
hilda-0.3.0.dist-info/WHEEL,sha256=AtBG6SXL3KF_v0NxLf0ehyVOh0cold-JbJYXNGorC6Q,92
|
|
42
|
+
hilda-0.3.0.dist-info/entry_points.txt,sha256=9n3O3j6V3XnVR_GcFqCWNgRAbalfukTSW2WvghsLVmA,46
|
|
43
|
+
hilda-0.3.0.dist-info/top_level.txt,sha256=nyNxC_JClCNn-Oi_JFapvV2VrlMk4x47b2mnwP5OJik,6
|
|
44
|
+
hilda-0.3.0.dist-info/RECORD,,
|
hilda-0.1.2.dist-info/RECORD
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
hilda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
hilda/__main__.py,sha256=TcX1OCjb1jBnD9cU9Kgidle_OjTv4btagSUIUAChiXU,58
|
|
3
|
-
hilda/command.py,sha256=GTpl7cFuLC7JlPRAulPM0qKxhynnguUFSW3rYqi8Xeg,640
|
|
4
|
-
hilda/exceptions.py,sha256=K1mKQe4ules8-c8BT1Z9sna0e1Fv3POF2qEX-WXNKDY,1818
|
|
5
|
-
hilda/from_ns_to_json.m,sha256=5Ddl0UJLQXlDYwR_yjE4yZk1aOsJGxoy1oRnhZHPrTw,2847
|
|
6
|
-
hilda/get_objectivec_class_description.m,sha256=Emqavl1i_qzVUYhg8b22mFhb0kZXQHPNB6vt_w-SUe0,4777
|
|
7
|
-
hilda/get_objectivec_symbol_data.m,sha256=xoxESO2iyMbTAkQPRste3ZWPYjqiC7QuixE3pHOML04,6421
|
|
8
|
-
hilda/hilda_ascii_art.html,sha256=-9YCjAKdGbjtdd6uoKrxkkcJq7j16r4dGka2bZ27b4o,120119
|
|
9
|
-
hilda/hilda_client.py,sha256=dnAoWehnN47jBRBjKPH9IQ3lazdVhWL8K1MGmjAdhLY,40937
|
|
10
|
-
hilda/launch_lldb.py,sha256=jL9fO6sz96xt6wWdsr8tyiKPUZOM-XZErcfav1iWjMw,2115
|
|
11
|
-
hilda/lldb_entrypoint.py,sha256=Cjj520dApKCiBUNeCbOACFrZV8zU2QUBgHFAmxwWH5w,900
|
|
12
|
-
hilda/lsof.m,sha256=FAtTc76-EFlWq1WTJkxYnNTnj0V8exPsiOH3rzAJAAA,3168
|
|
13
|
-
hilda/objective_c_class.py,sha256=Jf0Lvhc6hxRnzKjN8kaTBo6rlf8Dq4eM7iVrbtxMRHM,11366
|
|
14
|
-
hilda/objective_c_symbol.py,sha256=Ej_IV9MFE_OKb4BEluKnczIXj3_18xIoMuDGpHak9Yc,8611
|
|
15
|
-
hilda/registers.py,sha256=moGS9MXrfm8vmnqDKWZSg4wmZNydGUadui9uwEwzhsI,856
|
|
16
|
-
hilda/symbol.py,sha256=vYC2sLiUuF4FADTj6HqpRDhzOCpIVTQpD6bGMRz5v2o,6721
|
|
17
|
-
hilda/symbols_jar.py,sha256=S3-KrW9iVv8Sf6rGAvqKuLnC5EJRE79s66vdzHrPukM,6155
|
|
18
|
-
hilda/to_ns_from_json.m,sha256=dEvtIx-cPc0Flth7wfaKuKTWXJI1GtRFDrnjKrf2Bl4,1635
|
|
19
|
-
hilda/snippets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
hilda/snippets/collections.py,sha256=8UlJKKLV9ba1IUe9G6qAGZzweeHVVgj_HDf0QUYOTWs,417
|
|
21
|
-
hilda/snippets/dyld.py,sha256=LaOrL_feOxr6T82phYit09O8Bc8YnxtNKzsEQwMYNss,2162
|
|
22
|
-
hilda/snippets/fs_utils.py,sha256=97BKWXj6yuKxD6tDm3Nlaq6ACfET2oQFVwE2VlArw3E,397
|
|
23
|
-
hilda/snippets/remotepairingd.py,sha256=VvERg3ayvZ8UENm-bvDY43M4BqGBHlTTpvCiclhS3Mk,6008
|
|
24
|
-
hilda/snippets/syslog.py,sha256=8qhYHKTElzWifqYAwt72iQ57wf1n0F_au2Vl2L8NPOc,294
|
|
25
|
-
hilda/snippets/uuid.py,sha256=TWJ_0kwDqjlkJBDbpPooylAkRlYjPFgPtbgZC_F27Sc,273
|
|
26
|
-
hilda/snippets/xpc.py,sha256=Idb6-IZkEIHsfNcv13IN_WgMH1FG5OekX2yriiAvTO0,3629
|
|
27
|
-
hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py,sha256=8Tz2cc5KYmScQTspvMJPPGfo87VvwxqZWav59sVuBh4,2445
|
|
28
|
-
hilda/snippets/mach/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
hilda/snippets/macho/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
-
hilda/snippets/macho/all_image_infos.py,sha256=7p_Bi-hotSPOZkgi9lgHBHhAgX8b9iPSJKxx33-vBro,4768
|
|
31
|
-
hilda/snippets/macho/apple_version.py,sha256=aMwxyjkzmYHcT6luHuCN8m6ViUcK7vnPs5kx6QA5ABM,148
|
|
32
|
-
hilda/snippets/macho/image_info.py,sha256=rGr3_8dmf1883Yp4aVZNvWhO6w-iWZn8_54URv4g8H8,1588
|
|
33
|
-
hilda/snippets/macho/macho.py,sha256=FyMYOv3ZuQUqoUohVKonrQz4qyHzK7aX6OYAGPze2v0,838
|
|
34
|
-
hilda/snippets/macho/macho_load_commands.py,sha256=gt-iy7RVrni7H_nbZuL9CwrwfR7xEF79mGo2H7WDtVc,10645
|
|
35
|
-
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
-
tests/__main__.py,sha256=q8DLFsyyCYh0NORO5kJw4tfExOSzCOZ-3Owo09acirQ,69
|
|
37
|
-
tests/conftest.py,sha256=o0vZIMctO-05gTweXnvtZ69GHIH8xkKOy403YUdmGeI,545
|
|
38
|
-
tests/hilda_tests.py,sha256=k5Q1bUlq-V4uIxP-ntrtgyUBbEpxLpvG-s1Jg_g-P3Y,621
|
|
39
|
-
tests/lldb_entrypoint.py,sha256=_-cjxEVQZVZlw-Sq1DSdYxjikJ1EuUzRzdBGGylrMH0,948
|
|
40
|
-
hilda-0.1.2.dist-info/METADATA,sha256=H34hUVgU9ISAz7ClXpKRs8SRdqrHPWE1UonwtukXCuo,19241
|
|
41
|
-
hilda-0.1.2.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
42
|
-
hilda-0.1.2.dist-info/entry_points.txt,sha256=9n3O3j6V3XnVR_GcFqCWNgRAbalfukTSW2WvghsLVmA,46
|
|
43
|
-
hilda-0.1.2.dist-info/top_level.txt,sha256=cwL2eu1CjIAMUz2GpHu8BOdi6GA87grV3ELJ58ezuiE,12
|
|
44
|
-
hilda-0.1.2.dist-info/RECORD,,
|
tests/__init__.py
DELETED
|
File without changes
|
tests/__main__.py
DELETED
tests/conftest.py
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import lldb
|
|
2
|
-
import pytest
|
|
3
|
-
|
|
4
|
-
from hilda.hilda_client import HildaClient
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@pytest.fixture(scope='function')
|
|
8
|
-
def hilda_client(lldb_debugger):
|
|
9
|
-
client = HildaClient(lldb_debugger)
|
|
10
|
-
client.init_dynamic_environment()
|
|
11
|
-
lldb.hilda_client = client
|
|
12
|
-
with client.stopped():
|
|
13
|
-
yield client
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@pytest.fixture(scope='session', autouse=True)
|
|
17
|
-
def disable_jetsam_memory_checks(lldb_debugger):
|
|
18
|
-
client = HildaClient(lldb_debugger)
|
|
19
|
-
lldb.hilda_client = client
|
|
20
|
-
client.init_dynamic_environment()
|
|
21
|
-
client.disable_jetsam_memory_checks()
|
tests/hilda_tests.py
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
import click
|
|
5
|
-
from hilda import launch_lldb
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@click.command()
|
|
9
|
-
@click.argument('process')
|
|
10
|
-
@click.argument('ssh_port', type=click.INT)
|
|
11
|
-
@click.option('--debug-port', type=click.INT, default=1234)
|
|
12
|
-
@click.option('--hostname', default='localhost')
|
|
13
|
-
def main(process, ssh_port, debug_port, hostname):
|
|
14
|
-
""" Start debugserver at remote device and connect using lldb """
|
|
15
|
-
launch_lldb.start_remote(debug_port, ssh_port, process, hostname,
|
|
16
|
-
os.path.join(Path(__file__).resolve().parent, "lldb_entrypoint.py"))
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if __name__ == '__main__':
|
|
20
|
-
launch_lldb.remote()
|
tests/lldb_entrypoint.py
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/xcrun python3
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
|
-
import lldb
|
|
6
|
-
import pytest
|
|
7
|
-
|
|
8
|
-
logging.getLogger('parso.cache').disabled = True
|
|
9
|
-
logging.getLogger('parso.cache.pickle').disabled = True
|
|
10
|
-
logging.getLogger('parso.python.diff').disabled = True
|
|
11
|
-
logging.getLogger('humanfriendly.prompts').disabled = True
|
|
12
|
-
|
|
13
|
-
lldb.hilda_client = None
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class AddDebuggerPlugin:
|
|
17
|
-
def __init__(self, debugger):
|
|
18
|
-
self.__name__ = 'AddDebuggerPlugin'
|
|
19
|
-
self.debugger = debugger
|
|
20
|
-
|
|
21
|
-
@pytest.fixture(scope='session')
|
|
22
|
-
def lldb_debugger(self, request):
|
|
23
|
-
return request.config.pluginmanager.get_plugin('AddDebuggerPlugin').debugger
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def run_tests(debugger, command, result, internal_dict):
|
|
27
|
-
pytest.main(command.split(), plugins=[AddDebuggerPlugin(debugger)])
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def __lldb_init_module(debugger, internal_dict):
|
|
31
|
-
debugger.SetAsync(True)
|
|
32
|
-
debugger.HandleCommand('command script add -f lldb_entrypoint.run_tests run_tests')
|
|
33
|
-
print('Use "run_tests" command')
|
|
File without changes
|