Jump to content

Recommended Posts

Posted (edited)

V2:

#include <File.au3>
#include <WinAPIFiles.au3>
#include <WinAPI.au3>

; #FUNCTION# ====================================================================================================================
; Name............: _GetFileArch
; Description....: Determine the architecture (x86, x64, ARM, etc.) of the executable file or library (EXE, DLL, SYS, OCX...).
; Syntax.........: _GetFileArch($sFilePath [, $bAsText = True])
; Parameters.....: $sFilePath - File path to check
;                  $bAsText - True => Returns the description string (default)
;                             False => Returns the architecture code (e.g., 32, 64, 65,...)
; Return values..: Success: + When $bAsText = True → Returns the description string (e.g., "SCS_64BIT_BINARY", "ARM64", ...)
;                           + When $bAsText = False → Returns the code (eg: 64, 65, ...)
;                  Failed → SetError(code, ext, message)
; Author.........: Dao Van Trong - TRONG.PRO
; =========================================================================================================================

Func _GetFileArch($sFilePath, $bAsText = True)
    If Not FileExists($sFilePath) Then Return SetError(-1, 0, '')
    Local $tType = DllStructCreate("dword lpBinaryType")
    Local $aRetAPI = DllCall("kernel32.dll", "bool", "GetBinaryTypeW", "wstr", $sFilePath, "ptr", DllStructGetPtr($tType))
    If @error = 0 And $aRetAPI[0] Then
        Local $BinaryType = DllStructGetData($tType, "lpBinaryType")
        Switch $BinaryType
            Case 0
                Return SetError(0, 0, ($bAsText ? "x86" : 32)) ; (I386) SCS_32BIT_BINARY
            Case 6
                Return SetError(0, 6, ($bAsText ? "x64" : 64)) ; (AMD64)SCS_64BIT_BINARY
            Case 1
                Return SetError(0, 1, ($bAsText ? "DOS" : 1)) ;SCS_DOS_BINARY
            Case 2
                Return SetError(0, 2, ($bAsText ? "WOW" : 2)) ;SCS_WOW_BINARY
            Case 3
                Return SetError(0, 3, ($bAsText ? "PIF" : 3)) ;SCS_PIF_BINARY
            Case 4
                Return SetError(0, 4, ($bAsText ? "POSIX" : 4)) ;SCS_POSIX_BINARY
            Case 5
                Return SetError(0, 5, ($bAsText ? "OS216" : 5)) ;SCS_OS216_BINARY
                ;Case Else
                ;    Return SetError(1, $BinaryType, "Unknown (API Code: " & $BinaryType & ")")
        EndSwitch
    EndIf
    Local $hFile = _WinAPI_CreateFile($sFilePath, 2, 7)
    If $hFile = 0 Then Return SetError(2, 0, "Error: Cannot open file")
    Local $tDosHeader = DllStructCreate("char Magic[2];byte[58];dword Lfanew")
    Local $aRead = _WinAPI_ReadFile($hFile, DllStructGetPtr($tDosHeader), 64, 0)
    If Not $aRead Or DllStructGetData($tDosHeader, "Lfanew") < 64 Then
        _WinAPI_CloseHandle($hFile)
        Return SetError(3, 0, "Error: Cannot read DOS header")
    EndIf
    If DllStructGetData($tDosHeader, "Magic") <> "MZ" Then
        _WinAPI_CloseHandle($hFile)
        Return SetError(4, 0, "Error: Not a valid PE file")
    EndIf
    _WinAPI_SetFilePointer($hFile, DllStructGetData($tDosHeader, "Lfanew"))
    Local $tNtHeaders = DllStructCreate("dword Signature;word Machine;word NumberOfSections;byte[18]")
    $aRead = _WinAPI_ReadFile($hFile, DllStructGetPtr($tNtHeaders), 24, 0)
    If Not $aRead Then
        _WinAPI_CloseHandle($hFile)
        Return SetError(5, 0, "Error: Cannot read NT headers")
    EndIf
    If DllStructGetData($tNtHeaders, "Signature") <> 0x4550 Then
        _WinAPI_CloseHandle($hFile)
        Return SetError(6, 0, "Error: Invalid PE signature")
    EndIf
    Local $Machine = DllStructGetData($tNtHeaders, "Machine")
    _WinAPI_CloseHandle($hFile)
    Switch $Machine
        Case 0x014C
            Return SetError(0, 32, ($bAsText ? "x86" : 32)) ; (I386) SCS_32BIT_BINARY
        Case 0x8664
            Return SetError(0, 64, ($bAsText ? "x64" : 64)) ; (AMD64) SCS_64BIT_BINARY
        Case 0xAA64
            Return SetError(0, 65, ($bAsText ? "ARM64" : 65))
        Case 0x01C0
            Return SetError(0, 66, ($bAsText ? "ARM" : 66))
        Case 0x01C2
            Return SetError(0, 67, ($bAsText ? "THUMB" : 67))
        Case 0x01C4
            Return SetError(0, 68, ($bAsText ? "ARMNT" : 68))
        Case 0x0200
            Return SetError(0, 69, ($bAsText ? "IA64" : 69))
        Case 0x01C5
            Return SetError(0, 70, ($bAsText ? "ARMV7" : 70))
        Case 0x0162
            Return SetError(0, 71, ($bAsText ? "R3000" : 71))
        Case 0x0166
            Return SetError(0, 72, ($bAsText ? "R4000" : 72))
        Case 0x01F0
            Return SetError(0, 73, ($bAsText ? "POWERPC" : 73))
        Case 0x01F1
            Return SetError(0, 74, ($bAsText ? "POWERPCFP" : 74))
        Case 0x0EBC
            Return SetError(0, 75, ($bAsText ? "EBC" : 75))
        Case 0xC0EE
            Return SetError(0, 76, ($bAsText ? "CEE" : 76))
        Case Else
            Return SetError(7, $Machine, "Unknown (Machine: 0x" & Hex($Machine, 4) & ")")
    EndSwitch
EndFunc   ;==>_GetFileArch

V1:

Replacement function for _WinAPI_GetBinaryType() and _WinAPI_GetPEType() !

Using WinAPI depends on the version of Windows, so the results may not be accurate. So this UDF was born:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

; Eg:
ConsoleWrite("-: " & _GetPeType("C:\Windows\System32\winver.exe") & " - Extended: " & @extended & " > Is_x64_Exe: " & _Is_x64_Exe("C:\Windows\System32\winver.exe") & @CRLF)
ConsoleWrite("-: " & _GetPeType("C:\Windows\SysWOW64\winver.exe") & " - Extended: " & @extended & " > Is_x32_Exe: " & _Is_x32_Exe("C:\Windows\SysWOW64\winver.exe") & @CRLF)
ConsoleWrite("-: " & _GetPeType("C:\Program Files\Microsoft Visual Studio\2022\VC\Tools\MSVC\14.40.33807\bin\arm64\pgosweep.exe") & " - Extended: " & @extended & " > Is_x64Arm_Exe: " & _Is_x64Arm_Exe("C:\Program Files\Microsoft Visual Studio\2022\VC\Tools\MSVC\14.40.33807\bin\arm64\pgosweep.exe") & @CRLF)

Func _Is_x64_Exe($sPath)
    Local $peTYPE = _GetPeType($sPath)
    If ((@extended = 1) Or ($peTYPE = 'AMD64')) Then Return 1
    Return 0
EndFunc   ;==>_Is_x64_Exe

Func _Is_x32_Exe($sPath)
    Local $peTYPE = _GetPeType($sPath)
    If ((@extended = 2) Or ($peTYPE = 'I386')) Then Return 1
    Return 0
EndFunc   ;==>_Is_x32_Exe

Func _Is_x64Arm_Exe($sPath)
    Local $peTYPE = _GetPeType($sPath)
    If ((@extended = 3) Or ($peTYPE = 'ARM64')) Then Return 1
    Return 0
EndFunc   ;==>_Is_x64Arm_Exe

Func _GetPeType($peFilePath) ; Retrieves a type of the machine for the specified portable executable (PE)
    ; The return value is the architecture name
    ; @extendedis a custom number for architecture
    Local $hFile = FileOpen($peFilePath, 16)
    If ($hFile = -1) Then Return SetError(1, 0, '') ; File does not exist or No permission to open file!
    If BinaryToString(FileRead($hFile, 2)) <> "MZ" Then
        FileClose($hFile)
        Return SetError(2, 0, 0) ; Not a PE file.
    EndIf
    FileSetPos($hFile, 60, 0) ; Move to Windows PE Signature Offset location
    Local $peTYPE = FileRead($hFile, 4)
    FileSetPos($hFile, Number($peTYPE) + 4, 0) ; Move to Windows PE Header Offset
    $peTYPE = FileRead($hFile, 2) ; Read PE data
    FileClose($hFile)
;~  Local $sFileName = StringRegExpReplace($peFilePath, "^.*\\", "") ; Get File name with ext
    Switch $peTYPE
        Case '0x6486', '0x8664'
            Return SetError(0, 1, 'AMD64') ; AMD64 (K8) x64 64-bit
        Case '0x4C01', '0x014C'
            Return SetError(0, 2, 'I386') ; Intel 386 x86 32-bit
        Case '0x64AA', '0xAA64'
            Return SetError(0, 3, 'ARM64') ; ARM64 Little-Endian
        Case '0x0002', '0x0200'
            Return SetError(0, 4, 'IA64') ; Intel 64
        Case '0xC201', '0x01C2'
            Return SetError(0, 5, 'THUMB') ; ARM Thumb/Thumb-2 Little-Endian
        Case '0xC401', '0x01C4'
            Return SetError(0, 6, 'ARMNT') ; ARM Thumb-2 Little-Endian
        Case '0x6201', '0x0162'
            Return SetError(0, 7, 'R3000') ; MIPS little-endian, 0x160 big-endian
        Case '0x6601', '0x0166'
            Return SetError(0, 8, 'R4000') ; MIPS little-endian
        Case '0x6801', '0x0168'
            Return SetError(0, 9, 'R10000') ; MIPS little-endian
        Case '0x6901', '0x0169'
            Return SetError(0, 10, 'WCEMIPSV2') ; MIPS little-endian WCE v2
        Case '0x8401', '0x0184'
            Return SetError(0, 11, 'ALPHA') ; Alpha_AXP
        Case '0xA201', '0x01A2'
            Return SetError(0, 12, 'SH3') ; SH3 little-endian
        Case '0xA301', '0x01A3'
            Return SetError(0, 13, 'SH3DSP') ; SH3DSP
        Case '0xA401', '0x01A4'
            Return SetError(0, 14, 'SH3E') ; SH3E little-endian
        Case '0xA601', '0x01A6'
            Return SetError(0, 15, 'SH4') ; SH4 little-endian
        Case '0xA801', '0x01A8'
            Return SetError(0, 16, 'SH5') ; SH5
        Case '0xC001', '0x01C0'
            Return SetError(0, 17, 'ARM') ; ARM Little-Endian
        Case '0xD301', '0x01D3'
            Return SetError(0, 18, 'AM33') ; TAM33BD
        Case '0xF001', '0x01F0'
            Return SetError(0, 19, 'POWERPC') ; IBM PowerPC Little-Endian
        Case '0xF101', '0x01F1'
            Return SetError(0, 20, 'POWERPCFP') ; POWERPCFP
        Case '0x6602', '0x0266'
            Return SetError(0, 21, 'MIPS16') ; MIPS
        Case '0x8402', '0x0284'
            Return SetError(0, 22, 'ALPHA64') ; ALPHA64
        Case '0x6603', '0x0366'
            Return SetError(0, 23, 'MIPSFPU') ; MIPS
        Case '0x6604', '0x0466'
            Return SetError(0, 24, 'MIPSFPU16') ; MIPS
        Case '0x8402', '0x0284'
            Return SetError(0, 25, 'AXP64') ; AXP64
        Case '0x2005', '0x0520'
            Return SetError(0, 26, 'TRICORE') ; Infineon
        Case '0xEF0C', '0x0CEF'
            Return SetError(0, 27, 'CEF') ; CEF
        Case '0xBC0E', '0x0EBC'
            Return SetError(0, 28, 'EBC') ; EFI Byte Code
        Case '0x4190', '0x9041'
            Return SetError(0, 29, 'M32R') ; M32R little-endian
        Case '0xEEC0', '0xC0EE'
            Return SetError(0, 30, 'CEE') ; CEE
        Case Else
            Return SetError(3, 0, '') ; Unknown
    EndSwitch
    Return SetError(3, -1, '')
EndFunc   ;==>_GetPeType
; Dao Van Trong - TRONG.PRO

 

Edited by Trong
V2

Enjoy my work? Buy me a 🍻 or tip via ❤️ PayPal

Posted

I tested the code on Windows XP and other Windows versions! Of course it doesn't return any results so I just wrote this function!

ARM "This constant is available starting with Windows 7 and Windows Server 2008 R2."

 

ARM64 Little-Endian "This constant is available starting with Windows 8.1 and Windows Server 2012 R2."

https://learn.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants

Enjoy my work? Buy me a 🍻 or tip via ❤️ PayPal

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...