Jump to content

Recommended Posts

HxD is a Freeware hex, disk and memory editor, that is fast and can handle files of arbitrary size (up to 8 EiB).

 

414558680_MiniShotHxD1.png.aabade0086bbfb712b4ccbe31435c19e.png

 

Some of the feature highlights are:

  • Disk editor (automatically unmounts drives as necessary when saving changes)
  • Memory editor (full support for 64 and 32-bit)
    • Data folding, for easier overview and hiding inaccessible regions
  • Data inspector
  • Search and replace with support for various data types
  • Importing and exporting of Intel Hex, Motorola S-Records
  • Exporting to Pascal, C, Java, C#, VB.NET, PureBasic, but also HTML, RTF, and TeX
  • Checksum and hash generation and validation
  • File compare
  • Tools to split, join and shredder files

 

Currently, available in version 2.4 and 17 languages: HxD download.

 

P.S.: If you like it, please star the code on GitHub or give it a (good 😉) rating on download sites.

Edited by mael
  • Like 6
  • Thanks 4

Share this post


Link to post

Nice!

 

I used HxD before and I really liked it. I just always have VSCode open and it's easier with it's addon. It doesn't do as much as your program does, though.

Good job, you just created an awesome tool in an awesome language!

Share this post


Link to post

Looks very promising! Will give this tool a try, probably it could replace WinHex for some non-specific use cases.

In addition I'd like to have a text viewer (ideally editor) that supports very large files and UTF8. Currently I don't know an app with such abilities

Share this post


Link to post

Thank you everyone for the positive feedback 🙂

 

On 3/10/2020 at 8:58 AM, Fr0sT.Brutal said:

In addition I'd like to have a text viewer (ideally editor) that supports very large files and UTF8.

There is a feature request / progress report regarding UTF-8.

https://forum.mh-nexus.de/viewtopic.php?f=4&t=1004

If you have any comments regarding the design or implementation, please comment there. This is mostly about technical issues of multi-byte encodings and their representation.

Share this post


Link to post

As a file viewer (not editor) for very large files and with UTF8 support there is nothing to beat V from fileviewer.com.  I ignore all the file-manager stuff and use it, daily, as a file viewer.

  • Thanks 1

Share this post


Link to post
32 minutes ago, mael said:

There is a feature request / progress report regarding UTF-8. 

I'm unsure... probably that's not the proper task for Hex viewer

5 minutes ago, timfrost said:

V from fileviewer.com

Pretty nice one! Alas it's shareware

Share this post


Link to post

Well, yes, you do have to pay for excellence.  But $20 for 6 years use, and updates, is a steal; and when I first started using V in 1998 the licence was perpetual.  Prompt support and response to feature requests, too.  It's a classic which nobody should be without!

Share this post


Link to post

Well, I am sure you will understand that it's not really nice to advertise another product in a thread specifically presenting HxD.

 

I have invested many years into it (since 2002), and it has been Freeware all the time. A little respect for that effort would be appreciated.

Edited by mael
  • Like 6

Share this post


Link to post

@mael  OK, but my original posting made clear it was not a competitor.  Apologies for getting diverted by the reply to it.

Share this post


Link to post

@maelI would really find a Delphi library that wraps up the HexEditor features valuable. Not freeware but paid for.

Even if the library was binary only.   

 

Share this post


Link to post

@David Champion Thanks for the suggestion. Considering how I would have to keep updating to the most recent Delphi version regularly, and how limited the amount of people is that I would expect to use a hex editor component, it will probably cost me more than I would earn (and require additional support). My assumption is based on the plugin architecture that I published for HxD. While still limited in functionality, it is a first indicator.

 

But maybe I am missing something?

Edited by mael

Share this post


Link to post

I am working on a structure editor right now, so that you can define structure of files, like portable executables, declaratively.

Share this post


Link to post

It's still very much in development, but I can show some screenshots and show part of the (evolving) syntax, as it is implemented now.

Share this post


Link to post

Currently, I am working again (as mentioned above) on a feature for creating a structure viewer/editor.

 

PE (portable executable) files are currently the template to determine the necessary functionality (but other file formats like PNG-files and matching features will be added).

Currently, you can define dynamic arrays and structures with dynamic size, where other parts/fields in the file define the size, and pointers are dereferenced automatically.

There is also a feature to map pointers using a function (currently only built-in ones). For PE files this allows mapping RVA (relative virtual addresses) to absolute file offsets.

 

All of the file structure is given in a declarative language, called HxD structure definition (HSD).

 

A functional example for parsing PE headers is given below:

types
  PVirtualAddress = pointer<UInt32, UInt32>


  IMAGE_DATA_DIRECTORY = struct {
    VirtualAddress: UInt32;
    Size: UInt32;
  }

  IMAGE_FILE_HEADER = struct {
    Machine: UInt16;
    NumberOfSections: UInt16;
    TimeDateStamp: UInt32;
    PointerToSymbolTable: UInt32;
    NumberOfSymbols: UInt32;
    SizeOfOptionalHeader: UInt16;
    Characteristics: UInt16;
  }

  IMAGE_OPTIONAL_HEADER32 = struct {
    Magic: UInt16;
    MajorLinkerVersion: UInt8;
    MinorLinkerVersion: UInt8;
    SizeOfCode: UInt32;
    SizeOfInitializedData: UInt32;
    SizeOfUninitializedData: UInt32;
    AddressOfEntryPoint: UInt32;
    BaseOfCode: UInt32;
    BaseOfData: UInt32;

    ImageBase: UInt32;
    SectionAlignment: UInt32;
    FileAlignment: UInt32;
    MajorOperatingSystemVersion: UInt16;
    MinorOperatingSystemVersion: UInt16;
    MajorImageVersion: UInt16;
    MinorImageVersion: UInt16;
    MajorSubsystemVersion: UInt16;
    MinorSubsystemVersion: UInt16;
    Win32VersionValue: UInt32;
    SizeOfImage: UInt32;
    SizeOfHeaders: UInt32;
    CheckSum: UInt32;
    Subsystem: UInt16;
    DllCharacteristics: UInt16;
    SizeOfStackReserve: UInt32;
    SizeOfStackCommit: UInt32;
    SizeOfHeapReserve: UInt32;
    SizeOfHeapCommit: UInt32;
    LoaderFlags: UInt32;
    NumberOfRvaAndSizes: UInt32;
    DataDirectory: IMAGE_DATA_DIRECTORY[:NumberOfRvaAndSizes];
  }

  IMAGE_NT_HEADERS32 = struct {
    Signature: UInt8[4];
    FileHeader: IMAGE_FILE_HEADER;
    OptionalHeader: IMAGE_OPTIONAL_HEADER32;
  }


  PIMAGE_NT_HEADERS32 = pointer<UInt32, IMAGE_NT_HEADERS32>

  IMAGE_DOS_HEADER = struct {
    e_magic: UInt8[2];
    e_cblp: UInt16;
    e_cp: UInt16;
    e_crlc: UInt16;
    e_cparhdr: UInt16;
    e_minalloc: UInt16;
    e_maxalloc: UInt16;
    e_ss: UInt16;
    e_sp: UInt16;
    e_csum: UInt16;
    e_ip: UInt16;
    e_cs: UInt16;
    e_lfarlc: UInt16;
    e_ovno: UInt16;
    e_res: UInt16[4];
    e_oemid: UInt16;
    e_oeminfo: UInt16;
    e_res2: UInt16[10];
    _lfanew: UInt32;
  }

  IMAGE_SECTION_HEADER = struct {
    Name: Char8Ansi[8];
    Misc_PhysicalAddressOrVirtualSize: UInt32;
    VirtualAddress: UInt32;
    SizeOfRawData: UInt32;
    PointerToRawData: UInt32;
    PointerToRelocations: UInt32;
    PointerToLinenumbers: UInt32;
    NumberOfRelocations: UInt16;
    NumberOfLinenumbers: UInt16;
    Characteristics: UInt32;
  }

  IMAGE_IMPORT_DESCRIPTOR = struct {
    OriginalFirstThunk_ImportLookupTable_RVA: UInt32;
    TimeDateStamp: UInt32;
    ForwarderChain: UInt32;
    Name_RVA: UInt32;
    FirstThunk_ImportAddressTable_RVA: UInt32;
  }

  OVERALL_FILE = struct {
    ImageDosHeader: IMAGE_DOS_HEADER;
    ImageNtHeaders32: IMAGE_NT_HEADERS32 @ :ImageDosHeader._lfanew;                                                        
    ImageSectionHeaders: IMAGE_SECTION_HEADER[:ImageNtHeaders32.FileHeader.NumberOfSections];
  }

instances
  $root: OVERALL_FILE

 

The attached pictures show how this is parsed/visualized for my PropEdit.exe (but the solution is generic and works with any 32-bit PE file).

 

structedit1.thumb.png.85654d732b961eafdc4b3087a0f2bc00.png

structedit2.thumb.png.45b55d151d07418b6c1d3b5b0b73d0a7.png

structedit3.thumb.png.a500be4be233b75a615f07905f845acd.png

structedit4.thumb.png.b629886cc35b5fefda41d487051f66d8.png

structedit5.thumb.png.3092bc3b7b4710c03a96b6c1ef1a2405.png

Edited by mael
  • Like 2

Share this post


Link to post

What is special (besides being able to define dynamic structures and automatically parsing files accordingly), are expressions like this:

DataDirectory: IMAGE_DATA_DIRECTORY[:NumberOfRvaAndSizes];

As you can see in the fourth picture in the post above, the array size of DataDirectory dynamically depends on the field NumberOfRvaAndSize, which was defined earlier in the file, and is displayed accordingly. While with traditional programming language you would need additional code to handle the dynamic nature of the data structure, you can do it declaratively in HSD.

 

The position of ImageNtHeaders32 is dependent on ImageDosHeader._lfanew, which is a file-dependent offset/pointer and would also require imperative code in traditional languages. In HSD this declaration suffices:

ImageNtHeaders32: IMAGE_NT_HEADERS32 @ :ImageDosHeader._lfanew;

The result can be seen in the second picture in the post above.

 

ImageSectionHeaders: IMAGE_SECTION_HEADER[:ImageNtHeaders32.FileHeader.NumberOfSections];

ImageSectionHeaders is defined dynamically, as well. But in such a way that it depends on the two dynamic declarations before (their size and position, that depends on sibling/previous fields). This is because ImageSectionHeaders is the third field in OVERALL_FILE and the preceding fields are of dynamic size, so the position of ImageSectionHeaders adapts accordingly. The size of ImageSectionHeaders is also dynamic, as can be seen when looking at the identifier between [ and ].

Edited by mael
Fixed formatting
  • Like 1

Share this post


Link to post

Later I added the ability to define pointers which automatically use a function to map addresses, with this syntax:

 

PVirtualAddress = pointer<UInt32, UInt32, RVAToFilePointer>

The first UInt32 defines the address size (this is settable, since you cannot assume all pointers in a file to have the same bitwidth or even type; as opposed to pointers in normal code, that always follows the CPU's constraints). The second one is the datatype of the pointer target, to keep things simple for now, just an UInt32 (but it will be a structure type later).
Finally, RVAToFilePointer is the function that does the mapping from the RVAs stored in the file to absolute file offsets.

RVAToFilePointer is a built-in function that gets called whenever a mapping is needed, but I'll expand this to allow for simple functions, that can be declared in HSD, as well.

 

With this new ability, the data directories in the PE file can now be defined as follows, and will be properly found in the structure viewer:

IMAGE_DATA_DIRECTORY = struct {
  VirtualAddress: PVirtualAddress;
  Size: UInt32;
}

 

Edited by mael

Share this post


Link to post

@mael looks like you are well into the task and really motivated.

You explain it very clearly but I will need to re-read the comments in the morning, since I have been

working long hours and am just finishing for the day.

 

I'm catching your excitment.

Share this post


Link to post

 @David Champion Thanks, this is a summary of the work I have been doing over a longer period, more work is needed. I edited the posts a bit and clarified them, so rereading them later makes sense 🙂

Share this post


Link to post
On 2/1/2021 at 10:55 PM, David Champion said:

@mael looks like you are well into the task and really motivated.

You explain it very clearly but I will need to re-read the comments in the morning, since I have been

working long hours and am just finishing for the day.

 

I'm catching your excitment.

Were you planning to comment anything further, or just intended to look?

@David Champion

Edited by mael

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×