Skip to content

Instantly share code, notes, and snippets.

@bgrewell
Last active October 26, 2018 21:49
Show Gist options
  • Save bgrewell/3f4ed11737a24c1f7d7f0791c5b9be0e to your computer and use it in GitHub Desktop.
Save bgrewell/3f4ed11737a24c1f7d7f0791c5b9be0e to your computer and use it in GitHub Desktop.
import sys
import struct
import codecs
import binascii
sample_string = """
4C 00 00 00 01 14 02 00 00 00 00 00 C0 00 00 00
00 00 00 46 81 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 80 00 14 00
1F 00 E0 4F D0 20 EA 3A 69 10 A2 D8 08 00 2B 30
30 9D 14 00 2E 1E 20 20 EC 21 EA 3A 69 10 A2 DD
08 00 2B 30 30 9D 56 00 00 00 00 00 00 00 00 00
00 00 00 6A 00 00 00 00 00 00 00 00 00 00 5C 00
5C 00 31 00 30 00 2E 00 31 00 30 00 30 00 2E 00
32 00 2E 00 31 00 34 00 36 00 5C 00 65 00 70 00
74 00 73 00 63 00 5C 00 71 00 61 00 77 00 68 00
75 00 75 00 2E 00 64 00 6C 00 6C 00 00 00 00 00
00 00
"""
def convert_path_to_bytearray(path):
patharray = bytearray()
for idx, c in enumerate(path):
path_part = bytearray([ord(c), 0x00])
patharray.extend(path_part)
return patharray
def convert_size_to_little_endian_bytearray(value):
value_bytes = bytearray(value.to_bytes((value.bit_length() + 7) // 8, byteorder='little'))
if len(value_bytes) % 2 != 0:
value_bytes.append(0x00)
return value_bytes
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: {} <output filename>".format(sys.argv[0]))
exit(1)
header = bytearray()
header_size = bytearray(b'\x4C\x00') # Set Header Size
link_clsid = bytearray(b'\x00\x00\x01\x14\x02\x00\x00\x00\x00\x00\xC0\x00\x00\x00\x00\x00') # Set Link CLSID
link_flags = bytearray(b'\x00\x46\x81\x00') # Set Link Flags
file_attributes = bytearray(b'\x00\x00\x00\x00') # Set File Attributes
creation_time = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') # Set File Creation Time
access_time = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') # Set File Access Time
write_time = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') # Set File Write Time
file_size = bytearray(b'\x00\x00\x00\x00') # Set The Size Of The Link Target
icon_index = bytearray(b'\x00\x00\x00\x00') # Set the Index of an Icon
show_command = bytearray(b'\x00\x00\x00\x00') # Set the window state for the application
hotkey = bytearray(b'\x00\x00') # Set the HotKey Flags
res_1 = bytearray(b'\x00\x00') # Set Reserved 1 - Must be zero
res_2 = bytearray(b'\x00\x00\x00\x00') # Set Reserved 2 - Must be zero
res_3 = bytearray(b'\x00\x00\x00\x00') # Set Reserved 3 - Must be zero
# Build header
header.extend(header_size)
header.extend(link_clsid)
header.extend(link_flags)
header.extend(file_attributes)
header.extend(creation_time)
header.extend(access_time)
header.extend(write_time)
header.extend(file_size)
header.extend(icon_index)
header.extend(show_command)
header.extend(hotkey)
header.extend(res_1)
header.extend(res_2)
header.extend(res_3)
# Pad header to right size
header.append(0x00)
header.append(0x00)
# Setup LinkInfo
item_id_1_size = bytearray(b'\x14\x00') # My Computer CLSID size
print('item_id_1_size: ' + ' '.join('{:02X}'.format(x) for x in item_id_1_size))
item_id_1 = bytearray(b'\x1F\x00\xE0\x4F\xD0\x20\xEA\x3A\x69\x10\xA2\xD8\x08\x00\x2B\x30\x30\x9D') # My Computer CLSID
print('item_id_1: ' + ' '.join('{:02X}'.format(x) for x in item_id_1))
item_id_2_size = bytearray(b'\x14\x00') # Control Panel CLSID size
print('item_id_2_size: ' + ' '.join('{:02X}'.format(x) for x in item_id_2_size))
item_id_2 = bytearray(b'\x2E\x1E\x20\x20\xEC\x21\xEA\x3A\x69\x10\xA2\xDD\x08\x00\x2B\x30\x30\x9D') # Control Panel CLSID
print('item_id_2: ' + ' '.join('{:02X}'.format(x) for x in item_id_2))
item_id_3 = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
item_id_3.extend(convert_path_to_bytearray(sys.argv[1])) # Path to file
item_id_3_size = convert_size_to_little_endian_bytearray(len(item_id_3) + 2) # Path to file size
print('item_id_3_size: ' + ' '.join('{:02X}'.format(x) for x in item_id_3_size))
print('item_id_3: ' + ' '.join('{:02X}'.format(x) for x in item_id_3))
total_payload_length = 8 + len(item_id_1) + len(item_id_2) + len(item_id_3) # Length of the LinkInfo Section
id_list_size = bytearray(convert_size_to_little_endian_bytearray(total_payload_length)) # Set to actual size later
term = bytearray(b'\x00\x00') # TerminalID
# Build LinkInfo
linkinfo = bytearray()
linkinfo.extend(id_list_size)
linkinfo.extend(item_id_1_size)
linkinfo.extend(item_id_1)
linkinfo.extend(item_id_2_size)
linkinfo.extend(item_id_2)
linkinfo.extend(item_id_3_size)
linkinfo.extend(item_id_3)
linkinfo.extend(term)
# Build file
file_contents = bytearray()
file_contents.extend(header)
file_contents.extend(linkinfo)
# Print
print(' '.join('{:02X}'.format(x) for x in file_contents))
# Write File
output = open('output.lnk', 'wb')
output.write(file_contents)
output.flush()
output.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment