Page 1 of 2
How to tell if a file is executable or not?
Posted: Sat Mar 06, 2021 11:18 pm
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.
Re: How to tell if a file is executable or not?
Posted: Sat Mar 06, 2021 11:57 pm
by Mijikai
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 12:07 am
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.
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 1:47 am
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
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 3:29 am
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.

Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 3:40 am
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
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 7:37 am
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 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
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 1:07 pm
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 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?
Posted: Sun Mar 07, 2021 1:18 pm
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
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 1:23 pm
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?
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 1:29 pm
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
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 2:35 pm
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)
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 3:14 pm
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

Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 4:34 pm
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.
Re: How to tell if a file is executable or not?
Posted: Sun Mar 07, 2021 9:17 pm
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.
