Easy Grade Pro 4.1 file parsing bug used as an educational example to show how beginners can start vulnerability research through reverse engineering.
An educational example created to show beginners that vulnerability research through reverse engineering is possible from the very start.
This repository comes from the need to have a simple example that could be used when teaching beginners who are starting in vulnerability research, especially those who are interested in reverse engineering.
After completing a course, a training session, or a master program related to binary exploitation or binary analysis, many students feel that real vulnerability research is something far beyond their level. They usually associate reverse engineering with very advanced topics such as kernel vulnerabilities, browser exploitation, firmware research, or complex modern targets, and because of that, they think they are not ready yet. In practice, the problem is not the lack of knowledge, but the lack of a realistic starting point.
I wanted an example that could show that with the skills learned during a basic course, it is already possible to take a real program, understand how it works, trigger a crash, and identify a real bug.
This repository is exactly that kind of example. It is not about finding a complex vulnerability. It is about showing that beginners can start from something small, reproducible, and understandable, and still be doing real vulnerability research.
This repository is directly related to my talk "The Path That Leads to Your First CVE", where I explain that there are multiple ways to enter the world of vulnerability research, and that each person usually ends up following a different path depending on their interests.
Some people start with source code auditing, others with reverse engineering, others with web security, and others with technology research. All of these paths are valid, but the important part is understanding that every area also has beginner-friendly entry points.
Examples of beginner paths include:
These kinds of targets may look basic, but they teach the same core skills that are needed later when working on complex systems.
This repository represents one of those beginner paths in the reverse engineering field.
The vulnerability documented here was found by analyzing an old application, understanding how its file format is parsed, and identifying a programming mistake that leads to a crash. The impact itself is not complex, but the process is real, reproducible, and useful for learning how vulnerability research actually works.
This is the type of example I use when explaining "The Path That Leads to Your First CVE", to show that reverse engineering is a valid path from the very beginning, and that starting with simple targets is not only acceptable, but often the best way to learn.
When you are starting, modern applications are often too complex. They use protections, mitigations, and codebases that are difficult to understand without a lot of experience. Old software is different.
Legacy applications were not written with modern security practices in mind. They often contain simple parsing bugs, unsafe memory operations, and logic errors that can be understood with basic reversing skills. That makes them perfect for learning.
With an old program you can: reverse the binary, understand the file format, trigger a crash, analyze the crash, locate the bug, document the issue, and report the vulnerability. In other words, you learn the fundamental skills that every vulnerability researcher needs.
That is exactly what this example is about.
This example is important because it shows something very simple:
If you like reverse engineering, you can follow that path from the beginning. It may take years to master it, but you do not need to wait years to start doing real work.
The vulnerability (CVE-2025-70330)) affects the file parsing logic of Easy Grade Pro 4.1 when loading proprietary .EGP gradebook files.
The application reconstructs internal gradebook structures by reading fixed-position fields from the file and using those values as offsets inside the loaded file buffer. These offsets are later used to calculate memory sizes and to copy data into dynamically allocated buffers.
Under normal conditions, the file passes several structural checks before the parsing continues. However, once these checks succeed, the parser trusts the offset values stored inside the file without validating that they remain within the bounds of the loaded buffer.
By modifying specific bytes inside an otherwise valid .EGP file, it is possible to corrupt these internal offset calculations. When the parser later uses these values, it attempts to read memory outside the valid file region, which results in an access violation and application crash.
This condition corresponds to an out-of-bounds read (CWE-125), leading to a local denial-of-service when the crafted file is opened.
The .EGP file format is parsed using an offset-based approach. Instead of processing the file sequentially, the parser reads internal structures that contain start and end offsets describing where specific data blocks should be located inside the file.
These offsets are used to calculate the size of a memory region and to copy data from the loaded file buffer into newly allocated memory.
The vulnerable logic can be summarized as:
size = offset_end - offset_start + 1
buffer = calloc(1, size)
memcpy(buffer, file_buffer[offset_start - base_offset], size)
Once the file passes the initial validation checks, the parser assumes that the offsets stored in the file are valid. No verification is performed to ensure that the computed source pointer remains inside the loaded file buffer.
If the offsets are manipulated in a controlled way, the parser may attempt to read memory outside the valid region, causing an access violation during the memcpy() operation.
Not every malformed .EGP file triggers the crash.
The parser performs several consistency checks before reaching the vulnerable code path. If the file structure is too corrupted, the application stops parsing early and reports that the gradebook is damaged.
However, some modifications keep the internal structures coherent enough to pass the initial checks, while still producing incorrect offset values later in the parsing process.
When this happens, the parser reaches deeper routines where these offsets are trusted and used in memory copy operations, eventually causing the out-of-bounds read.
The crash can be triggered by modifying a valid .EGP file and inserting controlled data at a specific offset.
The proof of concept works by:
Example parameters used in the PoC:
This modification keeps the file structurally valid enough to pass the initial checks, but corrupts internal offset calculations used later by the parser, eventually causing the application crash.
When the malformed file is opened under a debugger, the application crashes during a memory copy operation.
The exception observed is an access violation caused by an invalid memory read.
During debugging, the invalid pointer used by memcpy() originates from offset calculations derived from the parsed file structures. When these offsets reference memory outside the loaded file buffer, the source pointer points to an unmapped address, causing the crash.
This confirms that the vulnerability is caused by missing bounds validation during file parsing.
This vulnerability affects an end-of-life product that is no longer maintained by the vendor.
The issue is documented for educational and research purposes, and to give beginners a concrete example of how software can be analyzed step by step to understand how bugs appear and how real vulnerabilities are found.