tetratelabs / func-e

func-e (pronounced funky) makes running Envoy® easy
https://func-e.io
Apache License 2.0
355 stars 42 forks source link

Add PE file checking for Windows moreos.isExecutable #357

Open dio opened 3 years ago

dio commented 3 years ago

Currently, on Windows, we only check the binary suffix to infer whether a file is executable or not (strings.HasSuffix(f.Name(), ".exe")). We can have a more sophisticated check for this if it is desired. However, we need to pull in github.com/Velocidex/go-pe or write a small package to accommodate our needs.

The steps that can be done are as follows:

  1. Check for IMAGE_DOS_HEADER magic byte, it should be MZ, i.e 0x5a4d. https://dev.to/wireless90/getting-the-windows-pe-internals-kka
  2. Check for NT header signature, expected value: 0x4550. This makes sure we have a valid PE file.https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail
  3. Check if the file is not a .dll file: mask the NT Header File header characteristic with 0x2000, it should 0 https://docs.microsoft.com/en-us/windows/win32/debug/pe-format.
  4. Per architecture check: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32, https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64. Check for the magic header.
codefromthecrypt commented 3 years ago

I dont think we need to do this optimization like this until there's a lot of motivation as we already try hard to keep deps low.

let's optimize for KISS (keep it simple and stupid)

thanks for the idea though.

codefromthecrypt commented 3 years ago

ps I am glad you mentioned how to do this as if I ever need we can look at this issue again (here or any project!)

dio commented 3 years ago

Seems like we can rely on something similar (the approach, by scanning the bytes) https://github.com/ArthurHlt/go-isexecutable/blob/v1.0.0/isexecutable.go, whilst it is very raw and naive, it has no external deps.

codefromthecrypt commented 3 years ago

good find and go for it, but please don't copy/paste that code for citation and otherwise reasons.

As our only use case at the moment is a binary executable, I think the minimum logic can be used for the windows code (scanning header for magic bytes) and leave the other operating systems as-is (based on chmod info).

make sure you make a nice comment about the magic bytes in the windows impl!