Skip to content

Instantly share code, notes, and snippets.

@dzwdz
Created January 13, 2024 14:07
Show Gist options
  • Select an option

  • Save dzwdz/4c51df9cc491700fccc0d33db516e709 to your computer and use it in GitHub Desktop.

Select an option

Save dzwdz/4c51df9cc491700fccc0d33db516e709 to your computer and use it in GitHub Desktop.
find SFX RAR header
import sys, struct
### some helper functions ###
def die(*args):
print(*args)
exit(0)
def pread(fp, size, offset):
fp.seek(offset)
return fp.read(size)
def read_u32le(fp, offset): # unsigned, 32 bits, little endian
return struct.unpack('<L', pread(fp, 4, offset))[0]
def hexdump(buf, offset=0):
for i in range(0, len(buf), 16):
line = buf[i:i+16]
print(
'%08x' % (offset + i),
' '.join(["%02x" % c for c in line]),
''.join([(chr(c) if 0x20 <= c < 0x7F else '.') for c in line]),
sep=' '
)
###
print(sys.argv[1])
fp = open(sys.argv[1], 'rb')
if pread(fp, 2, 0) != b'MZ': die("no MZ")
pe_header = read_u32le(fp, 0x3c)
if pread(fp, 4, pe_header) != b'PE\0\0': die("no PE header")
# not sure where the 0x140 came from
sections_loc = pe_header + 0xf8
sections = pread(fp, 0x140, sections_loc)
print("sections:")
hexdump(sections, sections_loc)
# find .rsrc's entry
rsrc_header = sections_loc + sections.index(b'.rsrc')
print(".rsrc header at 0x%x" % rsrc_header)
# https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/Debug/pe-format.md#section-table-section-headers
rsrc_loc = read_u32le(fp, rsrc_header + 20) # PointerToRawData
rsrc_len = read_u32le(fp, rsrc_header + 16) # SizeOfRawData
print('.rsrc', hex(rsrc_loc), hex(rsrc_len))
stub_end = rsrc_loc + rsrc_len
print('stub_end', hex(stub_end))
if pread(fp, 4, stub_end) != b'Rar!': die("didn't find RAR header")
print("ok, found RAR header")
"""
this works on the SFX that inspired this issue
file(1) has two other ways of detecting SFXes, though
1. just looking for "Rar!" at 0x17888. I assume this targets a particular version
of the SFX stub, and is probably redundant with the other rules?
2. "Skip to the end of the EXE", by reading some stuff from the MZ header.
I can't figure out how it's supposed to work, though, and I don't have any
archives that this checks works for handy.
I think by "EXE" they might actually mean old DOS executables?
That being said - you can get the Rar for DOS installers archive.org,
and neither file(1) nor bsdtar seem to recognize them as SFX archives (which they are).
https://web.archive.org/web/20030527011110/http://www.rarlab.com/download.htm
https://web.archive.org/web/20070707133254/http://www.rarlab.com/download.htm
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment