Detect MZ executable files

Peter Volz 1,295 Reputation points
2024-03-13T08:28:51.0033333+00:00

Hello,

I found a code online which works to detect many MZ executable files, but not all, anyone knows where can I extend it to cover detection of all executable files? ie Win16 executable files etc...

  • I'm on the .Net Framework 4.0
Try
    Dim MyBinaryReader As New BinaryReader(InputStream)
    If MyBinaryReader.ReadUInt16() = 23117 Then 'MZ Signature
        InputStream.Seek(&H3A, SeekOrigin.Current) 'Seek e_lfanew
        InputStream.Seek(MyBinaryReader.ReadUInt32(), SeekOrigin.Begin) 'Seek NT header start
        If MyBinaryReader.ReadUInt32() = 17744 Then 'PE\0\0 Signature
            InputStream.Seek(20, SeekOrigin.Current) 'Seek past the file header
            MyArchitecture = MyBinaryReader.ReadUInt16() 'Optional Header Magic Number
        End If
    End If
Catch Exception As Exception
    'I just take 0 as a sign of failure
    If MyArchitecture = 0 Then
        Return False
    Else
        Return True 'NE PE
    End If
End Try
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,197 questions
VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,564 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jiachen Li-MSFT 26,271 Reputation points Microsoft Vendor
    2024-03-13T09:32:00.5+00:00

    Hi @Peter Volz ,For Win16 executable files, known as New Executable, they also use MZ as the file header, so MyBinaryReader.ReadUInt16() = 23117 should also works for NE file.

    New (NE), linear (LX), and portable (PE) executables retain the DOS MZ format file header for [backward compatibility](https://en.wikipedia.org/wiki/Backward_compatibility"Backward compatibility") with DOS.

    Try
        Dim MyBinaryReader As New BinaryReader(InputStream)
        Dim mzSignature As UInt16 = MyBinaryReader.ReadUInt16()
        If mzSignature = &H5A4D Then ' Check for MZ signature
            MyArchitecture = 16 ' This is an MZ (DOS) file
        ElseIf mzSignature = 23117 Then ' Check for NE signature
            MyArchitecture = 16 ' This is an NE (16-bit New Executable) file
        Else
            InputStream.Seek(0, SeekOrigin.Begin) ' Reset stream position
            Dim peSignature As UInt32 = MyBinaryReader.ReadUInt32()
            If peSignature = 17744 Then ' Check for PE signature
                MyArchitecture = 32 ' This is a PE (Portable Executable) file
            End If
        End If
    Catch Exception As Exception
    
    End Try
    
    

    Best Regards.

    Jiachen Li


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. RLWA32 40,021 Reputation points
    2024-03-13T11:24:57.27+00:00

    See the Windows API SHGetFileInfoW function. When used with the SHGFI_EXETYPE (0x000002000) flag it returns the type of an executable. From the docs -

    shgfi

    0 comments No comments

  2. Peter Volz 1,295 Reputation points
    2024-03-13T14:41:04.8866667+00:00

    Hello,

    Please help me find how to convert and get these numbers?

    23117 is for MZ

    What to use for ZM?

    17744 is for PE

    What to use for NE and LE?

    How this is converted?

    I think my best bet is just to check if the file starts with MZ or ZM and PE/NE/LE is found:

    Dim MyBinaryReader As New BinaryReader(InputStream)
    Select Case MyBinaryReader.ReadUInt16()
      Case 23117, What's ZM number?
        InputStream.Seek(&H3A, SeekOrigin.Current) 'Seek e_lfanew
        InputStream.Seek(MyBinaryReader.ReadUInt32(), SeekOrigin.Begin) 'Seek NT header start
        Select Case MyBinaryReader.ReadUInt32()
            Case 17744, What's NE and LE numbers?
                Return True
        End Select
    End Select