Validating the PE Signature (My AV Flagged me) [Windows PE Internals]
Tags: cybersecurity, security
Published: 2021-04-23 13:47:19

# Previous Windows PE Internals Writeups
- [Creating a Windows Project in Visual Studio](https://dev.to/wireless90/creating-a-windows-project-in-visual-studio-windows-pe-internals-2p6e)
- [Getting a Handle to a Dynamically Linked Library ](https://dev.to/wireless90/getmodulehandlea-windows-pe-internals-1b0l)
- [Validating the MZ Signature](https://dev.to/wireless90/getting-the-windows-pe-internals-kka/edit)


# Previously

Previously, we learnt about how do we validate the `MZ` signature, which tells us that the file is very likely, a `Portable Executable (PE) file.` or a `MS DOS Executable`.

# Let's Begin

Now, lets proceed to navigate to another structure within the PE called the `NT_HEADERS` aka `PE HEADERS`.

The `NT_HEADERS` consist of 3 main subsections.
- NT Signature aka PE Signature
- File Header aka PE Header
- Optional Header

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fsqsxemd6x1yzjaj6c7s.png)
 

 
Today we will validate the `NT Signature`.

Continuing with our [previous article](https://dev.to/wireless90/getting-the-windows-pe-internals-kka), let's relook at the PE image above and the definition of the `IMAGE_DOS_HEADER`.

```cpp
typedef struct _IMAGE_DOS_HEADER
{
     WORD e_magic;
     WORD e_cblp;
     WORD e_cp;
     WORD e_crlc;
     WORD e_cparhdr;
     WORD e_minalloc;
     WORD e_maxalloc;
     WORD e_ss;
     WORD e_sp;
     WORD e_csum;
     WORD e_ip;
     WORD e_cs;
     WORD e_lfarlc;
     WORD e_ovno;
     WORD e_res[4];
     WORD e_oemid;
     WORD e_oeminfo;
     WORD e_res2[10];
     LONG e_lfanew;     //Use this to jump to PIMAGE_NT_HEADER
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
```

We can see that there is a property `e_lfanew`. It contains a `Relative Virtual Address (RVA)` whose offset leads us to the `PIMAGE_NT_HEADER`.

`e_lfanew` simply means the `long file address of the new executable header` , kinda saying the `IMAGE_DOS_HEADER` is old as its for `MS-DOS`.

An `RVA` is basically an offset(in bytes) from the `Base Address`. Meaning you would only compute the destination address by taking the `Base Address`, which is our start of PE Address, and add it to the `RVA` to get the destination address.

Let's now compute our `PIMAGE_NT_HEADER` by adding `PIMAGE_DOS_HEADER` to the `RVA` in `e_lfanew`.

The code below shows how to do that.

```cpp
PIMAGE_NT_HEADERS imageNtHeaders = (PIMAGE_NT_HEADERS)((unsigned char*)imageDosHeader + imageDosHeader->e_lfanew);
```
Let's break it down.

```cpp
(unsigned char*)imageDosHeader
```
As `imageDosHeader` is of a type `pointer to IMAGE_DOS_HEADER`, we cant do pointer arithmetic byte-wise. Meaning we want to shift the pointer byte by byte as the `RVA` is the offset in bytes.

Hence we casted it to a `(unsigned char*)` which allows the pointer to move byte by byte as a `char` is `1 byte`.

```cpp
(unsigned char*)imageDosHeader + imageDosHeader->e_lfanew
```
Next we moved the pointer by `imageDosHeader->e_lfanew` number of bytes. 

```cpp
PIMAGE_NT_HEADERS imageNtHeaders = (PIMAGE_NT_HEADERS)((unsigned char*)imageDosHeader + imageDosHeader->e_lfanew);
```
Then we re-casted it back to `PIMAGE_NT_HEADERS` which is basically a macro for `pointer to IMAGE_NT_HEADERS` aka `IMAGE_NT_HEADERS*`.


Now we can easily get our signature from `PIMAGE_NT_HEADERS` and compare it with the macro `IMAGE_NT_SIGNATURE`.

```cpp
if (imageNtHeaders->Signature == IMAGE_NT_SIGNATURE)
{
	//omitted
}
```
`IMAGE_NT_SIGNATURE` is a macro found in `winnt.h` which defines the PE signature to be `PE\0\0` which ends with 2 null bytes.

```cpp
//From winnt.h
#define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ
#define IMAGE_NT_SIGNATURE                  0x00004550  // PE00
```

Hence overall, our code would look like the following.

```cpp
#include <Windows.h>

int  WinMain(
	 HINSTANCE hInstance,
	 HINSTANCE hPrevInstance,
	 LPSTR     lpCmdLine,
	 int       nCmdShow
)
{
	HMODULE peBase = GetModuleHandleA("user32.dll");
	
	if (peBase == NULL)
	{
		MessageBoxA(0, "Can't load user32.dll", "Error", MB_OK | MB_ICONERROR);
		return 1;
	}

	PIMAGE_DOS_HEADER imageDosHeader = (PIMAGE_DOS_HEADER)peBase;

	if (imageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
	{
		MessageBoxA(0, "user32.dll has the wrong Image Dos Signature!", "Error", MB_OK | MB_ICONERROR);
		return 1;
	}

	PIMAGE_NT_HEADERS imageNtHeaders = (PIMAGE_NT_HEADERS)((unsigned char*)imageDosHeader + imageDosHeader->e_lfanew);

	if (imageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
	{
		MessageBoxA(0, "user32.dll has the wrong PE Signature!", "Error", MB_OK | MB_ICONERROR);
		return 1;
	}
	MessageBoxA(0, "user32.dll has the right PE Signature!", "Success", MB_OK | MB_ICONINFORMATION);

	return 0;
}
```

# Anti-Virus Bleeping...

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hb5g7zk89jcnsmjkqlu2.png)

I did not expect my antivirus to catch up very quickly that what I am trying to do might be suspicious. Many malwares have similar type of function calls to perform `DLL Injection`. We might discuss that in the future.

I have temporarily disabled it.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txwi5ax4mrk7xsqssu5o.png)


In this exercise, I learnt how to navigate from the `DOS HEADER` to the `PE HEADER` via the `e_lfanew` property. Following that, I successfully verfied the PE Header. Interestingly, we also saw my Antivirus going off and suspecting my code to be malicious.
 

# Next
[Dissecting the PE Header](https://dev.to/wireless90/dissecting-the-pe-header-windows-pe-internals-5113)