14

If you've gotten the file extensions messed up, how can you tell an executable apart from a DLL?

They both seem to have entry points and everything...

CharlesB
  • 86,532
  • 28
  • 194
  • 218
user541686
  • 205,094
  • 128
  • 528
  • 886
  • @OmerPT, @CharlesB: I mean more like through their features (e.g. their PE headers, their disassembly, etc.) – user541686 Jun 10 '11 at 16:17
  • Rename it with extension `exe` and try executing it in a Windows environment. If it does something, it's an exe. :P I'm actually curious about this too... –  Jun 10 '11 at 16:18
  • 1
    You can examine the PE header. See kichik's answer here: http://stackoverflow.com/questions/1210873/difference-between-dll-and-exe – vcsjones Jun 10 '11 at 16:18
  • @bdares: I should've seen that coming :P – user541686 Jun 10 '11 at 16:18
  • Is the file description and metadata messed up too? – Anirudh Ramanathan Jun 10 '11 at 16:19
  • @vcsjones: Thanks, but that doesn't actually say how to distinguish them. Also, I'm not sure what they mean by `There is only single main entry (for EXEs)` -- there's only a single main entry for DLLs too (`DllEntry`)... – user541686 Jun 10 '11 at 16:19
  • 2
    @anirudh4444: In case you're looking at the resources/version info, yeah -- that's cheating and it doesn't always work. :P – user541686 Jun 10 '11 at 16:20
  • 1
    @Mehrdad The accepted answer doesn't say much, but kichik's answer is right on the money: "one can look in the Characteristics member of IMAGE_FILE_HEADER inside IMAGE_NT_HEADERS. For a DLL, it has the IMAGE_FILE_DLL (0x2000) flag turned on. For a EXE it's the IMAGE_FILE_EXECUTABLE_IMAGE (0x2) flag" - I'll put some code together that does this. – vcsjones Jun 10 '11 at 16:21

5 Answers5

7

if anyone interested here is the code in C#, tested for 32 bit PE files.

 public static class PECheck
    {

        public static bool IsDll(Stream stream)
        {

            using (BinaryReader reader = new BinaryReader(stream))
            {

                byte[] header = reader.ReadBytes(2); //Read MZ
                if (header[0] != (byte)'M' && header[1] != (byte)'Z')
                    throw new Exception("Invalid PE file");

                stream.Seek(64 - 4, SeekOrigin.Begin);//read elf_new this is the offset where the IMAGE_NT_HEADER begins
                int offset = reader.ReadInt32();
                stream.Seek(offset, SeekOrigin.Begin);
                header = reader.ReadBytes(2);
                if (header[0] != (byte)'P' && header[1] != (byte)'E')
                    throw new Exception("Invalid PE file");

                stream.Seek(20, SeekOrigin.Current); //point to last word of IMAGE_FILE_HEADER
                short readInt16 = reader.ReadInt16();
                return (readInt16 & 0x2000) == 0x2000;

            }
        }
    }
crypted
  • 10,118
  • 3
  • 39
  • 52
6

This info is located in the PE header. To view it, you can open it with a PE explorer such as the NTCore CFF Explorer and open the Characterics field of the file header, where you can find whether it is a DLL or executable.

enter image description here

CharlesB
  • 86,532
  • 28
  • 194
  • 218
5

Look at this article for a good explanation of a portable executable on windows.

And then look at the section about the PE header. Also the code there-in shows in C the way to open and examine a PE file using Win32. This information you are looking for is stored in the IMAGE_FILE_HEADER. Specifically in the Characteristics field which would include the flag IMAGE_FILE_DLL 0x2000 if it is a dll.

That should give you enough information to create a small utility that makes the determination of a bunch of files if that is what you are looking for.

The most relevant bits of code for reference purposes, copied from the article above and edited to remove extraneous detail/error handling.

void DumpFile(LPWSTR filename)
{
    HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);

    LPVOID lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);    

    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpFileBase;

    PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + (DWORD)pDosHeader->e_lfanew);

    if ((pNTHeader->FileHeader.Characteristics & IMAGE_FILE_DLL))
         printf("dll"); 
    if ((pNTHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
         printf("exe"); 
    else 
         printf("????");

    UnmapViewOfFile(lpFileBase);
    CloseHandle(hFileMapping);
    CloseHandle(hFile);
}
dkackman
  • 15,179
  • 13
  • 69
  • 123
  • Thinking about it a bit more I realize that the code above isn't going to work (it's been a long time). It won't correctly get at the file header. When I get a moment I'll try and correct it – dkackman Jun 10 '11 at 18:08
2
dumpbin *.* | grep "File Type"

Works for me. I don't exactly remember what to use if you don't have grep installed, but I suggest you do.

Vladimir Sinenko
  • 4,629
  • 1
  • 27
  • 39
0

Grab OllyDbg and open the EXE/DLL in it. Bring up the memory map by clicking the big M button at the top. Scroll down till you find the PE header of the module which corresponds to your program. Double click to open it in memory dump. Scroll down to where you see PE signature (probably 0xF8 from image base) and if it's a DLL then Characteristics will have the DLL flag on it. Characteristics should be a few entires down from PE signature.

Mike Kwan
  • 24,123
  • 12
  • 63
  • 96