How to tell if a file is executable or not?
How to tell if a file is executable or not?
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.
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.
Re: How to tell if a file is executable or not?
U can check the PE Headers:
https://en.wikipedia.org/wiki/Portable_Executable
https://en.wikipedia.org/wiki/Portable_Executable
Re: How to tell if a file is executable or not?
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.
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).
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).
Re: How to tell if a file is executable or not?
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.
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
Re: How to tell if a file is executable or not?
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.

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.

Re: How to tell if a file is executable or not?
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
Re: How to tell if a file is executable or not?
There's a Windows API function for that, actually:stevylake wrote:... some kind of header within a file to determine what type of file it is?
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 

Re: How to tell if a file is executable or not?
TI-994A wrote:There's a Windows API function for that, actually:stevylake wrote:... some kind of header within a file to determine what type of file it is?
source: Microsoft Win32 API DocumentationCode: 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?
Re: How to tell if a file is executable or not?
They're part of the Microsoft Win32 API, integrated as native constants in Windows versions of PureBasic.stevylake wrote:...where you find a list of all those constants? Are they Microsoft constants or Pure Basic...
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 

Re: How to tell if a file is executable or not?
is it that SCS_64BIT_BINARY hasn't been integrated so the code had to use a variable instead then?TI-994A wrote:They're part of the Microsoft Win32 API, integrated as native constants in Windows versions of PureBasic.stevylake wrote:...where you find a list of all those constants? Are they Microsoft constants or Pure Basic...
They can be referenced here:
> Microsoft Win32 API Documentation
Is there somewhere to find a list of all the Microsoft constants used by PB?
- NicTheQuick
- 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?
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:
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.
Re: How to tell if a file is executable or not?
Yes, and yes. These might be good places to start: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?
> 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 

Re: How to tell if a file is executable or not?
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

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

Re: How to tell if a file is executable or not?
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.
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).
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).
Re: How to tell if a file is executable or not?
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.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.
