Skip to content

Repository files navigation

Image

ERC.Xdbg

License GitHub tag (latest by date) GitHub issues

An X64dbg plugin built around the ERC library designed to assist in the exploit development process.

Installation

Download the zip for your architecture from the releases page and unzip it into x64dbg's plugins directory - x32\plugins for the 32-bit debugger, x64\plugins for the 64-bit one. If x64dbg has no plugins directory yet, run it once to create the initial directory structure.

The archive contains the plugin and the native assembler it depends on. Unzip the whole thing: with FASM.DLL missing the plugin loads and then fails when --assemble is first used.

Every release is published with a .sha256 beside it. To check a download before installing it:

Get-FileHash .\Erc.Xdbg-x64.zip -Algorithm SHA256
type .\Erc.Xdbg-x64.zip.sha256

Updating

ERC --update downloads and installs the current release from inside the debugger. It verifies the download against the published hash and refuses to install anything that does not match, so an update cannot be swapped for something else in transit. Your existing plugin is renamed to Erc.Xdbg.dp64-OLD_0.txt rather than deleted, and x64dbg has to be restarted to load the new one.

Building from source

git clone https://github.com/Andy53/ERC.Xdbg
cd ERC.Xdbg
.\build.ps1

That produces both architectures and verifies each one before reporting success:

Platform Output Copy into
x86 ErcXdbg\bin\x86\Release\net472\Erc.Xdbg.dp32 x32\plugins\
x64 ErcXdbg\bin\x64\Release\net472\Erc.Xdbg.dp64 x64\plugins\

Build one at a time with .\build.ps1 -Platform x64, or a debug build with -Configuration Debug. The solution also opens and builds in Visual Studio.

Requirements: Visual Studio 2022 or the Build Tools for Visual Studio with the .NET desktop build tools workload. dotnet build alone is not enough: x64dbg loads plugins as native DLLs, and the native entry points are added by an IL-rewriting step that only runs under full MSBuild. build.ps1 locates MSBuild for you and fails with an explanation if it is missing.

No manual steps are needed to switch architecture. Everything follows from the platform you build, and build.ps1 checks the result really is the architecture you asked for before it reports success.

Running the tests

.\test.ps1                     # both architectures
.\test.ps1 -Platform x64       # one
.\test.ps1 -Coverage           # with a per-class coverage summary
.\test.ps1 -SkipIntegration    # skip the live-process tests

The suite runs against both x86 and x64 because the library is built per architecture and reads pointer width at run time, so some behaviour genuinely differs between the two - pointer filtering and PE flag parsing both did.

Some tests launch a real target process and inspect it, so that memory searching, gadget finding, module parsing and thread enumeration are exercised against something real rather than a substitute. The target (tests/Fixtures/ErcTestTarget) plants known byte sequences and strings in unmanaged memory and prints their addresses, and the tests assert that ERC finds the exact address the target reported. They are tagged Integration, take a few seconds, and can be skipped during a fast edit loop.

Cutting a release

.\package.ps1                  # builds both architectures and writes artifacts\
.\package.ps1 -SkipBuild       # package whatever is already built

That produces Erc.Xdbg-x86.zip and Erc.Xdbg-x64.zip, each with a .sha256 beside it. The archive contents are declared once, at the top of package.ps1, and checked from the test suite: ReleasePackageTests takes the archive that was actually produced and installs it with the same updater that runs inside x64dbg, so a dependency dropped from the package fails a test rather than reaching a user.

Pushing a v* tag runs the release workflow, which builds, tests, packages and publishes. One wrinkle is worth knowing about: the shipped plugin looks for a release under the fixed tag 32 or 64 rather than the newest one, so the workflow moves those two tags onto whatever it is releasing. Changing that scheme would strand every installation that predates the change.

Documentation

This library contains the fundamental specifications, documentation, and architecture that underpin ERC.Xdbg. If you're looking to understand the system better, or want to know how to integrate the various components, there is a lot of valuable information contained here.

📄 Documentation and Specifications

API

ERC.Net is the API used to develop ERC.Xdbg, all of the functionality in this plugin stems from the API. ERC.Net is a collection of tools designed to assist in debugging Windows application crashes.

📁 Source - https://github.com/Andy53/ERC.net
📦 32 bit Package - ERC.Net-x86.SDK
📦 64 bit Package - ERC.Net-x64.SDK

Articles

A list of articles covering common usage scenarios using ERC.Xdbg.

📄 The Basics of Exploit Development 1: Win32 Buffer Overflows
📄 The Basics of Exploit Development 2: SEH Overflows
📄 The Basics of Exploit Development 3: Egg Hunters
📄 The Basics of Exploit Development 4: Unicode Overflows
📄 The Basics of Exploit Development 5: x86-64 Buffer Overflows

Globals

Global variables are variables which are set and stored for one session. They are reset to the defaults each time X64dbg is restarted.

-ASLR
Used to exclude pointers from modules implementing ASLR in search output. Can be reset by supplying false as a parameter.
    Example: ERC --help -ASLR Remove pointers from ASLR enabled modules from all search results.
    Example: ERC --help -ASLR false Include pointers from ASLR enabled modules in all search results.

-SafeSEH
Used to exclude pointers from modules implementing SafeSEH in search output. Can be reset by supplying false as a parameter.
    Example: ERC --help -SafeSEH Remove pointers from SafeSEH enabled modules from all search results.
    Example: ERC --help -SafeSEH false Include pointers from SafeSEH enabled modules in all search results.

-Rebase
Used to exclude pointers from modules implementing Rebase in search output. Can be reset by supplying false as a parameter.
    Example: ERC --help -Rebase Remove pointers from Rebase enabled modules from all search results.
    Example: ERC --help -Rebase false Include pointers from Rebase enabled modules in all search results.

-NXCompat
Used to exclude pointers from modules implementing NXCompat in search output. Can be reset by supplying false as a parameter.
    Example: ERC --help -NXCompat Remove pointers from NXCompat enabled modules from all search results.
    Example: ERC --help -NXCompat false Include pointers from NXCompat enabled modules in all search results.

-OSdll
Used to exclude pointers from modules that are OSdll's in search output. Can be reset by supplying false as a parameter.
    Example: ERC --help -OSdll Remove pointers from OSdll's from all search results.
    Example: ERC --help -OSdll false Include pointers from OSdll's in all search results.

-Cfg
Used to exclude pointers from modules built with Control Flow Guard. Can be reset by supplying false as a parameter.
    Example: ERC --help -Cfg Remove pointers from CFG-enabled modules from all search results.
    Example: ERC --help -Cfg false Include pointers from CFG-enabled modules in all search results.

-Bytes
Used to exclude pointers containing specific bytes from all search results and from being added to bytearrays generated by the plugin. Can be disabled by passing switch with no arguments. Bytes must be passed without spaces.
    Example: ERC --help -Bytes 0x0A0x0D Remove pointers containing bytes 0A or 0D from all search results.
    Example: ERC --help -Bytes 740D Remove pointers containing bytes 74 or 0D from all search results.
    Example: ERC --help -Bytes Remove any previous byte restrictions from all further search results.

-Protection Used to specify the protection value of all pointers returned in search results. The default is read,write. Generic values of read, write and exec are used to specify which the returned pointers should have and can be used in combination. Options must be separated with commas and no spaces.
    Example: ERC --help -Protection exec Remove pointers that do not have exec permission from all search results.
    Example: ERC --help -Protection read,exec Remove pointers that do not have read and exec permission from all search results.
    Example: ERC --help -Protection all Remove any previous protection restrictions from all further search results.

-M
Restricts searches to named modules, comma-separated without spaces. * matches all modules and ignores -Aslr and the other module switches. *blah.dll is a suffix, blah* a prefix, anything else a substring of the module name. Disabled by passing the switch with no value.
    Example: ERC --jmp -r esp -M kernel32
    Example: ERC --searchmemory FFE4 -M kernel32,ntdll
    Example: ERC --jmp -r esp -M Clear the restriction.

-Cp
Restricts returned pointers to those whose bytes have a given shape, as they would be written into the exploit. Values are comma-separated without spaces: nonull, startswithnull, ascii, asciiprint, upper, lower, uppernum, lowernum, numeric, alphanum, unicode, unicoderev. Several are combined with AND; unicode with another criterion applies the other only to the non-null bytes. Disabled by passing the switch with no value.
    Example: ERC --jmp -r esp -Cp alphanum Only jumps whose address is A-Z, a-z or 0-9.
    Example: ERC --searchmemory FFE4 -Cp unicode,ascii Pointers that are UTF-16-shaped with ASCII non-null bytes.
    Example: ERC --jmp -r esp -Cp Clear the restriction.

-Extended
Used to specify that the extended character set should be used when using FindNRP and Pattern create and offset functionality. Can be reset by supplying false as a parameter.
    Example: ERC --help -Extended Replaces the standard character set with the extended character set.
    Example: ERC --help -Extended false Resets to the standard characters set.

-ASCII Sets the character encoding as ASCII. All search functions will seach for text in ASCII.
    Example: ERC --help -ASCII Changes the default characters encoding to ASCII.

-Unicode Sets the character encoding as Unicode. All search functions will seach for text in Unicode.
    Example: ERC --help -Unicode Changes the default characters encoding to Unicode.

-UTF7 Sets the character encoding as UTF-7. All search functions will seach for text in UTF-7.
    Example: ERC --help -UTF7 Changes the default characters encoding to UTF-7.

-UTF8 Sets the character encoding as UTF-8. All search functions will seach for text in UTF-8.
    Example: ERC --help -UTF8 Changes the default characters encoding to UTF-8.

-UTF32 Sets the character encoding as UTF-32. All search functions will seach for text in UTF-32.
    Example: ERC --help -UTF32 Changes the default characters encoding to UTF-32.

Usage

Instructions on usage of the plugin can be seen below. This can also be accessed directly through the debugger using ERC --help.

Details on each command can be seen below. Commands are not case sensitive.

--Help
Displays the help message below.
    Example: ERC --help

--Update Downloads the latest release of the plugin from Github and extracts it into the X64Dbg plugin directory for the architecture currently in use. Can be passed a ip:port pair in order to specify a proxy.
    Example 1: ERC --update
    Example 2: ERC --update 127.0.0.1:8080

--config
The config option can be used to set values in the config.xml file. These options persist between sessions. Can be used to set things such as the project author, current working directory and error log file. These options are predominantly used when writing the output of operations to file.
    Example 1: ERC --config SetWorkingDirectory C:\Users\You\Desktop
    Example 2: ERC --config GetErrorFilePath

--Pattern
The pattern option can be used to either create a pattern or to identify the location of a string within a pattern. Appending a c and then a number will create a pattern, appending a o and then a string of 3 or more characters will locate the string within the pattern. The plugin will attempt to automatically identify if the extended character set should be used however you can force it's use by adding "extended" to the command.
    Example 1: ERC --pattern c 1000
    Example 2: ERC --pattern o Aa9
    Example 2: ERC --pattern o Aa9 extended

--ByteArray
The ByteArray option allows the generation of a byte array which is displayed in the log and written to the working directory as both a text file and a binary file containing only the binary values the user wants. By default the array will contain all values from 0x00 to 0xFF and values can be omitted by passing them to the -bytes global variable.
    Example 1: ERC --bytearray
    Example 2: ERC --bytearray -bytes 0xFF0x0A \x0b 0C

--Compare
Generates a table with a byte by byte comparison of an area of memory and the bytes from a file. Takes a memory address from which to start the search and a file path for the binary file.     
    Example 1: ERC --Compare 0x12345678 C:\Users\You\Desktop\YourBinaryFile.bin

--Convert
Takes a string and converts it to a hex representation. The string can be converted as if it was ASCII, Unicode, UTF-7, UTF-8 or UTF-32.     Valid conversion types:
        Ascii to Hex = AtoH
        Unicode to Hex = UtoH
        UTF-7 to Hex = 7toH
        UTF-8 to Hex = 8toH
        UTF-32 to Hex = 32toH
    Example 1: ERC --Convert AtoH HelloWorld returns the ASCII bytes for HelloWorld.
    Example 2: ERC --convert UtoH HelloWorld returns the Unicode bytes for HelloWorld.

--Assemble
The assemble option can be used to convert assembly instructions into the associated opcodes. The plugin will attempt to identify the architecture required based on the attached process however a 0 can be passed to force 32 bit and a 1 can be passed to force 64 bit. Instructions must be separated with a comma (,).
    Example 1: ERC --Assemble jmp esp
    Example 2: ERC --assemble 1 jmp rsp, nop, nop

--Disassemble
The disassemble option can be used to convert opcodes into assembly instructions. The plugin will attempt to identify the architecture required based on the attached process however a 0 can be passed to force 32 bit and a 1 can be passed to force 64 bit.
    Example 1: ERC --disAssemble FF E4
    Example 2: ERC --disassemble 0 FF E4

--SearchMemory
Search memory can take a string or set of bytes to search for within the attached process memory and loaded modules. Optionally an integer can be passed to specify the search type (0 = bytes, 1 = Unicode, 2 = ASCII, 3 = UTF8, 4 = UTF7, 5 = UTF32). Modules can be excluded based on certain characteristics (Is ASLR/SafeSEH/Is the binary rebasable/NXCompat(DEP)/Is the binary an OS dll) The values are optional however if you wish to exclude a later value all previous ones must be included.     Example 1: ERC --SearchMemory FF E4 Search for bytes FF E4 include all dlls.
    Example 2: ERC --SearchMemory FF E4 false false false false true Search for bytes FF E4 excluding only OS dlls.
    Example 3: ERC --SearchMemory 1 HelloWorld Search for the ASCII string HelloWorld.

--SearchModules
Search modules can take a string or set of bytes to search for within the processes loaded modules. Optionally an integer can be passed to specify the search type (0 = bytes, 1 = Unicode, 2 = ASCII, 3 = UTF8, 4 = UTF7, 5 = UTF32). Modules can be excluded based on certain characteristics (Is ASLR/SafeSEH/Is the binary rebasable/NXCompat(DEP)/Is the binary an OS dll) The values are optional however if you wish to exclude a later value all previous ones must be included. Furthermore the search can be limited to certain modules by passing their name or path as arguments.
    Example: ERC --SearchModules FF E4. Search for bytes FF E4 including all dll's
    Example: ERC --SearchModules FF E4 module1.dll module2.dll. Search for bytes FF E4 only in module1.dll and module2.dll

--Dump
Dumps the contents of process memory to the log and a file in the working directory. Takes a hex start address and a hex number for number of bytes to be read.
    Example 1: ERC --Dump 0x63428401 0x30

--ListProcesses
The list processes option takes no parameters and simply lists all visible processes on the machine.
    Example 1: ERC --ListProcesses

--ProcessInfo
Displays information about the attached process, loaded modules and threads. Can be passed a boolean to indicate if the output should be written to disk.
    Example 1: ERC --processInfo
    Example 2: ERC --processinfo false Does not write processinfo output to disk.

--ModuleInfo
Displays info about the modules loaded by the attached process. Can be passed a boolean to indicate if the output should be written to disk.
    Example 1: ERC --moduleInfo
    Example 2: ERC --moduleinfo false Does not write moduleinfo output to disk.

--ThreadInfo
Displays info about threads associated with the attached process. Can be passed a boolean to indicate if the output should be written to disk.
    Example 1: ERC --threadInfo
    Example 2: ERC --threadinfo false Does not write threadinfo output to disk.

--HeapInfo
Displays information about the heap. Takes commands search, stats, ids, and dump. Takes an integer to represent the ID of the heap to utilize. Takes a hex value to specify the address of the heap entry to utilize. If both heap ID and start address are specified heap ID takes precedence, if start address and a byte pattern to search for are specified start address must be provided first. Takes a boolean value of true/false/1/0 to specify if output should be written to disk.
    Example 1: ERC --HeapInfo stats Display statistics about all heaps associated with the process.
    Example 2: ERC --HeapInfo 0x00453563 search FFE4 Search for FFE4 in the Heap entry starting at 0x00453563
    Example 3: ERC --HeapInfo 0x00453563 dump Dump all memory from heap entry starting at 0x00453563
    Example 4: ERC --HeapInfo 0x00453563 dump stats Dump all memory from heap entry starting at 0x00453563 and display stats for the heap entry starting at 0x00453563

--SEH
Displays a list of addresses for pop pop ret instructions. Can be passed a list of module paths to be ignored in the search.
    Example 1: ERC --seh
    Example 2: ERC --SEH C:\Path\To\Module\To\Exclude C:\Path\To\Other\Module\To\Exclude

--EggHunters
Prints egg hunters for x86, WOW64 (Windows 7 and 10) and x64. Optional 4-character tag, default ERCD. startreg <reg> starts the scan at that register. checksum <hex|file> skips a truncated copy. wow64 7|10 selects the WOW64 syscall stub. depmethod virtualprotect|copy|copy_size (with depreg, depsize, depdest) makes the found egg executable. The SEH hunter has no syscall; replace its four 0xCC bytes with a pop/pop/ret.
    Example 1: ERC --egghunters
    Example 2: ERC --egghunters ABCD
    Example 3: ERC --egghunters ABCD startreg eax
    Example 4: ERC --egghunters ABCD checksum 9090CC
    Example 5: ERC --egghunters wow64 10

--Encode
Encodes a payload so it survives a restricted character set. xor prefixes a position-independent decoder that XOR-decrypts in place; alphanum emits the printable AND/SUB/PUSH sequence mona uses (32-bit only). Bytes given to -Bytes are excluded from the result. The payload is hex or a file. Pass 0 or 1 to force x86 or x64 for the XOR decoder. Works without a process attached.
    Example 1: ERC --encode xor 9090CC
    Example 2: ERC --encode alphanum 9090CC
    Example 3: ERC --encode xor -Bytes 000A0D C:\payload.bin

--GetPc
Prints GetPC stubs that leave the current instruction pointer in a register. Takes the register; -r is accepted as in mona. On x86 this is the three mona variants (jmp-short-back, call-plus-4, fstenv); on x64 a RIP-relative lea is included as well. Pass 0 or 1 to force the architecture. Works without a process attached.
    Example 1: ERC --getpc eax
    Example 2: ERC --getpc -r rax 1

--FindWild
Finds an instruction sequence in process memory. Separate instructions with # or ;. * matches any one instruction; jmp * matches any jump. Honours -Aslr, -Bytes, -Cp and the other pointer filters.
    Example 1: ERC --findwild pop eax # pop ebx # ret
    Example 2: ERC --findwild jmp *
    Example 3: ERC --findwild push ecx # * # ret -Cp nonull

--Jop
Finds jump-oriented-programming gadgets: jmp or call through a memory operand. Takes an optional register to restrict the operand. Gadgets in CFG modules that are not 16-byte aligned are marked [cfg-unaligned]. Honours -Aslr, -Cfg, -Bytes, -Cp and the other pointer filters.
    Example 1: ERC --jop
    Example 2: ERC --jop eax

--Fwptr
Finds call and jmp instructions whose operand is a pointer in writable memory. A pointer-width write to that location redirects the call. Honours -Aslr, -M, -Bytes and -Cp.
    Example 1: ERC --fwptr

--Iat
Lists import address table slots: pointers to pointers a ROP chain can reuse. Optional module name, then an optional function name substring.
    Example 1: ERC --iat kernel32
    Example 2: ERC --iat kernel32 VirtualProtect

--Eat
Lists exported functions. Optional module name, then an optional function name substring.
    Example 1: ERC --eat ntdll NtAllocate

--UnicodeAlign
Builds a Venetian alignment stub for a Unicode overflow. Each injected byte is widened with 0x00, so the stub is pairs of inc/dec of the buffer register and 0x6D, which becomes add [ebp], ch. EBP must be writable. Takes an offset in bytes, or two hex addresses (current value of the register, then the target). Optional buffer register, a source register to copy from, leak (consume a leaked null), and jmp (push buffer; ret). Works without a process attached.
    Example 1: ERC --unicodealign 32
    Example 2: ERC --unicodealign 32 eax leak
    Example 3: ERC --unicodealign 0x0012FF00 0x0012FF40 eax jmp

--FindNRP
Searches process memory for a non repeating pattern specified in the pattern_extended and pattern_standard files. Takes an integer optional to specify the text formatting (1 = Unicode, 2 = ASCII, 3 = UTF8, 4 = UTF7, 5 = UTF32, default = ASCII) and can have the parameter "true" passed to indicate the extended pattern should be used. ERC --suggest turns the table into a buffer layout.
    Example 1: ERC --FindNRP
    Example 2: ERC --FindNRP 2 true Generates FindNRP table after searching for the extended NRP in Unicode format.

--Suggest
After a crash with a cyclic pattern, runs FindNRP and prints a buffer layout: junk, then a jump to a register (or nseh and pop/pop/ret for an SEH overwrite), then the payload. Looks up jmp <reg> and pop/pop/ret in the process. Honours -Aslr, -Bytes, -Cp and the other pointer filters.
    Example 1: ERC --suggest

--Rop
Attempts to build a ROP chain for the current process. Current implementation utilizes VirtualAlloc, VirtualProtect and HeapCreate.
    Example 1: ERC --Rop

--RopGadgets
Generates lists of ROP gadgets from within the current process. Lists are saved to the working directory.
    Example 1: ERC --RopGadgets

--Reset
Returns the plugin to a default status. Resets all client variables and configurations.
    Example 1: ERC --reset

Contributors

Andy Bowden
Josh Brown

About

An Xdbg Plugin of the ERC Library.

Topics

Resources

Stars

191 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages