hilda 0.1.2__tar.gz → 0.3.0__tar.gz

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.
Files changed (59) hide show
  1. hilda-0.3.0/LICENSE +20 -0
  2. {hilda-0.1.2/hilda.egg-info → hilda-0.3.0}/PKG-INFO +113 -12
  3. hilda-0.1.2/PKG-INFO → hilda-0.3.0/README.md +81 -22
  4. {hilda-0.1.2 → hilda-0.3.0}/hilda/hilda_client.py +55 -35
  5. {hilda-0.1.2 → hilda-0.3.0}/hilda/launch_lldb.py +20 -0
  6. {hilda-0.1.2 → hilda-0.3.0}/hilda/lldb_entrypoint.py +3 -1
  7. {hilda-0.1.2 → hilda-0.3.0}/hilda/objective_c_class.py +3 -2
  8. {hilda-0.1.2 → hilda-0.3.0}/hilda/objective_c_symbol.py +3 -3
  9. hilda-0.3.0/hilda/snippets/boringssl.py +26 -0
  10. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/dyld.py +1 -2
  11. hilda-0.3.0/hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py +92 -0
  12. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/macho/all_image_infos.py +2 -2
  13. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/macho/apple_version.py +1 -1
  14. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/macho/image_info.py +1 -1
  15. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/macho/macho.py +2 -1
  16. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/macho/macho_load_commands.py +2 -3
  17. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/remotepairingd.py +12 -18
  18. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/uuid.py +1 -1
  19. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/xpc.py +9 -0
  20. {hilda-0.1.2 → hilda-0.3.0}/hilda/symbol.py +9 -5
  21. {hilda-0.1.2 → hilda-0.3.0}/hilda/symbols_jar.py +1 -1
  22. hilda-0.3.0/hilda/ui/colors.json +13 -0
  23. hilda-0.3.0/hilda/ui/ui_manager.py +74 -0
  24. hilda-0.3.0/hilda/ui/views.py +217 -0
  25. hilda-0.1.2/README.md → hilda-0.3.0/hilda.egg-info/PKG-INFO +123 -7
  26. {hilda-0.1.2 → hilda-0.3.0}/hilda.egg-info/SOURCES.txt +7 -7
  27. {hilda-0.1.2 → hilda-0.3.0}/hilda.egg-info/requires.txt +0 -1
  28. hilda-0.3.0/hilda.egg-info/top_level.txt +3 -0
  29. hilda-0.3.0/pyproject.toml +51 -0
  30. hilda-0.3.0/requirements.txt +10 -0
  31. hilda-0.3.0/setup.cfg +4 -0
  32. hilda-0.1.2/hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py +0 -43
  33. hilda-0.1.2/hilda.egg-info/top_level.txt +0 -2
  34. hilda-0.1.2/setup.cfg +0 -48
  35. hilda-0.1.2/setup.py +0 -3
  36. hilda-0.1.2/tests/__init__.py +0 -0
  37. hilda-0.1.2/tests/__main__.py +0 -4
  38. hilda-0.1.2/tests/conftest.py +0 -21
  39. hilda-0.1.2/tests/hilda_tests.py +0 -20
  40. hilda-0.1.2/tests/lldb_entrypoint.py +0 -33
  41. {hilda-0.1.2 → hilda-0.3.0}/hilda/__init__.py +0 -0
  42. {hilda-0.1.2 → hilda-0.3.0}/hilda/__main__.py +0 -0
  43. {hilda-0.1.2 → hilda-0.3.0}/hilda/command.py +0 -0
  44. {hilda-0.1.2 → hilda-0.3.0}/hilda/exceptions.py +0 -0
  45. {hilda-0.1.2 → hilda-0.3.0}/hilda/from_ns_to_json.m +0 -0
  46. {hilda-0.1.2 → hilda-0.3.0}/hilda/get_objectivec_class_description.m +0 -0
  47. {hilda-0.1.2 → hilda-0.3.0}/hilda/get_objectivec_symbol_data.m +0 -0
  48. {hilda-0.1.2 → hilda-0.3.0}/hilda/hilda_ascii_art.html +0 -0
  49. {hilda-0.1.2 → hilda-0.3.0}/hilda/lsof.m +0 -0
  50. {hilda-0.1.2 → hilda-0.3.0}/hilda/registers.py +0 -0
  51. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/__init__.py +0 -0
  52. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/collections.py +0 -0
  53. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/fs_utils.py +0 -0
  54. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/mach/__init__.py +0 -0
  55. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/macho/__init__.py +0 -0
  56. {hilda-0.1.2 → hilda-0.3.0}/hilda/snippets/syslog.py +0 -0
  57. {hilda-0.1.2 → hilda-0.3.0}/hilda/to_ns_from_json.m +0 -0
  58. {hilda-0.1.2 → hilda-0.3.0}/hilda.egg-info/dependency_links.txt +0 -0
  59. {hilda-0.1.2 → hilda-0.3.0}/hilda.egg-info/entry_points.txt +0 -0
hilda-0.3.0/LICENSE ADDED
@@ -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,17 +1,44 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hilda
3
- Version: 0.1.2
3
+ Version: 0.3.0
4
4
  Summary: LLDB wrapped and empowered by iPython's features
5
- Home-page: https://github.com/doronz88/hilda
6
- Author: DoronZ
7
- Project-URL: hilda, https://github.com/doronz88/hilda
8
- Classifier: Programming Language :: Python :: 3.7
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
14
40
  Provides-Extra: test
41
+ License-File: LICENSE
15
42
 
16
43
  - [Description](#description)
17
44
  - [Example](#example)
@@ -80,6 +107,16 @@ xcrun python3 -m pip install --user -U hilda
80
107
 
81
108
  ## Starting a Hilda shell
82
109
 
110
+ ### Attach mode
111
+
112
+ Use the attach sub-command in order to start an LLDB shell attached to given process.
113
+
114
+ ```shell
115
+ hilda attach [-p pid] [-n process-name]
116
+ ```
117
+
118
+ After attaching, simply execute `hilda` command to enter the hilda shell.
119
+
83
120
  ### Bare mode
84
121
 
85
122
  Use "Bare mode" to get a "bare-bones" lldb shell, whereas hilda plugin is already loaded and ready to start. This mode
@@ -117,13 +154,17 @@ This mode will auto-connect to the remote device and attach to your target proce
117
154
  remote jailbroken iOS device.
118
155
 
119
156
  Please note the following:
120
- * script assumes the connected device already **has a running ssh server**, which doesn't require a password (you can use
121
- `ssh-copy-id` to achieve this).
157
+
158
+ * script assumes the connected device already **has a running ssh server**, which doesn't require a password (you can
159
+ use
160
+ `ssh-copy-id` to achieve this).
122
161
 
123
162
  From this point the flow diverges into 2 flows:
124
163
 
125
164
  ### The connected device is connected to the network via `internet sharing` with your computer
165
+
126
166
  Run the following command:
167
+
127
168
  ```shell
128
169
  hilda remote PROCESS_NAME SSH_PORT
129
170
  ```
@@ -131,11 +172,12 @@ hilda remote PROCESS_NAME SSH_PORT
131
172
  ### The connected device is connected via Wi-Fi
132
173
 
133
174
  For this to work, you will need to make sure of the following:
134
- * Find your cellphone IP address (Settings -> Wi-Fi -> network info -> IP Address).
135
- * Once you found it, run the following command:
136
- ```shell
137
- hilda remote PROCESS_NAME SSH_PORT --hostname <DEVICE_IP_ADDRESS>
138
- ```
175
+
176
+ * Find your cellphone IP address (Settings -> Wi-Fi -> network info -> IP Address).
177
+ * Once you found it, run the following command:
178
+ ```shell
179
+ hilda remote PROCESS_NAME SSH_PORT --hostname <DEVICE_IP_ADDRESS>
180
+ ```
139
181
 
140
182
  ## Commands
141
183
 
@@ -260,6 +302,65 @@ capabilities:
260
302
  stop?
261
303
  ```
262
304
 
305
+ ## UI Configuration
306
+
307
+ Hilda contains minimal UI for examining the target state.
308
+ The UI is divided into views:
309
+
310
+ - Registers
311
+ - Disassembly
312
+ - Stack
313
+ - Backtrace
314
+
315
+ ![img.png](gifs/ui.png)
316
+
317
+ This UI can be displayed at any time be executing:
318
+
319
+ ```python
320
+ ui.show()
321
+ ```
322
+
323
+ By default `step_into` and `step_over` will show this UI automatically.
324
+ You may disable this behaviour by executing:
325
+
326
+ ```python
327
+ ui.active = False
328
+ ```
329
+
330
+ Attentively, if you want to display UI after hitting a breakpoint, you can register `ui.show` as callback:
331
+
332
+ ```python
333
+ symbol(0x7ff7b97c21b0).bp(ui.show)
334
+ ```
335
+
336
+ Try playing with the UI settings by yourself:
337
+
338
+ ```python
339
+ # Disable stack view
340
+ ui.views.stack.active = False
341
+
342
+ # View words from the stack
343
+ ui.views.stack.depth = 10
344
+
345
+ # View last 10 frames
346
+ ui.views.backtrace.depth = 10
347
+
348
+ # Disassemble 5 instructions
349
+ ui.views.disassembly.instruction_count = 5
350
+
351
+ # Change disassembly syntax to AT&T
352
+ ui.views.disassembly.flavor = 'att'
353
+
354
+ # View floating point registers
355
+ ui.views.registers.rtype = 'float'
356
+
357
+ # Change addresses print color
358
+ ui.colors.address = 'red'
359
+
360
+ # Change titles color
361
+ ui.color.title = 'green'
362
+ ```
363
+
263
364
  ## Symbol objects
264
365
 
265
366
  In Hilda, almost everything is wrapped using the `Symbol` Object. Symbol is just a nicer way for referring to addresses
@@ -1,18 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: hilda
3
- Version: 0.1.2
4
- Summary: LLDB wrapped and empowered by iPython's features
5
- Home-page: https://github.com/doronz88/hilda
6
- Author: DoronZ
7
- Project-URL: hilda, https://github.com/doronz88/hilda
8
- Classifier: Programming Language :: Python :: 3.7
9
- Classifier: Programming Language :: Python :: 3.8
10
- Classifier: Programming Language :: Python :: 3.9
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Description-Content-Type: text/markdown
14
- Provides-Extra: test
15
-
16
1
  - [Description](#description)
17
2
  - [Example](#example)
18
3
  - [Installation](#installation)
@@ -80,6 +65,16 @@ xcrun python3 -m pip install --user -U hilda
80
65
 
81
66
  ## Starting a Hilda shell
82
67
 
68
+ ### Attach mode
69
+
70
+ Use the attach sub-command in order to start an LLDB shell attached to given process.
71
+
72
+ ```shell
73
+ hilda attach [-p pid] [-n process-name]
74
+ ```
75
+
76
+ After attaching, simply execute `hilda` command to enter the hilda shell.
77
+
83
78
  ### Bare mode
84
79
 
85
80
  Use "Bare mode" to get a "bare-bones" lldb shell, whereas hilda plugin is already loaded and ready to start. This mode
@@ -117,13 +112,17 @@ This mode will auto-connect to the remote device and attach to your target proce
117
112
  remote jailbroken iOS device.
118
113
 
119
114
  Please note the following:
120
- * script assumes the connected device already **has a running ssh server**, which doesn't require a password (you can use
121
- `ssh-copy-id` to achieve this).
115
+
116
+ * script assumes the connected device already **has a running ssh server**, which doesn't require a password (you can
117
+ use
118
+ `ssh-copy-id` to achieve this).
122
119
 
123
120
  From this point the flow diverges into 2 flows:
124
121
 
125
122
  ### The connected device is connected to the network via `internet sharing` with your computer
123
+
126
124
  Run the following command:
125
+
127
126
  ```shell
128
127
  hilda remote PROCESS_NAME SSH_PORT
129
128
  ```
@@ -131,11 +130,12 @@ hilda remote PROCESS_NAME SSH_PORT
131
130
  ### The connected device is connected via Wi-Fi
132
131
 
133
132
  For this to work, you will need to make sure of the following:
134
- * Find your cellphone IP address (Settings -> Wi-Fi -> network info -> IP Address).
135
- * Once you found it, run the following command:
136
- ```shell
137
- hilda remote PROCESS_NAME SSH_PORT --hostname <DEVICE_IP_ADDRESS>
138
- ```
133
+
134
+ * Find your cellphone IP address (Settings -> Wi-Fi -> network info -> IP Address).
135
+ * Once you found it, run the following command:
136
+ ```shell
137
+ hilda remote PROCESS_NAME SSH_PORT --hostname <DEVICE_IP_ADDRESS>
138
+ ```
139
139
 
140
140
  ## Commands
141
141
 
@@ -260,6 +260,65 @@ capabilities:
260
260
  stop?
261
261
  ```
262
262
 
263
+ ## UI Configuration
264
+
265
+ Hilda contains minimal UI for examining the target state.
266
+ The UI is divided into views:
267
+
268
+ - Registers
269
+ - Disassembly
270
+ - Stack
271
+ - Backtrace
272
+
273
+ ![img.png](gifs/ui.png)
274
+
275
+ This UI can be displayed at any time be executing:
276
+
277
+ ```python
278
+ ui.show()
279
+ ```
280
+
281
+ By default `step_into` and `step_over` will show this UI automatically.
282
+ You may disable this behaviour by executing:
283
+
284
+ ```python
285
+ ui.active = False
286
+ ```
287
+
288
+ Attentively, if you want to display UI after hitting a breakpoint, you can register `ui.show` as callback:
289
+
290
+ ```python
291
+ symbol(0x7ff7b97c21b0).bp(ui.show)
292
+ ```
293
+
294
+ Try playing with the UI settings by yourself:
295
+
296
+ ```python
297
+ # Disable stack view
298
+ ui.views.stack.active = False
299
+
300
+ # View words from the stack
301
+ ui.views.stack.depth = 10
302
+
303
+ # View last 10 frames
304
+ ui.views.backtrace.depth = 10
305
+
306
+ # Disassemble 5 instructions
307
+ ui.views.disassembly.instruction_count = 5
308
+
309
+ # Change disassembly syntax to AT&T
310
+ ui.views.disassembly.flavor = 'att'
311
+
312
+ # View floating point registers
313
+ ui.views.registers.rtype = 'float'
314
+
315
+ # Change addresses print color
316
+ ui.colors.address = 'red'
317
+
318
+ # Change titles color
319
+ ui.color.title = 'green'
320
+ ```
321
+
263
322
  ## Symbol objects
264
323
 
265
324
  In Hilda, almost everything is wrapped using the `Symbol` Object. Symbol is just a nicer way for referring to addresses
@@ -9,19 +9,21 @@ import os
9
9
  import pickle
10
10
  import textwrap
11
11
  import time
12
+ import typing
12
13
  from collections import namedtuple
13
14
  from contextlib import contextmanager, suppress
14
15
  from datetime import datetime, timezone
15
- from functools import partial
16
+ from functools import cached_property, partial
16
17
  from pathlib import Path
17
- from typing import Union
18
+ from typing import List, Optional, Union
18
19
 
19
- import IPython
20
20
  import docstring_parser
21
21
  import hexdump
22
+ import IPython
22
23
  import lldb
23
24
  from humanfriendly import prompts
24
25
  from humanfriendly.terminal.html import html_to_ansi
26
+ from keystone import KS_ARCH_ARM64, KS_ARCH_X86, KS_MODE_64, KS_MODE_LITTLE_ENDIAN, Ks
25
27
  from pygments import highlight
26
28
  from pygments.formatters import TerminalTrueColorFormatter
27
29
  from pygments.lexers import XmlLexer
@@ -29,14 +31,17 @@ from tqdm import tqdm
29
31
  from traitlets.config import Config
30
32
 
31
33
  from hilda import objective_c_class
32
- from hilda.command import command, CommandsMeta
33
- from hilda.exceptions import *
34
+ from hilda.command import CommandsMeta, command
35
+ from hilda.exceptions import AccessingMemoryError, AccessingRegisterError, AddingLldbSymbolError, \
36
+ BrokenLocalSymbolsJarError, ConvertingFromNSObjectError, ConvertingToNsObjectError, CreatingObjectiveCSymbolError, \
37
+ DisableJetsamMemoryChecksError, EvaluatingExpressionError, HildaException, SymbolAbsentError
38
+ from hilda.launch_lldb import disable_logs # noqa: F401
34
39
  from hilda.objective_c_symbol import ObjectiveCSymbol
35
40
  from hilda.registers import Registers
36
41
  from hilda.snippets.mach import CFRunLoopServiceMachPort_hooks
37
42
  from hilda.symbol import Symbol
38
43
  from hilda.symbols_jar import SymbolsJar
39
- from hilda.launch_lldb import disable_logs
44
+ from hilda.ui.ui_manager import UiManager
40
45
 
41
46
  IsaMagic = namedtuple('IsaMagic', 'mask value')
42
47
  ISA_MAGICS = [
@@ -77,7 +82,8 @@ class HildaClient(metaclass=CommandsMeta):
77
82
  self.breakpoints = {}
78
83
  self.captured_objects = {}
79
84
  self.registers = Registers(self)
80
-
85
+ self.arch = self.target.GetTriple().split('-')[0]
86
+ self.ui_manager = UiManager(self)
81
87
  # should unwind the stack on errors. change this to False in order to debug self-made calls
82
88
  # within hilda
83
89
  self._evaluation_unwind_on_error = True
@@ -117,16 +123,22 @@ class HildaClient(metaclass=CommandsMeta):
117
123
  return {int(k): v for k, v in result.items()}
118
124
 
119
125
  @command()
120
- def bt(self):
126
+ def bt(self, should_print=True, depth: Optional[int] = None) -> List:
121
127
  """ Print an improved backtrace. """
128
+ backtrace = []
122
129
  for i, frame in enumerate(self.thread.frames):
130
+ if i == depth:
131
+ break
123
132
  row = ''
124
133
  row += html_to_ansi(f'<span style="color: cyan">0x{frame.addr.GetFileAddress():x}</span> ')
125
134
  row += str(frame)
126
135
  if i == 0:
127
136
  # first line
128
137
  row += ' 👈'
129
- print(row)
138
+ backtrace.append([f'0x{frame.addr.file_addr:016x}', frame])
139
+ if should_print:
140
+ print(row)
141
+ return backtrace
130
142
 
131
143
  @command()
132
144
  def disable_jetsam_memory_checks(self):
@@ -238,6 +250,16 @@ class HildaClient(metaclass=CommandsMeta):
238
250
 
239
251
  return retval
240
252
 
253
+ @command()
254
+ def poke_text(self, address: int, code: str) -> int:
255
+ """
256
+ Write instructions to address.
257
+ :param address:
258
+ :param code:
259
+ """
260
+ bytecode, count = self._ks.asm(code, as_bytes=True)
261
+ return self.poke(address, bytecode)
262
+
241
263
  @command()
242
264
  def peek(self, address, size: int) -> bytes:
243
265
  """
@@ -258,28 +280,13 @@ class HildaClient(metaclass=CommandsMeta):
258
280
  return retval
259
281
 
260
282
  @command()
261
- def peek_str(self, address, encoding=None):
283
+ def peek_str(self, address: Symbol) -> str:
262
284
  """
263
285
  Peek a buffer till null termination
264
286
  :param address:
265
- :param encoding: character encoding. if None, bytes is returned
266
287
  :return:
267
288
  """
268
- if hasattr(self.symbols, 'strlen'):
269
- # always prefer using native strlen
270
- buf = self.peek(address, self.symbols.strlen(address))
271
- else:
272
- buf = self.peek(address, 1)
273
- while buf[-1] != 0:
274
- buf += self.peek(address + len(buf), 1)
275
-
276
- # remove null terminator
277
- buf = buf[:-1]
278
-
279
- if encoding is not None:
280
- buf = str(buf, encoding)
281
-
282
- return buf
289
+ return address.po('char *')[1:-1] # strip the ""
283
290
 
284
291
  @command()
285
292
  def stop(self):
@@ -322,15 +329,16 @@ class HildaClient(metaclass=CommandsMeta):
322
329
  self.log_critical('failed to detach')
323
330
 
324
331
  @command()
325
- def disass(self, address, buf, should_print=True) -> lldb.SBInstructionList:
332
+ def disass(self, address, buf, flavor='intel', should_print=True) -> lldb.SBInstructionList:
326
333
  """
327
334
  Print disassembly from a given address
335
+ :param flavor:
328
336
  :param address:
329
337
  :param buf:
330
338
  :param should_print:
331
339
  :return:
332
340
  """
333
- inst = self.target.GetInstructions(lldb.SBAddress(address, self.target), buf)
341
+ inst = self.target.GetInstructionsWithFlavor(lldb.SBAddress(address, self.target), flavor, buf)
334
342
  if should_print:
335
343
  print(inst)
336
344
  return inst
@@ -515,12 +523,16 @@ class HildaClient(metaclass=CommandsMeta):
515
523
  """ Step into current instruction. """
516
524
  with self.sync_mode():
517
525
  self.thread.StepInto()
526
+ if self.ui_manager.active:
527
+ self.ui_manager.show()
518
528
 
519
529
  @command()
520
530
  def step_over(self):
521
531
  """ Step over current instruction. """
522
532
  with self.sync_mode():
523
533
  self.thread.StepOver()
534
+ if self.ui_manager.active:
535
+ self.ui_manager.show()
524
536
 
525
537
  @command()
526
538
  def remove_all_hilda_breakpoints(self, remove_forced=False):
@@ -608,7 +620,7 @@ class HildaClient(metaclass=CommandsMeta):
608
620
 
609
621
  def bp_callback_router(self, frame, bp_loc, *_):
610
622
  """
611
- Route the breakpoint callback the the specific breakpoint callback.
623
+ Route the breakpoint callback the specific breakpoint callback.
612
624
  :param lldb.SBFrame frame: LLDB Frame object.
613
625
  :param lldb.SBBreakpointLocation bp_loc: LLDB Breakpoint location object.
614
626
  """
@@ -902,13 +914,13 @@ class HildaClient(metaclass=CommandsMeta):
902
914
 
903
915
  if is_running:
904
916
  self.stop()
905
- time.sleep(1)
917
+ time.sleep(interval)
906
918
 
907
919
  try:
908
920
  yield
909
921
  finally:
910
922
  if is_running:
911
- time.sleep(1)
923
+ time.sleep(interval)
912
924
  self.cont()
913
925
 
914
926
  @contextmanager
@@ -1009,7 +1021,7 @@ class HildaClient(metaclass=CommandsMeta):
1009
1021
 
1010
1022
  return value
1011
1023
 
1012
- def interactive(self):
1024
+ def interactive(self, additional_namespace: typing.Mapping = None):
1013
1025
  """ Start an interactive Hilda shell """
1014
1026
  if not self._dynamic_env_loaded:
1015
1027
  self.init_dynamic_environment()
@@ -1025,6 +1037,8 @@ class HildaClient(metaclass=CommandsMeta):
1025
1037
  ]
1026
1038
  namespace = globals()
1027
1039
  namespace.update(locals())
1040
+ if additional_namespace is not None:
1041
+ namespace.update(additional_namespace)
1028
1042
 
1029
1043
  IPython.start_ipython(config=c, user_ns=namespace)
1030
1044
 
@@ -1116,12 +1130,11 @@ class HildaClient(metaclass=CommandsMeta):
1116
1130
  raise NotImplementedError('cannot serialize argument')
1117
1131
  return args_conv
1118
1132
 
1119
- @staticmethod
1120
- def _generate_call_expression(address, params):
1133
+ def _generate_call_expression(self, address, params):
1121
1134
  args_type = ','.join(['intptr_t'] * len(params))
1122
1135
  args_conv = ','.join(params)
1123
1136
 
1124
- if self.target.modules[0].triple.split('-')[0] == 'arm64e':
1137
+ if self.arch == 'arm64e':
1125
1138
  address = f'ptrauth_sign_unauthenticated((void *){address}, ptrauth_key_asia, 0)'
1126
1139
 
1127
1140
  return f'((intptr_t(*)({args_type}))({address}))({args_conv})'
@@ -1178,3 +1191,10 @@ class HildaClient(metaclass=CommandsMeta):
1178
1191
  return formatters[fmt](value)
1179
1192
  else:
1180
1193
  return f'{value:x} (unsupported format)'
1194
+
1195
+ @cached_property
1196
+ def _ks(self) -> Ks:
1197
+ platforms = {'arm64': Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN),
1198
+ 'arm64e': Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN),
1199
+ 'x86_64h': Ks(KS_ARCH_X86, KS_MODE_64)}
1200
+ return platforms.get(self.arch)
@@ -67,6 +67,26 @@ def bare():
67
67
  execute(f'lldb --one-line "{commands}"')
68
68
 
69
69
 
70
+ @cli.command('attach')
71
+ @click.option('-n', '--name', help='process name to attach')
72
+ @click.option('-p', '--pid', type=click.INT, help='pid to attach')
73
+ def attach(name: str, pid: int):
74
+ """ Attach to given process and start an lldb shell """
75
+ # connect local LLDB client
76
+ commands = []
77
+ if name is not None:
78
+ commands.append(f'process attach -n {name}')
79
+ elif pid is not None:
80
+ commands.append(f'process attach -p {pid}')
81
+ else:
82
+ print('missing either process name or pid for attaching')
83
+ return
84
+
85
+ commands.append(f'command script import {os.path.join(Path(__file__).resolve().parent, "lldb_entrypoint.py")}')
86
+ commands = '\n'.join(commands)
87
+ execute(f'lldb --one-line "{commands}"')
88
+
89
+
70
90
  if __name__ == '__main__':
71
91
  disable_logs()
72
92
  cli()
@@ -15,7 +15,9 @@ lldb.hilda_client = None
15
15
  def hilda(debugger, command, result, internal_dict):
16
16
  if lldb.hilda_client is None:
17
17
  lldb.hilda_client = HildaClient(debugger)
18
- lldb.hilda_client.interactive()
18
+
19
+ additional_namespace = {'ui': lldb.hilda_client.ui_manager}
20
+ lldb.hilda_client.interactive(additional_namespace=additional_namespace)
19
21
 
20
22
 
21
23
  def __lldb_init_module(debugger, internal_dict):
@@ -7,13 +7,14 @@ from functools import partial
7
7
  from pathlib import Path
8
8
  from uuid import uuid4
9
9
 
10
+ from objc_types_decoder.decode import decode as decode_type
11
+ from objc_types_decoder.decode import decode_with_tail
10
12
  from pygments import highlight
11
13
  from pygments.formatters import TerminalTrueColorFormatter
12
14
  from pygments.lexers import ObjectiveCLexer
13
- from objc_types_decoder.decode import decode as decode_type, decode_with_tail
14
15
 
15
- from hilda.symbols_jar import SymbolsJar
16
16
  from hilda.exceptions import GettingObjectiveCClassError
17
+ from hilda.symbols_jar import SymbolsJar
17
18
 
18
19
  Ivar = namedtuple('Ivar', 'name type_ offset')
19
20
  Property = namedtuple('Property', 'name attributes')
@@ -5,15 +5,15 @@ from dataclasses import dataclass
5
5
  from functools import partial
6
6
  from pathlib import Path
7
7
 
8
+ from objc_types_decoder.decode import decode as decode_type
8
9
  from pygments import highlight
9
10
  from pygments.formatters import TerminalTrueColorFormatter
10
11
  from pygments.lexers import ObjectiveCLexer
11
- from objc_types_decoder.decode import decode as decode_type
12
12
 
13
13
  from hilda.exceptions import HildaException
14
- from hilda.objective_c_class import Class, convert_encoded_property_attributes, Method, Property
15
- from hilda.symbols_jar import SymbolsJar
14
+ from hilda.objective_c_class import Class, Method, Property, convert_encoded_property_attributes
16
15
  from hilda.symbol import Symbol
16
+ from hilda.symbols_jar import SymbolsJar
17
17
 
18
18
 
19
19
  class SettingIvarError(HildaException):
@@ -0,0 +1,26 @@
1
+ import lldb
2
+
3
+ _FILENAME = '/tmp/hilda-keylog.txt'
4
+
5
+
6
+ def _ssl_log_secret_bp(hilda, *args):
7
+ label = hilda.registers.x1.peek_str()
8
+ secret = hilda.registers.x2.peek(hilda.registers.x3).hex()
9
+ random = (hilda.registers.x0[6] + 48).peek(32).hex()
10
+ print(f'ssl_log_secret\n'
11
+ f' label: {label}\n'
12
+ f' secret: {secret}\n'
13
+ f' random: {random}\n'
14
+ f'---\n')
15
+ with open(_FILENAME, 'a') as f:
16
+ f.write(f'{label} {random} {secret}\n')
17
+ hilda.cont()
18
+
19
+
20
+ def start_keylog(filename: str = None) -> None:
21
+ global _FILENAME
22
+
23
+ if filename is not None:
24
+ _FILENAME = filename
25
+ hilda_client = lldb.hilda_client
26
+ hilda_client.symbols._ZN4bssl14ssl_log_secretEPK6ssl_stPKcNS_4SpanIKhEE.bp(_ssl_log_secret_bp)
@@ -1,6 +1,5 @@
1
- from cached_property import cached_property
2
-
3
1
  import lldb
2
+ from cached_property import cached_property
4
3
 
5
4
  from hilda.snippets.macho.all_image_infos import AllImageInfos
6
5
  from hilda.snippets.syslog import open_syslog_socket