The script is able to determine the target CPU of a Portable Executable file. You will find the CPU identifiers in the msdn specification. Basically the ID for 32 bit files is 0x014C and for 64 bit files is 0x8664.
If you pass certain system files (like explorer.exe) to the sub routine you can also draw conclusions if you run a 32 or 64 bit OS.
I added some comments that should explain how it works. Anyway if you have questions just ask me ...
Code: Select all
@echo off &setlocal
echo file errorlevel CPU ID
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
call :getPETarget "%SystemRoot%\explorer.exe"
echo explorer.exe %errorlevel% %=ExitCode%
call :getPETarget "%SystemRoot%\system32\chcp.com"
echo chcp.com %errorlevel% %=ExitCode%
call :getPETarget "%SystemRoot%\system32\vbscript.dll"
echo vbscript.dll %errorlevel% %=ExitCode%
call :getPETarget "nothing"
echo nothing %errorlevel% %=ExitCode%
call :getPETarget "test1.txt"
echo test1.txt %errorlevel% %=ExitCode%
call :getPETarget "test2.txt"
echo test2.txt %errorlevel% %=ExitCode%
call :getPETarget "test3.txt"
echo test3.txt %errorlevel% %=ExitCode%
echo(
pause
goto :eof
:getPETarget FilePath
:: ~~~~~~~~~~~~~~~~~~~~~~
:: Errorlevel
:: 0 Success
:: 1 File Not Found
:: 2 Wrong Magic Number
:: 3 Out Of Scope
:: 4 No PE File
:: ~~~~~~~~~~~~~~~~~~~~~~
:: =ExitCode
:: CPU identifier
setlocal DisableDelayedExpansion
set "File=%~1"
set Cmp="%temp%\%random%.%random%.1KB"
set Dmp="%temp%\%random%.%random%.dmp"
REM write 1024 times 'A' into a temporary file
if exist "%File%" (
>%Cmp% (
for /l %%i in (1 1 32) do <nul set /p "=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
)
setlocal EnableDelayedExpansion
) else (endlocal &cmd /c exit 0 &exit /b 1)
REM generate a HEX dump of the executable file (first 1024 Bytes)
set "X=1"
>!Dmp! (
for /f "skip=1 tokens=1,2 delims=: " %%i in ('fc /b "!File!" !Cmp!^|findstr /vbi "FC:"') do (
set /a "Y=0x%%i"
for /l %%k in (!X! 1 !Y!) do echo 41
set /a "X=Y+2"
echo %%j
)
)
del !Cmp!
REM read certain values out of the HEX dump
set "err="
<!Dmp! (
set /p "A="
set /p "B="
REM magic number has to be "MZ"
if "!A!!B!" neq "4D5A" (set "err=2") else (
REM skip next 58 bytes
for /l %%i in (3 1 60) do set /p "="
REM bytes 61-64 contain the offset to the PE header in little endian order
set /p "C="
set /p "D="
set /p "E="
set /p "F="
REM check if the beginning of the PE header is part of the HEX dump
if 0x!F!!E!!D!!C! lss 1 (set "err=3") else (
if 0x!F!!E!!D!!C! gtr 1018 (set "err=3") else (
REM skip the offset to the PE header
for /l %%i in (65 1 0x!F!!E!!D!!C!) do set /p "="
REM next 4 bytes have to contain the signature of the PE header
set /p "G="
set /p "H="
set /p "I="
set /p "J="
REM next 2 bytes contain the CPU identifier in little endian order
set /p "K="
set /p "L="
)
)
)
)
del !Dmp!
if defined err (endlocal &endlocal &cmd /c exit 0 &exit /b %err%)
REM was the signature ("PE\0\0") of the PE header found
if "%G%%H%%I%%J%"=="50450000" (
REM calculate the decimal value of the CPU identifier
set /a "CPUID=0x%L%%K%"
) else (endlocal &endlocal &cmd /c exit 0 &exit /b 4)
endlocal &endlocal &cmd /c exit %CPUID% &exit /b 0
I used some example files.
"nothing" does not exist.
"test1.txt"
Code: Select all
test*test*test
"test2.txt"
Code: Select all
MZ0000000000000000000000000000000000000000000000000000000000!!!!
"test3.txt"
Code: Select all
MZ0000000000000000000000000000000000000000000000000000000000!
... a single line each without line break.
The output under my Win7 x86:
Code: Select all
file errorlevel CPU ID
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
explorer.exe 0 0000014C
chcp.com 0 0000014C
vbscript.dll 0 0000014C
nothing 1 00000000
test1.txt 2 00000000
test2.txt 3 00000000
test3.txt 4 00000000
Drücken Sie eine beliebige Taste . . .
Maybe somebody finds it useful
Regards
aGerman