337
339
If this indirect offset cannot be used as-is, there are simple calculations
338
340
possible: appending
339
.Em [+-*/%&|^]<number>
341
.Em [+-*/%\*[Am]|^]\*[Lt]number\*[Gt]
340
342
inside parentheses allows one to modify
341
343
the value read from the file before it is used as an offset:
342
.Bd -literal -offset indent
344
.Bd -literal -offset indent
343
345
# MS Windows executables are also valid MS-DOS executables
345
347
# sometimes, the value at 0x18 is less that 0x40 but there's still an
346
348
# extended executable, simply appended to the file
348
>>(4.s*512) leshort 0x014c COFF executable (MS-DOS, DJGPP)
349
>>(4.s*512) leshort !0x014c MZ executable (MS-DOS)
349
\*[Gt]0x18 leshort \*[Lt]0x40
350
\*[Gt]\*[Gt](4.s*512) leshort 0x014c COFF executable (MS-DOS, DJGPP)
351
\*[Gt]\*[Gt](4.s*512) leshort !0x014c MZ executable (MS-DOS)
352
354
Sometimes you do not know the exact offset as this depends on the length or
353
position (when indirection was used before) of preceding fields. You can
354
specify an offset relative to the end of the last up-level field using
355
position (when indirection was used before) of preceding fields.
356
You can specify an offset relative to the end of the last up-level
356
359
as a prefix to the offset:
357
.Bd -literal -offset indent
360
.Bd -literal -offset indent
360
>>(0x3c.l) string PE\e0\e0 PE executable (MS-Windows)
362
\*[Gt]0x18 leshort \*[Gt]0x3f
363
\*[Gt]\*[Gt](0x3c.l) string PE\e0\e0 PE executable (MS-Windows)
361
364
# immediately following the PE signature is the CPU type
362
>>>&0 leshort 0x14c for Intel 80386
363
>>>&0 leshort 0x184 for DEC Alpha
365
\*[Gt]\*[Gt]\*[Gt]\*[Am]0 leshort 0x14c for Intel 80386
366
\*[Gt]\*[Gt]\*[Gt]\*[Am]0 leshort 0x184 for DEC Alpha
366
369
Indirect and relative offsets can be combined:
367
.Bd -literal -offset indent
370
.Bd -literal -offset indent
370
>>(4.s*512) leshort !0x014c MZ executable (MS-DOS)
372
\*[Gt]0x18 leshort \*[Lt]0x40
373
\*[Gt]\*[Gt](4.s*512) leshort !0x014c MZ executable (MS-DOS)
371
374
# if it's not COFF, go back 512 bytes and add the offset taken
372
375
# from byte 2/3, which is yet another way of finding the start
373
376
# of the extended executable
374
>>>&(2.s-514) string LE LE executable (MS Windows VxD driver)
377
\*[Gt]\*[Gt]\*[Gt]\*[Am](2.s-514) string LE LE executable (MS Windows VxD driver)
377
380
Or the other way around:
378
.Bd -literal -offset indent
381
.Bd -literal -offset indent
381
>>(0x3c.l) string LE\e0\e0 LE executable (MS-Windows)
383
\*[Gt]0x18 leshort \*[Gt]0x3f
384
\*[Gt]\*[Gt](0x3c.l) string LE\e0\e0 LE executable (MS-Windows)
382
385
# at offset 0x80 (-4, since relative offsets start at the end
383
386
# of the up-level match) inside the LE header, we find the absolute
384
387
# offset to the code area, where we look for a specific signature
385
>>>(&0x7c.l+0x26) string UPX \eb, UPX compressed
388
\*[Gt]\*[Gt]\*[Gt](\*[Am]0x7c.l+0x26) string UPX \eb, UPX compressed
389
.Bd -literal -offset indent
392
.Bd -literal -offset indent
392
>>(0x3c.l) string LE\e0\e0 LE executable (MS-Windows)
394
\*[Gt]0x18 leshort \*[Gt]0x3f
395
\*[Gt]\*[Gt](0x3c.l) string LE\e0\e0 LE executable (MS-Windows)
393
396
# at offset 0x58 inside the LE header, we find the relative offset
394
397
# to a data area where we look for a specific signature
395
>>>&(&0x54.l-3) string UNACE \eb, ACE self-extracting archive
398
\*[Gt]\*[Gt]\*[Gt]\*[Am](\*[Am]0x54.l-3) string UNACE \eb, ACE self-extracting archive
398
401
Finally, if you have to deal with offset/length pairs in your file, even the
399
402
second value in a parenthesized expression can be taken from the file itself,
400
using another set of parentheses. Note that this additional indirect offset
401
is always relative to the start of the main indirect offset.
402
.Bd -literal -offset indent
403
using another set of parentheses.
404
Note that this additional indirect offset is always relative to the
405
start of the main indirect offset.
406
.Bd -literal -offset indent
405
>>(0x3c.l) string PE\e0\e0 PE executable (MS-Windows)
408
\*[Gt]0x18 leshort \*[Gt]0x3f
409
\*[Gt]\*[Gt](0x3c.l) string PE\e0\e0 PE executable (MS-Windows)
406
410
# search for the PE section called ".idata"...
407
>>>&0xf4 search/0x140 .idata
411
\*[Gt]\*[Gt]\*[Gt]\*[Am]0xf4 search/0x140 .idata
408
412
# ...and go to the end of it, calculated from start+length;
409
413
# these are located 14 and 10 bytes after the section name
410
>>>>(&0xe.l+(-4)) string PK\e3\e4 \eb, ZIP self-extracting archive
414
\*[Gt]\*[Gt]\*[Gt]\*[Gt](\*[Am]0xe.l+(-4)) string PK\e3\e4 \eb, ZIP self-extracting archive
417
.Xr file __CSECTION__
418
\- the command that reads this file.