Page 1 of 2
detect EXE/DLL bitness (x86 or x64)
Posted: 29 Apr 2014 10:46
by bdeshi
Hi, here's a script to detect whether a selected binary executable file is 64bits or 32bits, or 16 bits, or DOS. Feel free to use it or modify it as you need.(in fact I'll be glad if you do

)
See posts below for much better and more useful updates of this script
Versions:
v2:
http://www.xyplorer.com/xyfc/viewtopic. ... 74#p111439
v3:
http://www.xyplorer.com/xyfc/viewtopic. ... 74#p111498
v4:
http://www.xyplorer.com/xyfc/viewtopic. ... 74#p111515
v5:
http://www.xyplorer.com/xyfc/viewtopic. ... 74#p111533
v6:
http://www.xyplorer.com/xyfc/viewtopic. ... 15#p111620
=============
These are the original very basic first versions of the script and CC by me, kept here for history's sake.
Script:
Code: Select all
"Bitness Detector"
//first version, by SammaySarkar, 13th April, 2014
$filext = getpathcomponent(<curitem>,ext);
if ($filext == "exe") || ($filext == "dll") || ($filext == "ocx") || ($filext == "cpl") { $file = "<curitem>"; }
else { $file = inputfile("<curpath>","exe|dll|ocx|cpl", "Choose a valid file"); }
unset $filext;
if ( readfile($file, b, 2,, 1) == "MZ" ) {
$pntr = hexdump(readfile($file, b, 4,, 61),,r);
$pntr = hextodec(gettoken($pntr,2).gettoken($pntr,1));
if ($pntr-8 <= filesize($file)) {
$bitnum = hexdump(readfile($file, b, 6,, $pntr+1),,r);
if ( strpos($bitnum, '64 86') != -1 ) { msg "$file<crlf>is 64 bit."; }
elseif ( strpos($bitnum, '00 02') != -1 ) { msg "$file<crlf>is 64 bit (IA64)."; }
elseif ( strpos($bitnum, '4C 01') != -1 ) { msg "$file<crlf>is 32 bit."; }
elseif (strpos($bitnum, '4E 45') != -1) || (strpos($bitnum, '4C 45') != -1) { msg "$file<crlf>is 16 bit."; }
//elseif( ) { msg"$file<crlf>is bit"; }
else { msg "$file<crlf>is a DOS program."; }
} else { msg "$file<crlf>is probably a DOS program."; }
} else { msg "Cannot detect bitness."; }
[/size]
CustomColum snippet:
Code: Select all
Snip: CustomColumn 1
XYplorer 14.00.0115, 5/14/2014 08:49:06 AM
Action
ConfigureColumn
Caption
Bitness
Type
3
Definition
$file = <cc_item>;
if (readfile($file, b, 2, , 1) == "MZ") {
$pntr = hexdump(readfile($file, b, 4, , 61),,r);
$pntr = hextodec(gettoken($pntr,2).gettoken($pntr,1));
if ($pntr-8 <= filesize($file)) {
$bitnum = hexdump(readfile($file, b, 6,, $pntr+1), ,r);
if (strpos($bitnum, '64 86') != -1) { return "64bit"; }
elseif (strpos($bitnum, '00 02') != -1) { return "~64bit"; }
elseif (strpos($bitnum, '4C 01') != -1) { return "32bit"; }
elseif (strpos($bitnum, '4E 45') != -1)||(strpos($bitnum, '4C 45') != -1) { return "16bit"; }
else { return "DOS"; }
} else { return "~DOS"; }
} else { return "N/A"; }
Format
0
Trigger
1
Item Type
0
Item Filter
exe;dll;ocx;cpl
[/size]
It only detects "plain" 64bit and 32bit files, old DOS exe's and .NET is unsupported.
Check posts below for better detection.
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 13 May 2014 09:21
by admin
Nice one!
With the new hexdump() you could even streamline it a bit...

Re: detect EXE/DLL bitness (x86 or x64)
Posted: 13 May 2014 09:35
by bdeshi
Thanks, right.
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 14 May 2014 09:20
by bdeshi
Okay, updated the script. Has basic detection of 16bit files. But more importantly, it
won't generate a fatal error anymore when bytes to read are out of file size limits.
Tested in CustomColumn, pretty fast, so posted a CC script too.
And... it's more user-friendly now, can I ask this thread be moved to scripts exchange? 
v
Thank you!

Re: detect EXE/DLL bitness (x86 or x64)
Posted: 14 May 2014 09:23
by admin
Sure, thanks!

Re: detect EXE/DLL bitness (x86 or x64)
Posted: 29 Jun 2014 10:35
by Enternal
Amazing! I just found several uses for it! Thanks!
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 29 Jun 2014 16:08
by bdeshi
Ah, your comment made it a success!!! thank you!
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 09 Sep 2014 13:47
by PeterH
SammaySarkar wrote:Hi, here's a script to detect whether a selected exe/dll/ocx/cpl file is 64bits or 32bits, or 16 bits, or DOS apps. Feel free to use it or modify it as you need.(in fact I'll be glad if you do

)
Hi Sammay,
you asked for changes - here are some.
Real functional changes:
- centralized the allowed extensions to variable $extlist
- added extension 'sys'
- test for extension by GetTokenIndex(), allow mixed case
Non-functional
- added some quotes for syntax (e.g. 'b')
- added some blanks and some empty lines for format
The code:
Code: Select all
"BitnessDetector"
// by SammaySarkar, modified by PeterH 2014-09-09
$extlist = 'exe|dll|ocx|cpl|sys'; // allowed extentions
$filext = getpathcomponent(<curitem>,ext);
If (GetTokenIndex($filext, $extlist, , 'i') > 0) { $file = "<curitem>"; }
Else { $file = Inputfile("<curpath>", $filext, "Choose a valid file"); }
if (readfile($file, 'b', 2, , 1) == "MZ") {
$pntr = hexdump(readfile($file, 'b', 4, , 61), , 'r');
$pntr = hextodec(gettoken($pntr, 2) . gettoken($pntr, 1));
if ($pntr-8 <= filesize($file)) {
$bitnum = hexdump(readfile($file, 'b', 6, , $pntr+1), , 'r');
if (strpos($bitnum, '64 86') != -1) { msg "$file<crlf>is 64 bit."; }
elseif (strpos($bitnum, '00 02') != -1) { msg "$file<crlf>is 64 bit (IA64)."; }
elseif (strpos($bitnum, '4C 01') != -1) { msg "$file<crlf>is 32 bit."; }
elseif (strpos($bitnum, '4E 45') != -1)
|| (strpos($bitnum, '4C 45') != -1) { msg "$file<crlf>is 16 bit."; }
//elseif (...) { msg "$file<crlf>is bit."; }
else { msg "$file<crlf>is a DOS program."; }
}
else { msg "$file<crlf>is probably a DOS program."; }
}
else { msg "Cannot detect bitness."; }
If OK you can copy it to first post.
Open for further suggestions...
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 09 Sep 2014 15:48
by bdeshi
Of coure it's okay.
I just replaced my original script (which reeked of noobidity
)
Much appreciated.
Edit 10th sep, 2014: since there have been many updates, I repasted my original script back in the first post (which does still reek of "noobidity"
)
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 09 Sep 2014 19:12
by Snail
Very nice.
Here is a little more updating.
Code: Select all
"BitnessDetector"
// by SammaySarkar, modified by PeterH 2014-09-09, and Snail 2014-09-09.
// Expanded extensions list, added COM support, added more details, added none ext error trap, improved open file, added limited packed exe support.
$extlist = 'exe|dll|ocx|cpl|sys|com'; // allowed extensions
$filext = getpathcomponent(<curitem>, ext);
If (GetTokenIndex($filext, $extlist, , 'i') > 0) { $file = "<curitem>"; }
Else { msg "BIT testable files limited to<crlf>$extlist.<crlf>.$filext is not valid!";
$file = Inputfile("<curpath>", $extlist, "Choose a valid file");
$filext = ""; }
if (readfile($file, 'b', 2, , 1) == "MZ") {
$pntr = hexdump(readfile($file, 'b', 4, , 61), , 'r');
$pntr = hextodec(gettoken($pntr, 2) . gettoken($pntr, 1));
if ($pntr-8 <= filesize($file)) {
$bitnum = hexdump(readfile($file, 'b', 6, , $pntr+1), , 'r');
$byteme = $bitnum;
// HI-Lo bits are inverted!
if (strpos($bitnum, '64 86') != -1) { msg "$file<crlf>is AMD64 WinPE+ Lite x64 bit $filext."; }
elseif (strpos($bitnum, '02 00') != -1) { msg "$file<crlf>is IA64 WinPE+ x64 bit $filext."; }
elseif (strpos($bitnum, '0B 00') != -1) { msg "$file<crlf>is Magic # x64 bit $filext."; }
elseif (strpos($bitnum, '0B 01') != -1) { msg "$file<crlf>is Magic # 32 bit $filext."; }
elseif (strpos($bitnum, '0B 02') != -1) { msg "$file<crlf>is Magic # 64 bit $filext."; }
elseif (strpos($bitnum, '07 01') != -1) { msg "$file<crlf>is ROM non-bit $filext."; }
elseif (strpos($bitnum, '00 4C') != -1) { msg "$file<crlf>is WinPE x86 32 bit $filext."; }
elseif (strpos($bitnum, '01 4C') != -1) { msg "$file<crlf>is i386 WinPE 32 bit $filext."; }
elseif (strpos($bitnum, '07 06') != -1) { msg "$file<crlf>is DOS Compiled 16 bit $filext."; }
elseif (strpos($bitnum, '0C A5') != -1) { msg "$file<crlf>is DOS Executable 16 bit $filext."; }
elseif (strpos($bitnum, '4E 45') != -1)
|| (strpos($bitnum, '4C 45') != -1) { msg "$file<crlf>is WinNE 16 bit $filext."; }
}
else { msg "$file<crlf>is probably a PACKED executable."; }
}
else { msg "Cannot detect bitness.<crlf>Probably a PACKED executable."; }
A lot more could be done, such as searching of UPX and .DATA blocks to indicate types of packed executables.
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 09 Sep 2014 20:00
by bdeshi
That's so much better! thank you.
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 09 Sep 2014 22:01
by TheQwerty
To keep the changes going...
BitnessDetector.xys
This is a much bigger modification...
- Easier to use the script standalone or as a Custom Column Script.*
- Thus descriptions were reworded for better sorting in a column.
- Determines which item(s) to test in the following order:
- Tagged / Custom Column Item
- PFA/POM Item
- Dropped Item(s)
- Selected Item(s)
- Focused Item
- That's right items with an 's' it supports more than one.
- Moved the magic bits into a list - might be easier to update.
* To use this script for a custom column script you must first set the Global variable $G_INTERACTIVE to false.
This is because the <cc_*> variables persist outside of the Custom Column Script meaning there is no good way to detect when the script should be in interactive mode. In other words your custom column for this script should look like:
Code: Select all
Global $G_INTERACTIVE = false;Load 'BitnessDetector';
Here we go:
Code: Select all
/*#############################################################################\
BitnessDetector.xys
This script attempts to determine for which architecture binaries and executables
are compiled.
It can be used as-is or within a Custom Column Script, but note that due to
limitations in XY the Custom Column Script must set a Global variable
'$G_INTERACTIVE' to 'false' before calling the script. Example:
Global $G_INTERACTIVE = false;
Load 'BitnessDetector';
See also:
http://www.xyplorer.com/xyfc/viewtopic.php?f=7&t=11574
[ABOUT]
Author = SammaySarkar
Version = 4.0
Date = 2014-09-09 16:00z
Requires = XYplorer v14.40.0300
Contributors = PeterH, Snail, TheQwerty
[]
\#############################################################################*/
"BitnessDetector"
// Changed separator to semi-colon so it matches CC filter.
$SUPPORTED_EXTENSIONS = 'exe;dll;ocx;cpl;sys;com'; // allowed extensions
// Unfortunately the <cc_*> vars persist outside the scope of the CC script,
// so there is no way to determine when running within a CC script.
// Until Don makes this possible we'll use a global variable.
// http://www.xyplorer.com/xyfc/viewtopic.php?f=3&t=11181&p=111509#p111509
// Thus it is the responsibility of the CC script to set:
// Global $G_INTERACTIVE = false;
Global $G_INTERACTIVE;
if ($G_INTERACTIVE == '') {
$G_INTERACTIVE = true;
}
// If not interactive...
if (! $G_INTERACTIVE) {
// Assume we are in a Custom Column.
$list = "<cc_item>";
} else {
// Determine items to work on.
// <cc_item> is removed because of the above-mentioned issue with their scope.
// If fixed it will probably be #3.
$list = GetToken(FormatList("<taggeditem>|<pfaitem>|<get drop <crlf>>|<get SelectedItemsPathNames <crlf>>|<focitem>", 'ted'), 1, '|');
}
// These are the magic bits and descriptions.
// Try to keep bitness first so it sorts better in a custom column.
$magicBits = <<<#KNOWNBITS
64 86|64-bit [AMD64 WinPE+ Lite]
02 00|64-bit [IA64 WinPE+]
0B 00|64-bit [Magic # x64]
0B 01|32-bit [Magic # 32]
0B 02|64-bit [Magic # 64]
07 01|ROM non-bit
00 4C|32-bit [WinPE x86]
01 4C|32-bit [i386 WinPE]
07 06|16-bit [DOS Compiled]
0C A5|16-bit [DOS Executable]
4[CE] 45|16-bit [WinNE]
#KNOWNBITS;
// Collection of all results.
$allResults = '';
foreach ($item, $list, "<crlf>") {
if ($item == '') { continue; }
$result = 'Unknown';
// Not a file.
if (exists($item) != 1) {
$result = 'Not a file.';
// Unsupported extension.
} elseif (! GetTokenIndex(GetPathComponent($item, 'ext'), $SUPPORTED_EXTENSIONS, ';', 'i')) {
$result = 'Extension not supported';
// Missing MZ header.
} elseif (ReadFile($item, 'b', 2, /*codepage*/, 1) != 'MZ') {
$result = 'Maybe PACKED - Not MZ';
// Contains MZ header.
} else {
$pntr = HexDump(ReadFile($item, 'b', 4, /*codepage*/, 61), 0, 'r');
$pntr = HexToDec(GetToken($pntr, 2) . GetToken($pntr, 1));
// Pointer out of range.
if ($pntr-8 > FileSize($item)) {
$result = 'Maybe PACKED';
} else {
$bitnum = HexDump(ReadFile($item, 'b', 6, /*codepage*/, $pntr+1), 0, 'r');
foreach ($line, $magicBits, "<crlf>") {
// Trim line & skip empties.
$line = Trim($line, " <tab><crlf>");
if ($line == '') { continue; }
// Split line
$pattern = GetToken($line, 1, '|', 't');
$text = GetToken($line, 2, '|', 't', 2);
// Check for match
if ($bitnum LikeI "*$pattern*") {
$result = $text;
break;
}
} // foreach - knownBits
} // valid pointer
} // MZ header
$allResults = $allResults . $item . "<crlf><tab>" . $result . "<crlf>";
} // foreach - list
// Display results when not in a Custom Column.
if ($G_INTERACTIVE) {
Text $allResults;
} else {
return $result;
}
[/size]
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 10 Sep 2014 00:30
by klownboy
TheQwerty wrote:To keep the changes going...
and they keep getting better. Thanks to all.

Re: detect EXE/DLL bitness (x86 or x64)
Posted: 10 Sep 2014 06:43
by Snail
A very nice update!
I have taken it and expanded a little more. Mainly, I've added more recognition for older/odd executables.
Code: Select all
/*#############################################################################\
BitnessDetector.xys
This script attempts to determine for which architecture binaries and executables
are compiled.
It can be used as-is or within a Custom Column Script, but note that due to
limitations in XY the Custom Column Script must set a Global variable
'$G_INTERACTIVE' to 'false' before calling the script. Example:
Global $G_INTERACTIVE = false;
Load 'BitnessDetector';
See also:
http://www.xyplorer.com/xyfc/viewtopic.php?f=7&t=11574
[ABOUT]
Author = SammaySarkar
Version = 5.0
Date = 2014-09-10 02:00z
Requires = XYplorer v14.40.0300
Contributors = PeterH, Snail, TheQwerty
[]
\#############################################################################*/
"BitnessDetector"
// Changed separator to semi-colon so it matches CC filter.
$SUPPORTED_EXTENSIONS = 'exe;dll;ocx;cpl;sys;com;gem;app;elf'; // allowed extensions
// Unfortunately the <cc_*> vars persist outside the scope of the CC script,
// so there is no way to determine when running within a CC script.
// Until Don makes this possible we'll use a global variable.
// http://www.xyplorer.com/xyfc/viewtopic.php?f=3&t=11181&p=111509#p111509
// Thus it is the responsibility of the CC script to set:
// Global $G_INTERACTIVE = false;
Global $G_INTERACTIVE;
if ($G_INTERACTIVE == '') {
$G_INTERACTIVE = true;
}
// If not interactive...
if (! $G_INTERACTIVE) {
// Assume we are in a Custom Column.
$list = "<cc_item>";
} else {
// Determine items to work on.
// <cc_item> is removed because of the above-mentioned issue with their scope.
// If fixed it will probably be #3.
$list = GetToken(FormatList("<taggeditem>|<pfaitem>|<get drop <crlf>>|<get SelectedItemsPathNames <crlf>>|<focitem>", 'ted'), 1, '|');
}
// These are the magic bits and descriptions.
// Try to keep bitness first so it sorts better in a custom column.
$magicBits = <<<#KNOWNBITS
64 86|64-bit [AMD64 WinPE+ Lite]
02 00|64-bit [IA64 WinPE+]
0B 00|64-bit [Magic # x64]
0B 01|32-bit [Magic # 32]
0B 02|64-bit [Magic # 64]
07 01|ROM non-bit
00 4C|32-bit [WinPE x86]
01 4C|32-bit [i386 WinPE]
07 06|16-bit [DOS Compiled]
0C A5|16-bit [DOS Executable]
4[CE] 45|16-bit [WinNE]
#KNOWNBITS;
// Collection of all results.
$allResults = '';
foreach ($item, $list, "<crlf>") {
if ($item == '') { continue; }
// Set header MZ value
$header = ReadFile($item, 'b', 2, /*codepage*/, 1);
// Default responce if no other provided.
$result = 'File may be PACKED (exe/com).';
// Not a file.
if (exists($item) != 1) {
$result = 'Not a suported file.';
// Unsupported extension.
} elseif (! GetTokenIndex(GetPathComponent($item, 'ext'), $SUPPORTED_EXTENSIONS, ';', 'i')) {
$result = 'Extension not supported'<crlf>'Current support for > ' . $SUPPORTED_EXTENSIONS;
// Missing MZ header.
} elseif ($header != 'MZ') {
$result = 'File may be packed with UPX/PKLite/ASPack'<crlf>'or other protection.'<crlf>'Or, it may not be an executable file at all.'<crlf>' - Not MZ';
// Old non-MZ executbles.
} elseif ($header == 'NE') {
$result = 'File may be DOS4 8bit or Win3x 16bit.'<crlf>' - Not MZ';
} elseif ($header == 'LX') {
$result = 'File may be OS/2 8bit.'<crlf>' - Not MZ';
} elseif ($header == 'PI') {
$result = 'File may be PalmDOS 8bit.'<crlf>' - Not MZ';
} elseif ($header == 'XI') {
$result = 'File may be PalmDOS Extended 16bit.'<crlf>' - Not MZ';
} elseif ($header == 'DL') {
$result = 'File may be DOS Manager 8bit.'<crlf>' - Not MZ';
} elseif ($header == 'MP') {
$result = 'File may be DOS Extender 8bit.'<crlf>' - Not MZ';
} elseif ($header == 'P2') {
$result = 'File may be DOS Extender 16bit.'<crlf>' - Not MZ';
} elseif ($header == 'P3') {
$result = 'File may be DOS Extender 32bit.'<crlf>' - Not MZ';
// Contains MZ header.
} else {
$pntr = HexDump(ReadFile($item, 'b', 4, /*codepage*/, 61), 0, 'r');
$pntr = HexToDec(GetToken($pntr, 2) . GetToken($pntr, 1));
// Pointer out of range.
if ($pntr-8 > FileSize($item)) {
$result = 'Maybe PACKED';
} else {
$bitnum = HexDump(ReadFile($item, 'b', 6, /*codepage*/, $pntr+1), 0, 'r');
foreach ($line, $magicBits, "<crlf>") {
// Trim line & skip empties.
$line = Trim($line, " <tab><crlf>");
if ($line == '') { continue; }
// Split line
$pattern = GetToken($line, 1, '|', 't');
$text = GetToken($line, 2, '|', 't', 2);
// Check for match
if ($bitnum LikeI "*$pattern*") {
$result = $text;
break;
}
} // foreach - knownBits
} // valid pointer
} // MZ header
$allResults = $allResults . $item . "<crlf><tab>" . $result . "<crlf>";
} // foreach - list
// Display results when not in a Custom Column.
if ($G_INTERACTIVE) {
Text $allResults;
} else {
return $result;
}
BitnessDetector.zip
Re: detect EXE/DLL bitness (x86 or x64)
Posted: 10 Sep 2014 07:05
by bdeshi
Nice to see so much interest...
( if this goes on, I see this script becoming Ultimate File Detector...

)
BTW, there's absolutely no reason now to have me as the only author. This intro note is better suited:
Code: Select all
...
[About]
Authors = PeterH, SammaySarkar, Snail, TheQwerty
...