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/hilda_client.py
CHANGED
|
@@ -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
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
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(
|
|
917
|
+
time.sleep(interval)
|
|
906
918
|
|
|
907
919
|
try:
|
|
908
920
|
yield
|
|
909
921
|
finally:
|
|
910
922
|
if is_running:
|
|
911
|
-
time.sleep(
|
|
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
|
-
|
|
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.
|
|
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)
|
hilda/launch_lldb.py
CHANGED
|
@@ -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()
|
hilda/lldb_entrypoint.py
CHANGED
|
@@ -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
|
-
|
|
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):
|
hilda/objective_c_class.py
CHANGED
|
@@ -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')
|
hilda/objective_c_symbol.py
CHANGED
|
@@ -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,
|
|
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)
|
hilda/snippets/dyld.py
CHANGED
|
@@ -1,11 +1,53 @@
|
|
|
1
1
|
import lldb
|
|
2
|
-
from keystone import Ks, KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN
|
|
3
2
|
|
|
3
|
+
from hilda.exceptions import SymbolAbsentError
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
def _CFRunLoopServiceMachPort_hook(hilda, *args):
|
|
7
|
+
"""
|
|
8
|
+
:param hilda.hilda_client.HildaClient hilda:
|
|
9
|
+
"""
|
|
10
|
+
hilda.jump(hilda.CFRunLoopServiceMachPort_while_ea)
|
|
11
|
+
hilda.cont()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _disable_internal_error_handling() -> None:
|
|
15
|
+
hilda = lldb.hilda_client
|
|
16
|
+
with hilda.stopped():
|
|
17
|
+
instructions = hilda.symbols.__CFRunLoopServiceMachPort.disass(2000, should_print=False)
|
|
18
|
+
while_ea = None
|
|
19
|
+
for instruction in instructions:
|
|
20
|
+
if (while_ea is None) and instruction.DoesBranch():
|
|
21
|
+
# Beginning of the `while(true) { ... }`
|
|
22
|
+
while_ea = instruction.GetOperands(hilda.target)
|
|
23
|
+
hilda.CFRunLoopServiceMachPort_while_ea = int(hilda.file_symbol(eval(while_ea)))
|
|
24
|
+
elif instruction.GetMnemonic(hilda.target) in ('brk', 'ud2'):
|
|
25
|
+
symbol = hilda.symbol(instruction.addr.GetLoadAddress(hilda.target))
|
|
26
|
+
symbol.bp(
|
|
27
|
+
_CFRunLoopServiceMachPort_hook,
|
|
28
|
+
forced=True,
|
|
29
|
+
name=f'__CFRunLoopServiceMachPort-brk-{int(symbol - hilda.symbols.__CFRunLoopServiceMachPort)}'
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if hilda.arch == 'x86_64h':
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
# on iOS 16.x, will need to also patch this one
|
|
36
|
+
try:
|
|
37
|
+
handle_error = hilda.symbols['__CFRunLoopServiceMachPort.cold.1']
|
|
38
|
+
except SymbolAbsentError:
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
for instruction in handle_error.disass(2000, should_print=False):
|
|
42
|
+
if instruction.GetMnemonic(hilda.target) in ('brk', 'ud2'):
|
|
43
|
+
# mov x0, x0
|
|
44
|
+
hilda.symbol(instruction.addr.GetLoadAddress(hilda.target)).poke(b'\xe0\x03\x00\xaa')
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _disable_mach_msg_timeout() -> None:
|
|
6
48
|
"""
|
|
7
|
-
|
|
8
|
-
|
|
49
|
+
Remove the timeout validation from __CFRunLoopServiceMachPort. This is done by patching the mach_msg_timeout_t
|
|
50
|
+
parameter (4rd one) to MACH_MSG_TIMEOUT_NONE. On arm the parameter passes on `x3` register.
|
|
9
51
|
|
|
10
52
|
__int64 __fastcall __CFRunLoopServiceMachPort(
|
|
11
53
|
mach_port_name_t a1,
|
|
@@ -29,15 +71,22 @@ def disable_mach_msg_errors():
|
|
|
29
71
|
CoreFoundation:__text:0000000186E50154 MOV X23, X3 <-------- Timeout parameter
|
|
30
72
|
"""
|
|
31
73
|
hilda = lldb.hilda_client
|
|
32
|
-
|
|
74
|
+
if hilda.arch == 'x86_64h':
|
|
75
|
+
return
|
|
76
|
+
|
|
33
77
|
with hilda.stopped():
|
|
34
78
|
for inst in hilda.symbols.__CFRunLoopServiceMachPort.disass(200, should_print=False):
|
|
35
79
|
mnemonic = inst.GetMnemonic(hilda.target)
|
|
36
|
-
operands = inst.GetOperands(hilda.target)
|
|
37
|
-
if mnemonic != 'mov' or '
|
|
80
|
+
operands = inst.GetOperands(hilda.target)
|
|
81
|
+
if mnemonic != 'mov' or not operands.endswith('x3'):
|
|
38
82
|
continue
|
|
39
83
|
addr = inst.GetAddress()
|
|
40
84
|
file_addr = addr.GetFileAddress()
|
|
41
|
-
|
|
42
|
-
hilda.file_symbol(file_addr).
|
|
85
|
+
new_inst = f'{mnemonic} {operands.replace("x3", "0")}'
|
|
86
|
+
hilda.file_symbol(file_addr).poke_text(new_inst)
|
|
43
87
|
break
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def disable_mach_msg_errors() -> None:
|
|
91
|
+
_disable_mach_msg_timeout()
|
|
92
|
+
_disable_internal_error_handling()
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
3
|
import lldb
|
|
4
|
-
from construct import
|
|
4
|
+
from construct import Array, CString, Hex, If, Int32ub, Int32ul, Int64ul, Pointer, Struct, Tell, this
|
|
5
5
|
from humanfriendly import prompts
|
|
6
6
|
|
|
7
|
-
from hilda.snippets.macho.image_info import
|
|
7
|
+
from hilda.snippets.macho.image_info import ImageInfo, dyld_image_info_t
|
|
8
8
|
from hilda.snippets.macho.macho import mach_header_t
|
|
9
9
|
from hilda.snippets.uuid import uuid_t
|
|
10
10
|
from hilda.symbol import SymbolFormatField
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import lldb
|
|
2
|
-
from construct import
|
|
2
|
+
from construct import CString, If, Int64ul, Pointer, Struct, this
|
|
3
3
|
|
|
4
4
|
from hilda.snippets.macho.macho import mach_header_t
|
|
5
5
|
from hilda.snippets.macho.macho_load_commands import LoadCommands
|
hilda/snippets/macho/macho.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import lldb
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Array, Int8ul
|
|
2
|
+
from construct import Array, Bytes, Enum, Hex, Int8ul, Int32ul, Int64ul, PaddedString, Pointer, Seek, Struct, Switch, \
|
|
3
|
+
Tell, this
|
|
5
4
|
|
|
6
5
|
from hilda.snippets.macho.apple_version import version_t
|
|
7
6
|
from hilda.symbol import SymbolFormatField
|
hilda/snippets/remotepairingd.py
CHANGED
|
@@ -35,9 +35,7 @@ TLV_MAP = {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
def
|
|
39
|
-
src = hilda.registers.x0
|
|
40
|
-
end = hilda.registers.x1
|
|
38
|
+
def _TLV8CopyCoalesced_bp(hilda, *args):
|
|
41
39
|
type_ = hilda.registers.x2
|
|
42
40
|
out_len = hilda.registers.x3
|
|
43
41
|
out_len.item_size = 4
|
|
@@ -56,7 +54,7 @@ def TLV8CopyCoalesced_bp(hilda, *args):
|
|
|
56
54
|
hilda.cont()
|
|
57
55
|
|
|
58
56
|
|
|
59
|
-
def
|
|
57
|
+
def _TLV8BufferAppend_bp(hilda, *args):
|
|
60
58
|
buffer = hilda.registers.x0
|
|
61
59
|
type_ = hilda.registers.x1
|
|
62
60
|
buffer = hilda.registers.x2
|
|
@@ -68,9 +66,7 @@ def TLV8BufferAppend_bp(hilda, *args):
|
|
|
68
66
|
hilda.cont()
|
|
69
67
|
|
|
70
68
|
|
|
71
|
-
def
|
|
72
|
-
client = hilda.registers.x0
|
|
73
|
-
params = hilda.registers.x1
|
|
69
|
+
def _SRPClientStart_libsrp_bp(hilda, *args):
|
|
74
70
|
username = hilda.registers.x2
|
|
75
71
|
username_len = hilda.registers.x3
|
|
76
72
|
password = hilda.registers.x4
|
|
@@ -91,8 +87,7 @@ def SRPClientStart_libsrp_bp(hilda, *args):
|
|
|
91
87
|
hilda.cont()
|
|
92
88
|
|
|
93
89
|
|
|
94
|
-
def
|
|
95
|
-
digest_info = hilda.registers.x0
|
|
90
|
+
def _cced25519_sign_bp(hilda, *args):
|
|
96
91
|
sig = hilda.registers.x1
|
|
97
92
|
len = hilda.registers.x2
|
|
98
93
|
msg = hilda.registers.x3
|
|
@@ -109,8 +104,7 @@ def cced25519_sign_bp(hilda, *args):
|
|
|
109
104
|
hilda.cont()
|
|
110
105
|
|
|
111
106
|
|
|
112
|
-
def
|
|
113
|
-
digest_info = hilda.registers.x0
|
|
107
|
+
def _cced25519_verify_bp(hilda, *args):
|
|
114
108
|
sig = hilda.registers.x3
|
|
115
109
|
len = hilda.registers.x1
|
|
116
110
|
msg = hilda.registers.x2
|
|
@@ -125,7 +119,7 @@ def cced25519_verify_bp(hilda, *args):
|
|
|
125
119
|
hilda.cont()
|
|
126
120
|
|
|
127
121
|
|
|
128
|
-
def
|
|
122
|
+
def _CryptoHKDF_bp(hilda, *args):
|
|
129
123
|
descriptor = hilda.registers.x0
|
|
130
124
|
key = hilda.registers.x1.peek(hilda.registers.x2)
|
|
131
125
|
salt = hilda.registers.x3
|
|
@@ -177,14 +171,14 @@ def _chacha20_poly1305_decrypt_all_bp(hilda, *args):
|
|
|
177
171
|
def monitor_crypto_functions() -> None:
|
|
178
172
|
hilda_client = lldb.hilda_client
|
|
179
173
|
|
|
180
|
-
hilda_client.symbols.TLV8CopyCoalesced.bp(
|
|
181
|
-
hilda_client.symbols.TLV8BufferAppend.bp(
|
|
182
|
-
hilda_client.symbols.SRPClientStart_libsrp.bp(
|
|
174
|
+
hilda_client.symbols.TLV8CopyCoalesced.bp(_TLV8CopyCoalesced_bp)
|
|
175
|
+
hilda_client.symbols.TLV8BufferAppend.bp(_TLV8BufferAppend_bp)
|
|
176
|
+
hilda_client.symbols.SRPClientStart_libsrp.bp(_SRPClientStart_libsrp_bp)
|
|
183
177
|
hilda_client.symbols.SRPClientVerify_libsrp.monitor()
|
|
184
178
|
hilda_client.symbols.SRPServerStart_libsrp.monitor()
|
|
185
179
|
hilda_client.symbols.SRPServerVerify_libsrp.monitor()
|
|
186
|
-
hilda_client.symbols.cced25519_sign.bp(
|
|
187
|
-
hilda_client.symbols.cced25519_verify.bp(
|
|
188
|
-
hilda_client.symbols.CryptoHKDF.bp(
|
|
180
|
+
hilda_client.symbols.cced25519_sign.bp(_cced25519_sign_bp)
|
|
181
|
+
hilda_client.symbols.cced25519_verify.bp(_cced25519_verify_bp)
|
|
182
|
+
hilda_client.symbols.CryptoHKDF.bp(_CryptoHKDF_bp)
|
|
189
183
|
hilda_client.symbols._chacha20_poly1305_encrypt_all.bp(_chacha20_poly1305_encrypt_all_bp)
|
|
190
184
|
hilda_client.symbols._chacha20_poly1305_decrypt_all.bp(_chacha20_poly1305_decrypt_all_bp)
|
hilda/snippets/uuid.py
CHANGED
hilda/snippets/xpc.py
CHANGED
|
@@ -54,6 +54,15 @@ def from_xpc_object(address: int):
|
|
|
54
54
|
return lldb.hilda_client.from_ns(f'_CFXPCCreateCFObjectFromXPCObject({address})')
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
def disable_transaction_exit():
|
|
58
|
+
"""
|
|
59
|
+
xpc_transaction_exit_clean will kill the process when transaction is done.
|
|
60
|
+
By patching this function the process will stay alive.
|
|
61
|
+
"""
|
|
62
|
+
hilda = lldb.hilda_client
|
|
63
|
+
hilda.symbols.xpc_transaction_exit_clean.poke_text('ret')
|
|
64
|
+
|
|
65
|
+
|
|
57
66
|
def to_xpc_object(obj: object):
|
|
58
67
|
"""
|
|
59
68
|
Convert python object to XPC object.
|
hilda/symbol.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
from construct import FormatField
|
|
2
|
-
from contextlib import contextmanager
|
|
3
|
-
import struct
|
|
4
1
|
import os
|
|
2
|
+
import struct
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
|
|
5
|
+
from construct import FormatField
|
|
5
6
|
|
|
6
7
|
from hilda.objective_c_class import Class
|
|
7
8
|
|
|
@@ -119,8 +120,11 @@ class Symbol(int):
|
|
|
119
120
|
def poke(self, buf):
|
|
120
121
|
return self._client.poke(self, buf)
|
|
121
122
|
|
|
122
|
-
def
|
|
123
|
-
return self._client.
|
|
123
|
+
def poke_text(self, code: str) -> int:
|
|
124
|
+
return self._client.poke_text(self, code)
|
|
125
|
+
|
|
126
|
+
def peek_str(self):
|
|
127
|
+
return self._client.peek_str(self)
|
|
124
128
|
|
|
125
129
|
def monitor(self, **args):
|
|
126
130
|
return self._client.monitor(self, **args)
|
hilda/symbols_jar.py
CHANGED
hilda/ui/colors.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "green",
|
|
3
|
+
"address": "bright_blue",
|
|
4
|
+
"regs_title": "green",
|
|
5
|
+
"regs_name": "cyan",
|
|
6
|
+
"regs_value": "white",
|
|
7
|
+
"mnemonic": "white",
|
|
8
|
+
"operands": "white",
|
|
9
|
+
"basename": "yellow",
|
|
10
|
+
"stack_offset": "white",
|
|
11
|
+
"stack_data": "white",
|
|
12
|
+
"diff": "red"
|
|
13
|
+
}
|