Code Monkey home page Code Monkey logo

penet's Introduction

license NuGet NuGet Build Test BuiltWithDot.Net shield

PeNet Logo PeNet is a parser for Windows Portable Executable headers. It completely written in C# and does not rely on any native Windows APIs. Furthermore it supports the creation of Import Hashes (ImpHash), which is a feature often used in malware analysis. You can extract Certificate Revocation List, compute different hash sums and other useful stuff for working with PE files.

Getting Started & API Reference

The API reference can be found here: PeNet Documentation & API Reference.

For an overview of PeNet or to analyze PE files go to: penet.io

Continuous Integration

The project is automatically build, tested and released with an Azure Pipeline.

To release a new version, push a tagged commit. For example:

git tag -a v2.0.0 -m 'Release version 2.0.0'
git push origin v2.0.0

penet's People

Contributors

0xced avatar a510 avatar alexrp avatar bopin2020 avatar corstiaan84 avatar dependabot-preview[bot] avatar dependabot[bot] avatar dewera avatar droyad avatar farodin91 avatar gfs avatar japp-0xlabs avatar kodemum avatar larsschlieper avatar lifka avatar lisa0930 avatar lufthavn avatar mrjul avatar paulirwin avatar pfamircea avatar rngcntr avatar secana avatar sergiibratus avatar sgso avatar washi1337 avatar xkein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

penet's Issues

Issues that freeze

Hi.

I found some malware that freeze your project. It looks like it is an easy fix, and some of these are the same issue, but I figured I would send all of them to you just in case.

This is real malware, so I zipped the files with the password: infected

You can download the malware files from here:

www.desktopfolders.com/Malware.zip

Thank you!

Use new constructor syntax (C# 8)

Example:

public class CnCDBConfig
        {
            public string ConString { get; }
            public int UpdateAllSeconds { get; }

            public CnCDBConfig(string conString, int updateAllSeconds)
                => (ConString, UpdateAllSeconds) = (conString, updateAllSeconds);
        }

How to extract Debug Info

I've been digging through the source, but I can't figure out how to take an Address or Pointer and use it to read the section. Specifically I am looking for the hash/signature and age in the ImageDebugDirectory data. Any pointers would be appreciated.

A couple small exceptions

Hi,

Here are some files that reproduce a few minor bugs, they are all clean Windows files.

I also have some malware files that have similar issues, but I think fixing these minor bugs will fix the exceptions for the malware files, if not, I will let you know.

You can download the files here:
www.desktopfolders.com/FilesWithErrors.zip

Thank you!

Support .Net Framework v.4.0

Hello,
Could you please add support of .Net v4.0 for nuget package.
It seems that your library can be compiled targeting this version of .Net

StrongName version of package

This package is amazing, but I'm needing a version that is strongly-name to avoid the following errors:

System.IO.FileLoadException: Could not load file or assembly 'PeNet, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)
File name: 'PeNet, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null

signed files reporting as unsigned

It appears that signed file checks may have an issue, have only tested with a few known signed x64 binaries, no other info at the moment.

> PeNet.Utilities.SignatureInformation.IsSigned("C:\Windows\System32\kernel32.dll");; 
val it : bool = false 
> PeNet.Utilities.SignatureInformation.IsSigned("C:\Users\me\Downloads\SysinternalsSuite\ADExplorer.exe");; 
val it : bool = false 
> PeNet.Utilities.SignatureInformation.IsSigned("C:\Windows\explorer.exe");;                               
val it : bool = false```

Filling imports

There does not appear to be any way to easily translate an imported function to its IAT address (for mapping an image into memory.) The following code works. 64 bit only, was in a hurry!

    public struct BetterImportedFunction
    {
        /// <summary>
        /// The module of the import.
        /// </summary>
        public string Module;
        /// <summary>
        /// The function being imported.
        /// </summary>
        public string Function;
        /// <summary>
        /// The ordinal being imported.
        /// </summary>
        public int Ordinal;
        /// <summary>
        /// The IAT address to fill.
        /// </summary>
        public ulong FillAddress;
    }

    public static class PeFileExtensions
    {
        private const ulong OrdinalBit = 0x8000000000000000ul;
        private const ulong OrdinalMask = 0x7FFFFFFFFFFFFFFFul;


        public static void IterateImports(this PeFile file, Action<BetterImportedFunction> handler)
        {
            var headers = file.ImageSectionHeaders;
            foreach (var import in file.ImageImportDescriptors)
            {
                var module = file.Buff.GetCString(import.Name.RVAtoFileMapping(headers));
                var round = 0u;

                var thunkAddr = import.FirstThunk.RVAtoFileMapping(headers);
                var thunk = new IMAGE_THUNK_DATA(file.Buff, thunkAddr, true);
                while (thunk.AddressOfData != 0)
                {
                    if ((thunk.Ordinal & OrdinalBit) == OrdinalBit)
                    {
                        handler.Invoke(new BetterImportedFunction
                        {
                            Module = module,
                            Function = null,
                            Ordinal = (ushort)(thunk.Ordinal & OrdinalMask),
                            FillAddress = import.FirstThunk + (round * 8)
                        });
                    }
                    else
                    {
                        var addrOfNameData = ((uint)thunk.AddressOfData).RVAtoFileMapping(headers);
                        var nameData = new IMAGE_IMPORT_BY_NAME(file.Buff, addrOfNameData);

                        handler.Invoke(new BetterImportedFunction
                        {
                            Module = module,
                            Function = nameData.Name,
                            Ordinal = -1,
                            FillAddress = import.FirstThunk + (round * 8)
                        });
                    }

                    round += 1;
                    thunk = new IMAGE_THUNK_DATA(file.Buff, thunkAddr + (round * 8u), true);
                }
            }
        }
    }
`

DllCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_SEH Flag is never set.

The DllCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_SEH Flag is never set when examining a PE file regardless of whether the PE uses safeseh or not.

It's either that or I am being a moron and not using it correctly. :D

The following code demonstrates the problem, however you will have to supply a non safeseh dll on your system to test with:

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var peHeader = new PeNet.PeFile(@"C:\Windows\System32\ntdll.dll"); //try a non safeseh file as well 

            var File_Characteristics = peHeader.ImageNtHeaders.OptionalHeader.DllCharacteristics;

            PeNet.Constants.OptionalHeaderDllCharacteristics safe_seh = (PeNet.Constants.OptionalHeaderDllCharacteristics)File_Characteristics;

            if (safe_seh.HasFlag(PeNet.Constants.OptionalHeaderDllCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_SEH))
            {
                Console.WriteLine("flag is set");
            }
            else
            {
                Console.WriteLine("flag is not set");
            }
            Console.ReadKey();
        }
    }
}

throw Exception

I've got a patch to throw a new PeNetException instead of Exception so I can ignore it from PeNet (the way we use it creates a lot of exception chatter)

But should I apply it to master or devel or core, or what? I can't tell what's going on

Memory leak?

I forgot to mention this, but one last thing...

I noticed that if I open several files (especially large files), the memory utilization of the PeNet process continues to increase.

Should PeNet dispose of the opened file after it is finished displaying the results?

Thank you!

TLS Callback

Hi, I am not sure that the TLS Callbacks are working correctly. Files that use TLS callbacks are somewhat rare, so I searched for a sample and analyzed it with another PE utility, and it showed the TLS callbacks, but for some reason, they are not showing in PeNet.

For example if you download and compile this code:

https://docs.google.com/uc?id=0ByDwYV_JGWRNNTZkMWUzMjYtNDljOS00YmNjLWFlZDItMWRjYTI0YmY5OWVk&export=download&hl=en

Here is the website where I got the above link: http://waleedassar.blogspot.com/2010/10/quick-look-at-tls-callbacks.html

One quick question... what is purpose of the AhoCorasick class? It looks really cool, but I do not see anything that calls it. Just curious. Thank you!

Parsing PE file in memory

Hi,

first of all thanks for PeNet, it is a great library!
I have one feature request - the ability to parse PE file directly from memory, without the need to copy the contents to another buffer.
I tried to implement this myself using Streams, but I got stuck since the byte array usage is used in every parser and it seems to me that switch to memory streams would be very consuming (although I might be wrong).

Thanks,
aelth

Quick quesion / possible issue

The IsExe attribute ALWAYS returns True for .exe AND .dll files...

While the IsDll attribute returns True only for .dll files. (So this makes sense)

Is the IsExe attribute supposed to return True for ALL .dll files?

Thank you!

Debug Directories is not fully dumped

Hi secana,
Sometimes, the debug directory has more than one entry, but PeNet parsers only the first one.
For example,
Debug Directories

    Time Type        Size      RVA  Pointer
-------- ------- -------- -------- --------
AEA44997 cv            22 00002228      E28    Format: RSDS, {A2E56CF0-FB64-CC3D-EABD-4F16EB0AAB11}, 1, csrss.pdb
AEA44997 coffgrp      1A4 0000224C      E4C    50475500 (PGU)
AEA44997 repro         24 000023F0      FF0    F0 6C E5 A2 64 FB 3D CC EA BD 4F 16 EB 0A AB 11 56 E5 54 A5 89 68 C0 8A 07 66 50 24 97 49 A4 AE

PeFile.IsDriver is incorrect

IsDriver is checking if the subsystem is native to determine if an image is a driver or not. This is insufficient. There are native Windows executables (i.e. not linked to a subsystem), such as SMSS.EXE that are user-mode applications. The correct way to determine if an image is a kernel-mode driver is to check if the subsystem is native AND the image is linked against NTOSKRNL.EXE. Windows applications cannot link against NTOSKRNL, and are instead linked against NTDLL.DLL

Use null-coalescing-assignment operator (C# 8)

using System;

namespace Test
{
    class Program
    {
        private byte[] _myFile = null;

        public byte[] MyFile { 
            get {
                if(_myFile == null)
                {
                    _myFile = System.IO.File.ReadAllBytes(@"c:\foo.bar");
                }

                return _myFile;
            }
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

becomes

using System;

namespace Test
{
    class Program
    {
        private byte[] _myFile = null;
        public byte[] MyFile => _myFile ??= System.IO.File.ReadAllBytes(@"c:\foo.bar");

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

TLS Directory Parsing Doesn't Work

I consistently get a null value for the TLSDirectory of multiple PE images that have valid TLS Directories (confirmed through CFF Explorer & my own PE Parser.)

Authenticode in .Net

Currently PeNet uses the Windows Native API to check if a sample has a valid signature. This brings the problem, that the check does not run under non-Windows systems.

Mono has an implementation that can be used instead or adapted to work with PeNet.

https://github.com/mono/mono/blob/0bcbe39b148bb498742fc68416f8293ccd350fb6/mcs/tools/security/chktrust.cs

https://github.com/mono/mono/tree/0bcbe39b148bb498742fc68416f8293ccd350fb6/mcs/class/Mono.Security/Mono.Security.Authenticode

Use this as a base to get rid of the Windows dependency here.

not usable in .Net Framework

Since the conversion to .NET Core and .NET Standard NuGet in VS 2015 doesn't allow PeNet to be referenced by .NET Framework projects.

Could not install package 'PeNet 0.5.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.6.1', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

Remove JSON dependency

Remove the Newtonsoft.JSON dependency and instead discribe the way to export a PE file as JSON in the help files.

Saving a modified PE File

First of all, PeNet is awesome. I'm just missing the ability to write modified headers / file back to disk. Is this feature really not implemented or did I miss something? In case its really missing is there a chance to see it implemented in the future?

why the ImageBase type is ulong?

hi , when I debuging a 32bit app(PeNet.Test\Binaries\NetFrameworkConsole.exe),
why PeFile.ImageNtHeaders.OptionalHeader.ImageBase is a ulong field ,not uint ?

Exported data.

Not all exports could be a functions. It could be a data also. How to distinguish them?

PeFile ignores exported functions without a name

Some DLLs have functions that are exported by ordinal only. These functions do not have a name at all, so NumberOfNames is not equal to NumberOfFunctions. I have modified PeFile.ParseExportedFunctions, and can confirm that this code works on my test file:

    private PeFile.ExportFunction[] ParseExportedFunctions(byte[] buff, Structures.IMAGE_EXPORT_DIRECTORY ed, Structures.IMAGE_SECTION_HEADER[] sh)
    {
        var expFuncs = new PeFile.ExportFunction[ed.NumberOfFunctions];
        var funcOffsetPointer = Utility.RVAtoFileMapping(ed.AddressOfFunctions, sh);
        var ordOffset = Utility.RVAtoFileMapping(ed.AddressOfNameOrdinals, sh);
        var nameOffsetPointer = Utility.RVAtoFileMapping(ed.AddressOfNames, sh);

        var funcOffset = Utility.BytesToUInt32(buff, funcOffsetPointer);

        //Get addresses
        for (uint i = 0; i < expFuncs.Length; i++)
        {
            var ordinal = i + ed.Base;
            var address = Utility.BytesToUInt32(buff, funcOffsetPointer + sizeof(uint) * i);

            expFuncs[i] = new PeFile.ExportFunction(null, address, (ushort)ordinal);
        }

        //Associate names
        for (uint i = 0; i < ed.NumberOfNames; i++)
        {
            var namePtr = Utility.BytesToUInt32(buff, nameOffsetPointer + sizeof(uint) * i);
            var nameAdr = Utility.RVAtoFileMapping(namePtr, sh);
            var name = Utility.GetName(nameAdr, buff);
            var ordinalIndex = (uint)Utility.GetOrdinal(ordOffset + sizeof (ushort)*i, buff);

            expFuncs[ordinalIndex] = new PeFile.ExportFunction(name, expFuncs[ordinalIndex].Address, expFuncs[ordinalIndex].Ordinal);
        }

        return expFuncs;
    }

My reference for this modification was http://web.archive.org/web/20160306071658/http://win32assembly.programminghorizon.com/pe-tut7.html

A few small specific issues

Hey, here are a few more samples that reproduce bugs… they are all malware, so the zipped file is password protected with the password “infected”.

The Resource.ResourceDirectory.Manifest Crash.exe will crash PeNet when you navigate to the Resource tab, then expand Resource Directory, and then expand Manifest.

The other two files have invalid values under the Sections tab… I believe because they contain embedded files.

http://www.desktopfolders.com/Malware2.zip

Thank you!

Useless code in PEditor.TabItems. SetImports()

public void SetImports(PeFile peFile)
{
_peFile = peFile;
lbImportDlls.Items.Clear();
if (peFile.ImportedFunctions == null)
return;
var dllNames = peFile.ImportedFunctions?.Select(x => x.DLL).Distinct();
var dllFunctions = new Dictionary<string, IEnumerable<ImportFunction>>();
foreach (var dllName in dllNames)
{
var functions = peFile.ImportedFunctions.Where(x => x.DLL == dllName);
dllFunctions.Add(dllName, functions);
}
foreach (var kv in dllFunctions)
{
lbImportDlls.Items.Add(new { DLL = kv.Key });
}
}

Is functionally same as

        public void SetImports(PeFile peFile)
        {
            _peFile = peFile;
            lbImportDlls.Items.Clear();

            if (peFile.ImportedFunctions == null)
                return;

            foreach (var dllName in peFile.ImportedFunctions?.Select(x => x.DLL).Distinct())
            {
                lbImportDlls.Items.Add(new { DLL = dllName });
            }
        }

Switch to DocFx

The API documentation wasn't updated in a long time. The old sandcastle API generator is deprecated. Switch to DocFx to autogenerate the API reference.

Add the API reference build step to the Cake script with automatic upload if possible.

.Net Framework test binary missing

THe ".Net Framework test binary" from the PeNet testing project is missing in the binary folder of the PeNet test project which leads to failing test.

Copy the test binary to the binary folder of the PeNet test project and make sure the binary gets checked in this time.

Authenticode works only for x32

The authenticode implementation in PeNet works only for x32 binaries but not for x64 binaries. The hash that is read from the certificate is correct, but the computed hash is wrong.

Example 32 bit:

var peFile = new PeFile(@"c:\windows\syswow64\kernel32.dll");
Assert.True(peFile.IsSignatureValid); // OK

Example 64 bit:

var peFile = new PeFile(@"c:\windows\system32\kernel32.dll");
Assert.True(peFile.IsSignatureValid); // FAILS

Split build and deploy

When a code or documentation is committed to the master branch, it builds and deploys to Nuget. The deploy fails, because there exists an package with the same version already.

Split build an deploy, such that the build and test run without triggering the deploy to Nuget.

NullReferenceException in Find

I'm getting a null NullReferenceException. Somehow t.Fail is null.

   at PeNet.PatternMatching.Trie2.<Find>d__3.MoveNext() in D:\Users\Clint\Documents\Visual Studio 2015\Projects\ConsoleApplication1\PeNet2\PatternMatching\AhoCorasick.cs:line 163
   at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
   at ConsoleApplication1.Program.Main(String[] args) in d:\users\clint\documents\visual studio 2015\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:line 26
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

This is my program:

class Program
{
    static void Main(string[] args)
    {
        var pe = new PeFile(@"c:\windows\system32\calc.exe");

        var trie = new Trie();

        var nsisSig = StringToByteArray("83 EC 20 53 55 56 33 DB 57 89 5C 24 18 C7 44 24 10");
        var s = BitConverter.ToString(nsisSig);

        trie.Add(nsisSig, "NSIS");

        var matches = trie.Find(pe.Buff);

        var count = matches.Count();

        foreach (var match in matches)
        {
            Console.WriteLine($"Pattern {match.Item1} at offset {match.Item2}");
        }
    }

    public static byte[] StringToByteArray(string hex)
    {
        hex = hex.Replace(" ", "");
        return Enumerable.Range(0, hex.Length)
                         .Where(x => x % 2 == 0)
                         .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                         .ToArray();
    }
}

Add raw and virtual offset to all properties

Currently only the property value can be accessed by its name. Add the raw (file) and virtual offset to each property. Show resolved values as a extra property.

E.g.:

PropertyType PropertyName = Property<string>(value, rawOffset, virtualOffset);

var value = PropertyName.Value;
var rawOffset = PropertyName.RawOffset;
var virtualOffset = PropertyName.VirtualOffset;
var resolvedValue = PropertyName.ResolvedValue;

IsValidPeFile returns false for valid PE file

The "IsValidPeFile" function returns "false" for "c:\windows\system32\calc.exe" which is an valid PE file.

Find out, why the function thinks it's invalid and repair the function.

What is missing for a 1.x version?

What do you think is missing for a 1.0 version step? We'd like to use your library, however our company has a kind of "no beta libraries" policy and we're concerned because of the 0.x version indicator. Would you think that the library can be used to parse the IMAGE_FILE_EXECUTABLE_IMAGE flag or do you think that your library isn't that far and we should consider implementing this ourselves instead?

Best regards,
D.R.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.