How to tell if a file is executable or not?

Just starting out? Need help? Post your questions and find answers here.
stevylake
User
User
Posts: 24
Joined: Fri Apr 05, 2019 6:50 pm

How to tell if a file is executable or not?

Post by stevylake »

Hello
I was thinking of how to tell if a file is a renamed .exe or other executable file type?
Instead of PossibleVirus.exe it is renamed PossibleVirus.dat.
Or would that not even be a problem as the renamed file could never be run? Unless another program renamed it and ran it maybe.
There must be some kind of header within a file to determine what type of file it is? Mustn't there?
Thanks.
User avatar
Mijikai
Addict
Addict
Posts: 1517
Joined: Sun Sep 11, 2016 2:17 pm

Re: How to tell if a file is executable or not?

Post by Mijikai »

Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: How to tell if a file is executable or not?

Post by Axolotl »

There are special file formats.
The most common used formats are under Window PE, under Linux ELF and Mach-O on macOS.

Furthermore there are Permissions (Linux) and Data Execution Prevention (Windows).

I recommend the general search on the internet for details.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: How to tell if a file is executable or not?

Post by Keya »

this code tests for valid Windows PE executables (32bit/64bit).

Returns 0 if invalid (not a valid Windows PE executable), or the size of the executable as reported by its PE header (which isn't necessarily the same as its filesize). If the reported size is smaller than the filesize you can use that to determine how much extra data it has appended to it.

To call it, read the file data (you don't need to read the entire file, just enough to cover the PE header, 4kb is sufficient), and pass the pointer to that data, as well as the LOF() filesize.

Code: Select all

#IMAGE_DOS_SIGNATURE = $5A4D ;"MZ"
#IMAGE_NT_SIGNATURE  = $4550 ;"PE"
#IMAGE_NT_OPTIONAL_HDR32_MAGIC = $10b ;32bit
#IMAGE_NT_OPTIONAL_HDR64_MAGIC = $20b ;64bit


Procedure IsValidPE(*DOShdr.IMAGE_DOS_HEADER, imgsize)
  Protected *PEhdr32.IMAGE_NT_HEADERS32, PEimgsize  
  If *DOShdr = 0 Or imgsize <= SizeOf(IMAGE_DOS_HEADER)
    ProcedureReturn 0
  EndIf  
  PEimgsize = imgsize - SizeOf(IMAGE_DOS_HEADER)
  If *DOShdr\e_magic <> #IMAGE_DOS_SIGNATURE
    ProcedureReturn 0
  EndIf

  ;At this stage, you know it's seemingly a valid MZ DOS executable. Now check if it's a valid PE...

  If *DOShdr\e_lfanew = 0 Or *DOShdr\e_lfanew > PEimgsize
    ProcedureReturn 0
  EndIf
  *PEhdr32 = *DOShdr + *DOShdr\e_lfanew
  If *PEhdr32\Signature <> #IMAGE_NT_SIGNATURE
    ProcedureReturn 0
  EndIf
  If *PEhdr32\FileHeader\SizeOfOptionalHeader = 0 Or *PEhdr32\FileHeader\SizeOfOptionalHeader > PEimgsize
    ProcedureReturn 0
  EndIf  
  If *PEhdr32\FileHeader\NumberOfSections = 0 Or *PEhdr32\FileHeader\NumberOfSections > 255
    ProcedureReturn 0
  EndIf
  If Not (*PEhdr32\OptionalHeader\Magic = #IMAGE_NT_OPTIONAL_HDR64_MAGIC Or *PEhdr32\OptionalHeader\Magic = #IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    ProcedureReturn 0
  EndIf
  ProcedureReturn *PEhdr32\OptionalHeader\SizeOfImage
EndProcedure
stevylake
User
User
Posts: 24
Joined: Fri Apr 05, 2019 6:50 pm

Re: How to tell if a file is executable or not?

Post by stevylake »

Thanks for the code I just got stuck at this bit.

To call it, read the file data (you don't need to read the entire file, just enough to cover the PE header, 4kb is sufficient), and pass the pointer to that data, as well as the LOF() filesize.

:-)
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: How to tell if a file is executable or not?

Post by Keya »

stevylake wrote:Thanks for the code I just got stuck at this bit.
To call it, read the file data (you don't need to read the entire file, just enough to cover the PE header, 4kb is sufficient), and pass the pointer to that data, as well as the LOF() filesize.
:-)

Code: Select all

szFile.s = "c:\windows\system32\calc.exe"
hFile = ReadFile(#PB_Any, szFile)
fSize = Lof(hFile)
If fSize > 4096: fSize = 4096: EndIf  ;we don't need to read any more than 4kb as we're only looking at the file header
*fData = AllocateMemory(fSize)
ReadData(hFile, *fData, fSize)
IsPE = IsValidPE(*fData, Lof(hFile))
FreeMemory(*fData)
CloseFile(hFile)
If IsPE = 0
 Debug "Not a valid PE executable"
Else
 Debug "Valid PE executable, the reported image size is " + Str(IsPE)
EndIf
User avatar
TI-994A
Addict
Addict
Posts: 2701
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to tell if a file is executable or not?

Post by TI-994A »

stevylake wrote:... some kind of header within a file to determine what type of file it is?
There's a Windows API function for that, actually:

source: Microsoft Win32 API Documentation

Code: Select all

Procedure.s checkBinaryType(fileName.s)
  Protected SCS_64BIT_BINARY = 6
  Protected fileExt$ = UCase(GetExtensionPart(fileName))
  Protected binaryType$ = Trim(fileExt$ + " file type (unconfirmed)")
 
  If FileSize(fileName) > -1 And
     GetBinaryType_(fileName, @binaryType)   
    Select binaryType     
      Case #SCS_DOS_BINARY
        binaryType$ = "MS-DOS–based application"
      Case #SCS_WOW_BINARY
        binaryType$ = "16-bit Windows-based application"
      Case #SCS_32BIT_BINARY
        binaryType$ = "32-bit Windows-based application"
      Case SCS_64BIT_BINARY
        binaryType$ = "64-bit Windows-based application" 
      Case #SCS_OS216_BINARY
        binaryType$ = "16-bit OS/2-based application"
      Case #SCS_POSIX_BINARY
        binaryType$ = "POSIX–based application"
      Case #SCS_PIF_BINARY
        binaryType$ = "PIF for MS-DOS–based application"
      Default
        binaryType$ = "Unknown binary type"
    EndSelect   
  EndIf
 
  ProcedureReturn binaryType$ 
EndProcedure

Repeat 
  file.s = OpenFileRequester("Select file to check", "",
                             "All files (*.*) | *.*", 0)
  Debug checkBinaryType(file) 
  If MessageRequester("Binary File Type", "Check another file?",
                      #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
    Break
  EndIf
ForEver
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
stevylake
User
User
Posts: 24
Joined: Fri Apr 05, 2019 6:50 pm

Re: How to tell if a file is executable or not?

Post by stevylake »

TI-994A wrote:
stevylake wrote:... some kind of header within a file to determine what type of file it is?
There's a Windows API function for that, actually:

source: Microsoft Win32 API Documentation

Code: Select all

Procedure.s checkBinaryType(fileName.s)
  Protected SCS_64BIT_BINARY = 6
  Protected fileExt$ = UCase(GetExtensionPart(fileName))
  Protected binaryType$ = Trim(fileExt$ + " file type (unconfirmed)")
 
  If FileSize(fileName) > -1 And
     GetBinaryType_(fileName, @binaryType)   
    Select binaryType     
      Case #SCS_DOS_BINARY
        binaryType$ = "MS-DOS–based application"
      Case #SCS_WOW_BINARY
        binaryType$ = "16-bit Windows-based application"
      Case #SCS_32BIT_BINARY
        binaryType$ = "32-bit Windows-based application"
      Case SCS_64BIT_BINARY
        binaryType$ = "64-bit Windows-based application" 
      Case #SCS_OS216_BINARY
        binaryType$ = "16-bit OS/2-based application"
      Case #SCS_POSIX_BINARY
        binaryType$ = "POSIX–based application"
      Case #SCS_PIF_BINARY
        binaryType$ = "PIF for MS-DOS–based application"
      Default
        binaryType$ = "Unknown binary type"
    EndSelect   
  EndIf
 
  ProcedureReturn binaryType$ 
EndProcedure

Repeat 
  file.s = OpenFileRequester("Select file to check", "",
                             "All files (*.*) | *.*", 0)
  Debug checkBinaryType(file) 
  If MessageRequester("Binary File Type", "Check another file?",
                      #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
    Break
  EndIf
ForEver


Seems good. Just wondering where you find a list of all those constants? Are they Microsoft constants or Pure Basic or something else?
User avatar
TI-994A
Addict
Addict
Posts: 2701
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to tell if a file is executable or not?

Post by TI-994A »

stevylake wrote:...where you find a list of all those constants? Are they Microsoft constants or Pure Basic...
They're part of the Microsoft Win32 API, integrated as native constants in Windows versions of PureBasic.

They can be referenced here:
> Microsoft Win32 API Documentation
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
stevylake
User
User
Posts: 24
Joined: Fri Apr 05, 2019 6:50 pm

Re: How to tell if a file is executable or not?

Post by stevylake »

TI-994A wrote:
stevylake wrote:...where you find a list of all those constants? Are they Microsoft constants or Pure Basic...
They're part of the Microsoft Win32 API, integrated as native constants in Windows versions of PureBasic.

They can be referenced here:
> Microsoft Win32 API Documentation
is it that SCS_64BIT_BINARY hasn't been integrated so the code had to use a variable instead then?

Is there somewhere to find a list of all the Microsoft constants used by PB?
User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: How to tell if a file is executable or not?

Post by NicTheQuick »

On Linux and Mac every file with execution rights could possibly be an executable. Either it's a real binary or it's a script with a Shebang in the first line or an appropriate file extensions. But in general file extensions on Linux/Mac are just a suggestion.
You can call the `file` tool with a filename you want to check for its type. For example:

Code: Select all

nicolas@tp-w530:~/git/FractalSoundExplorer$ file FractalSoundExplorer 
FractalSoundExplorer: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=cabc8f367f97790c528f174cf07001e7ac378bac, for GNU/Linux 3.2.0, not stripped
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
TI-994A
Addict
Addict
Posts: 2701
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to tell if a file is executable or not?

Post by TI-994A »

stevylake wrote:is it that SCS_64BIT_BINARY hasn't been integrated so the code had to use a variable instead then?

Is there somewhere to find a list of all the Microsoft constants used by PB?
Yes, and yes. These might be good places to start:

> PureBasic Windows Resident Data (Fantaisie Software Git)

> Windows API Index (Microsoft Documentation)
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: How to tell if a file is executable or not?

Post by Marc56us »

Hi stevylake,

Understanding how it works is very useful: Search wikipedia for Magic number (programming)
https://en.wikipedia.org/wiki/Magic_num ... ogramming)

and use PB file functions
https://www.purebasic.com/documentation/file/index.html

:wink:
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: How to tell if a file is executable or not?

Post by Axolotl »

Your question suggests that you are concerned with preventing "attacks" by malware.

Let's see where this thread takes us.
In general, however, other types of files can cause damage in addition to directly executable files.

You have to consider that scripts are also executed under Windows. For example the good old MS-DOS scripts *.BAT (*.cmd) or Powershell or or. (under Linux there is BASH etc.)

Otherwise there is under Windows still the environment variable PathExt, so that you dont have to add the extension on the console. (Looks like this PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC)

Additionally there is the option that the files that are not executed are started because of a file association.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
stevylake
User
User
Posts: 24
Joined: Fri Apr 05, 2019 6:50 pm

Re: How to tell if a file is executable or not?

Post by stevylake »

Axolotl wrote:Your question suggests that you are concerned with preventing "attacks" by malware.

Let's see where this thread takes us.
In general, however, other types of files can cause damage in addition to directly executable files.

You have to consider that scripts are also executed under Windows. For example the good old MS-DOS scripts *.BAT (*.cmd) or Powershell or or. (under Linux there is BASH etc.)

Otherwise there is under Windows still the environment variable PathExt, so that you dont have to add the extension on the console. (Looks like this PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC)

Additionally there is the option that the files that are not executed are started because of a file association.
Yes I was kindof thinking that. It's just that I have set up a way where a user can send me a message with a file attachment via one of my servers. All works good. What I was thinking is how much testing would I have to do to ensure that any file uploaded couldn't be run and do horrible things to my server. That was what I was thinking and that got me to how does one know an executable file when it's been disguised. :-)
Post Reply