An X64dbg plugin built around the ERC library designed to assist in the exploit development process.
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.sha256ERC --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.
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.
.\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.
.\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.
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
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
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
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.
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