
Joseph Mallord William Turner, The Burning of the Houses of Lords and Commons, 16 October 1834 (digitally altered)
Contents
On 20 October 2026, a forum post introduced EByte: A Go ransomware package with ChaCha20 encryption and ECIES key protection, as well as its own panel and decryptor. The post, made by moderator procurator, touted its unusual encryption pattern: Encrypt one byte, leave the next two untouched, and repeat.

Figure 1. The supplied forum screenshot shows the EByte listing dated 20 October 2026. It advertises Go, ChaCha20, ECIES, intermittent encryption, a panel and a decryptor. The post is advertising evidence; the technical findings below come from source review.
A member on T1erOne replied to the post and called out the kit, which led us to examine the source more closely.
The source package we examined implements that pattern, also revealing where much of EByte came from. Its README credits Prince ransomware, and comparison with a preserved Prince snapshot found the same encryption and decryption routines, file walkers and several supporting functions. EByte adds a builder, a web panel and launch reporting around that inherited code and switches out the branding.
For incident responders, there are two key findings here. First, although EByte leaves substantial portions of file content untouched, that does not make complete files recoverable without the missing encrypted bytes. Second, its builder embeds the private key in the matching decryptor and prints it to the builder console. These artifacts offer a much stronger recovery lead than the encryptor alone.
The Prince connection
The resemblance between EByte and Prince goes well beyond two projects which happen to share the same cryptographic libraries. In six paired implementation files, 12 of 13 shared functions have identical token sequences. Nine of those functions are byte-for-byte identical, including names, literals and operators. The comparison ignores only comments and whitespace.
Four complete files also match after substituting the projects' module import paths: The decryptor's crypto module, both file walkers, and the decryptor's main module. In the encryptor's crypto module, all four named functions match, including EncryptFile, generateKey and generateNonce. The main difference in the shared functions is the encryptor's entry point, where EByte adds a sendLockerID call.
| Component | Comparison result |
|---|---|
| Encryptor crypto module | All four shared functions match token-for-token |
| Decryptor crypto module | Entire file matches after an import-path substitution |
| Encryptor and decryptor file walkers | Both files match after import-path substitutions |
| Decryptor entry point | Entire file matches after an import-path substitution |
| Encryptor entry point | Modified main function and a new launch-reporting helper |
We used Prince commit e7ec248b846cf956456e7967519f10f402124264, recorded on 3 July 2024. The original SecDbg/Prince-Ransomware URL credited by EByte returned HTTP 404 during acquisition; the accessible repository preserves a comparison snapshot. Its hosting account should not be treated as an EByte operator identity.
The matches establish source reuse. They do not establish shared operators, victims, infrastructure or keys. They also do not make the builds interchangeable: EByte's encryptor declares Go 1.23.3 and x/crypto v0.32.0, while the Prince snapshot declares Go 1.22.3 and x/crypto v0.24.0. EByte's decryptor retains the older crypto dependency. Identical function text is one part of a program's behaviour; build dependencies and configuration still matter.

Figure 2. REMnux terminal — static comparison results for EByte and the pinned Prince snapshot. The 12-of-13 result covers shared functions in the selected implementation files, not the percentage of the entire kit copied from Prince. The new sendLockerID helper is excluded from that denominator.
What runs on the endpoint
EByte's encryptor checks drive letters A:\ through Z:\ and walks the accessible roots. There is no target-path command-line option in the supplied source. A mapped network drive could therefore be reached through its letter, but the code contains no separate UNC share discovery or share-exploitation routine.
The walker applies case-insensitive exclusions before starting a goroutine for each selected file. The excluded extensions include .sys, .exe, .dll, .com, .scr, .bat, .vbs, .ps1, .lnk, .inf, .reg, .msi, .ini and .EByteLocker, alongside system, program and development directory names.
There is no visible worker-pool limit. Each encryption operation reads the whole file and allocates additional buffers. Although the code uses a 64 KiB read buffer, it does not keep total memory use bounded to that size. Large files and many concurrent file operations could put pressure on memory; we did not execute the kit to measure that behaviour.
The walker adds .EByteLocker to filenames and writes Decryption Instructions.txt in directories. The wallpaper routine downloads https://i.imgur.com/zQ1ei8j.png to %TEMP%/Wallpaper.png and invokes hidden PowerShell to change the victim’s desktop background. The image points users to their decryption instruction file and also links to a GitHub repository named EvilBytecode.
![Figure 3. EByte Locker artwork found at https://i.imgur[.]com/zQ1ei8j[.]png. It directs users to Decryption Instructions.txt and displays a GitHub account reference. This is an image supplied for the report, not a capture of a compromised desktop; it has not been hash-matched to the source-configured wallpaper URL.](/_next/static/media/figure-03-ebyte-locker-artwork.3jr4n98t1tev0.png)
Figure 3. EByte Locker artwork found at https://i.imgur[.]com/zQ1ei8j[.]png. It directs users to Decryption Instructions.txt and displays a GitHub account reference. This is an image supplied for the report, not a capture of a compromised desktop; it has not been hash-matched to the source-configured wallpaper URL.
The source contains no screen-locking routine, nor does it contain persistence installation, privilege escalation, service or process killing, shadow-copy deletion, backup deletion, event-log clearing, VM/debugger evasion, self-deletion or file-data uploader. (NOTE: Although this applies to the examined package, it’s entirely possible that a separately built or modified payload may differ here). The encryptor still overwrites original file content, even without those additional destructive features.

Figure 4. Static source view of the REMnux terminal, which includes drive discovery, exclusions and per-file goroutines in its source. The rename follows the encryption call, which matters when interpreting files that carry the EByte suffix.
A panel that records launches
Before traversing drives, sendLockerID sends a JSON object containing locker_id and timestamp to http://localhost:8080/launch. Failure in this helper does not stop the subsequent drive walk. The request does not contain file content, a symmetric key or an ECIES private key.
The endpoint is local to the machine running the encryptor. Calling it an exfiltration endpoint would overstate what the code does, as it is a development configuration in the supplied kit as opposed to evidence of an external command-and-control service.
The panel exposes /dashboard-data, /launch, /graph-data, /mini-graphs-data and /generate-locker on port 8080. Its SQLite schema stores locker identifiers and launch/date statistics but does not store encryption keys. No authentication middleware appears in the supplied route setup, although we did not run the panel or test an exposed deployment.
These additions explain much of EByte's packaging: an inherited locker and decryptor sit behind a generation interface and a small reporting system. The archive does not establish an active affiliate programme, victim count or operational deployment.
One encrypted byte, two clear bytes
For each file, EncryptFile requests a fresh 32-byte key and 24-byte nonce from crypto/rand.Read. The nonce length selects XChaCha20 in the Go ChaCha20 implementation.
The cipher state remains attached to that file. The loop encrypts payload offsets in multiples of three (0, 3, 6 and so on), consuming one keystream byte at each selected position. The intervening two bytes are copied unchanged and consume no keystream. This detail matters to any recovery implementation: applying a conventional continuous stream across the whole body would not reproduce this layout.
The key and nonce are separately wrapped with ECIES under the builder-supplied public key. EByte places both wrapped objects ahead of the transformed body, separated by the two ASCII characters ||:
ECIES(file key) | "||" | ECIES(file nonce) | "||" | file bodyFor a body of length N, the loop transforms ceil(N/3) positions. The other N - ceil(N/3) positions remain unchanged. That can preserve useful fragments for forensic salvage, provided the body is correctly located and intact. It does not preserve a usable copy of every document, archive or database: The missing bytes may contain headers, compressed data or other essential content.

Figure 5. REMnux terminal showing per-file randomness, ECIES wrapping and the intermittent encryption loop. The loop advances by three and copies the other two bytes without consuming additional keystream.
The pinned ecies/go v1.0.1 implementation normally contributes an uncompressed ephemeral public key, a 16-byte AES-GCM nonce and a 16-byte tag to each wrapped object. With EByte's message lengths, that yields nominal objects of 129 and 121 bytes, placing the body at offset 254 after the separators.
That offset is not a safe universal parser rule. The dependency's public-key encoder has a coordinate-padding edge case, so a reader must account for the actual encoding. The wrapper implementation and public-key encoder are the relevant references. These sizes were derived from source, not measured from a victim file.
Where recovery could succeed
The builder creates a new ECIES key pair for each generation. It prints the private and public values to its console, then embeds the public key in EByteLocker-Built.exe and the private key in Decryptor-Built.exe using Go linker variables. The template key variables in the supplied source are empty.
A matching built decryptor or retained builder-console log is therefore the first artifact to look for. The encryptor contains the public key, which cannot by itself unwrap the per-file secrets. Reusing Prince's code does not mean EByte reuses a Prince private key, or that an unrelated decryptor will work.
The inherited decryptor also has a parsing problem. It splits binary file content at the first two occurrences of ||. ECIES objects contain binary data and can contain that same byte sequence. A file can therefore be correctly encrypted but incorrectly split by the actor's reader. A defensive reader should validate candidate boundaries through authenticated ECIES decoding rather than accept the first delimiter match. This is a repair opportunity for recovery when the correct private key is available, as it does not expose that key.

Figure 6. REMnux terminal showing builder key ownership and the decryptor's binary delimiter split. The builder prints the private key and embeds it in the built decryptor. The parser then relies on SplitN over binary content.
There is a second trap for responders: Both walkers can rename a file after a crypto routine returns early on error. Adding .EByteLocker does not prove encryption completed, and removing it does not prove successful decryption. Because of this, responders should make sure to check the file content.
ECIES authenticates the wrapped key and nonce, but the file body has no authentication tag of its own. A successful unwrap therefore does not prove that every recovered body byte is correct. In a controlled validation, we would require the recovered file's exact length and an independently recorded original SHA-256. In a real incident where no original hash is available, responders must document the checks they can perform as well as the remaining uncertainty.
Process memory is another possible source of keys, nonces and original buffers: the source does not explicitly wipe them. Backups, snapshots and retained extents may provide earlier versions. We have not tested those routes against an EByte memory image, disk image or encrypted file. There is no demonstrated keyless decryptor from this review.
What defenders should preserve and hunt for
Preserve the encryptor, any matching decryptor, builder output and console logs before attempting recovery. Keep original encrypted files unchanged and test on copies. The combination of a matching private key, correctly parsed metadata and independent original-file checks should let a recovery tool be evaluated without relying on filenames or readable fragments.
For hunting, correlate file renames to .EByteLocker, repeated creation of Decryption Instructions.txt, and the %TEMP%/Wallpaper.png write with the associated process activity. The wallpaper download and hidden PowerShell invocation provide additional context. These are source-derived hunting leads, not detection rules validated against execution telemetry.
Several strings in the kit need careful handling. localhost:8080 does not identify remote attacker infrastructure and example@airmail.cc is an example placeholder. A shared image-hosting domain is also too broad to serve as a standalone malicious indicator. Use the exact path and surrounding endpoint behaviour.
| Observable | Interpretation |
|---|---|
.EByteLocker | Configured filename suffix; verify whether the body was transformed |
Decryption Instructions.txt | Ransom-note filename |
EByteLocker-Built.exe, Decryptor-Built.exe | Builder output names and recovery acquisition leads |
%TEMP%/Wallpaper.png | Wallpaper destination |
https://i.imgur[.]com/zQ1ei8j[.]png | Source-configured wallpaper URL; not contacted during analysis |
http://localhost:8080/launch | Local launch-reporting endpoint in this configuration |
locker_id, timestamp | Fields in the launch JSON object |
example@airmail.cc | Template contact, not a confirmed operator inbox |
https://t[.]me/ebytelabs | Source-declared channel; ownership not independently established |
https://github[.]com/EvilBytecode | Account reference displayed in the supplied artwork; unverified attribution lead |
Main takeaway
EByte shows how an existing ransomware implementation can be repackaged with new branding and operator-facing tooling. For defenders, the useful link is the shared file format and code behaviour. The recovery priority is equally specific: Find the matching private-key-bearing artifact, then handle the inherited parser and error-reporting defects before trusting recovered output.
Inside the lab-built binaries
To check how the supplied source appears after compilation, we built Windows x86-64 encryptor and decryptor templates with Go 1.23.3 and analysed them in Ghidra 12.2. The source and dependency manifests were unchanged. We used the templates' empty key variables, with no linker-injected key pair, and did not execute either binary.
Ghidra recovered the Go function names and linked source paths. In generateKey at 0x0067e4e0, the decompilation shows a 32-byte allocation followed by crypto/rand.Read. In EncryptFile, the view around 0x0067ea54 shows the ChaCha20 XOR call inside a loop that advances by three, with explicit copies of the two intervening bytes. This corroborates the source's intermittent layout.

Figure 7. Ghidra CodeBrowser and decompiler showing static analysis of the lab-built encryptor. generateKey at 0x0067e4e0 allocates 0x20 bytes and calls crypto/rand.Read. No binary execution occurred.

Figure 8. Ghidra static view of EncryptFile at the XORKeyStream call, 0x0067ea54. The loop advances by three; the assignments at index +1 and +2 preserve the intervening bytes. Decompiled names and types are Ghidra's reconstruction.
The compiled worker also retains the rename-after-encryption sequence. Its call to EncryptFile is followed by suffix construction and os.Rename, without a success return from the encryption routine to gate that rename. In the decryptor, the SplitN operation is lowered to strings.genSplit with a two-byte separator and a maximum of three parts. These views support the error-handling and parser findings above, while the original terminal source views remain useful for reading the intended Go operations.

Figure 9. Ghidra static view of the encryptor's per-file worker, 0x0067f360. EncryptFile is followed by construction of the .EByteLocker name and os.Rename. The suffix itself is not proof of successful encryption.

Figure 10. Ghidra static view of the lab-built decryptor around 0x004fb78f. strings.genSplit separates the binary content into at most three parts before the wrapped fields are decoded. This corroborates the delimiter-based parser, not a demonstrated key-recovery exploit.
The encryptor declares Go 1.23.3; the decryptor declares Go 1.22.3. Both comparison binaries were compiled with Go 1.23.3, targeting Windows/amd64 with CGO disabled and the flags -trimpath -buildvcs=false -ldflags="-H=windowsgui -s -w". The dependencies remained pinned by the supplied manifests. Addresses in these figures refer only to these lab builds and may differ in other builds.
Lab-built encryptor SHA-256:
3ca182e332f65ceaf8e6a56da6fc79b2b8a5a042c4e394dbc2a1b0d30a414d21Lab-built decryptor SHA-256:
b8ec3cffc5e41f7e92a4007ca9565445517e3d2ce932e11e1020b13a3ed5a74aFigures 2 and 4–6 are native REMnux terminal captures of source review and comparison results. Figures 7–10 are native Ghidra CodeBrowser and decompiler captures of the lab-built binaries.
Viewing the panel locally
We rendered the supplied dashboard frontend on localhost with synthetic responses for its three read endpoints. The view displays Total Lockers, Total Launches, Infections Today and a Launches Summary chart. All counts and graph values in this preview are fabricated for illustration; they provide no evidence of actual infections, victim counts or operational deployment.
The original frontend JavaScript and CSS were retained. External library references were replaced with local copies, chart animation was disabled for the still capture, and a visible preview label was added. The Go backend and SQLite database were not started; the mock server rejected all POST requests, including locker generation.

Figure 11. The supplied EByte dashboard frontend rendered locally in Chrome with synthetic data. This is a visual preview of the frontend, not an operator dashboard or compromised-host capture. No locker was generated and no EByte executable was run.
The source also references chat-modal and close-modal elements that are absent from the supplied HTML. These produced a browser error while the dashboard remained visible. The chat icon alone therefore does not establish a working chat feature. The source leaves some frontend dependency versions unpinned; the preview's local dependency versions and source hashes are recorded with the image.
Sources and analysis scope
This article is based on static review of EByte Ransomware.zip, a 24,688-byte archive containing 27 files, including 16 Go source files, dependency manifests and a web frontend. Its SHA-256 is:
01977a6ecf5ed2b06300c53f7ccd52621ec0a81e7e3ee05226bda73c40dc4f27No compiled encryptor, built decryptor, victim ciphertext, operator database or saved key pair accompanied the source package. Source review took place on REMnux. For the follow-up static analysis described above, we compiled the unchanged encryptor and decryptor templates and imported them into Ghidra. We did not execute either binary, run the Go builder or panel backend, inject keys, or contact malware infrastructure. The forum post and locker artwork were supplied separately. The screenshot date is the displayed post date, not an established first-seen date for EByte.
The Prince comparison is pinned to commit e7ec248b846cf956456e7967519f10f402124264. Its encryption module and decryption module provide reproducible reference points. The companion comparison memo retains source hashes, function fingerprints and line references. The comparison is lexical, not a claim of binary equivalence or an exhaustive search of all ransomware families.
YARA rules for triage
The following rules identify the Windows encryptor and decryptor separately using EByte-specific Go function names and the configured suffix. Neither rule depends on an exact sample hash. For the decryptor, reserve a matching artifact for recovery analysis rather than treating the match alone as proof of malicious activity.
import "pe"
rule EByte_Go_Windows_Encryptor : ransomware ebyte encryptor
{
meta:
author = "Tammy Harper / Ransom-ISAC"
date = "2026-10-27"
description = "EByte Windows encryptor source-lineage markers"
scope = "Static PE files; validated on analyst-built templates"
reference = "EByte Ransomware: Prince Code Behind a New Locker"
version = "1.0"
strings:
$suffix = ".EByteLocker" ascii
$encrypt = "EByte-Rware/encryption.EncryptFile" ascii
$walker = "EByte-Rware/filewalker.EncryptDirectory" ascii
$key = "EByte-Rware/encryption.generateKey" ascii
$nonce = "EByte-Rware/encryption.generateNonce" ascii
condition:
uint16(0) == 0x5a4d and pe.is_pe and
$suffix and $encrypt and $walker and ($key or $nonce)
}
rule EByte_Go_Windows_Decryptor : ebyte decryptor recovery_artifact
{
meta:
author = "Tammy Harper / Ransom-ISAC"
date = "2026-10-27"
description = "EByte matching-decryptor acquisition lead"
scope = "Identify and preserve; not proof of malicious execution"
reference = "EByte Ransomware: Prince Code Behind a New Locker"
version = "1.0"
strings:
$suffix = ".EByteLocker" ascii
$decrypt = "EByte-Rware-Decryptor/decryption.DecryptFile" ascii
$walker = "EByte-Rware-Decryptor/iterator.DecryptDirectory" ascii
condition:
uint16(0) == 0x5a4d and pe.is_pe and all of them
}We compiled and tested these rules with YARA 4.5.0 without executing any target binary. They matched the appropriate encryptor or decryptor in all four lab builds: Each template compiled with Go 1.23.3 and Go 1.25.4. Each positive matched only its intended rule. The Ghidra figures use the Go 1.23.3 builds.
All six negative controls were refused: a benign Go Windows executable containing crypto/rand and .EByteLocker; two copies of that benign PE with only one EByte function marker appended; plain text containing the rule markers; an invalid MZ-header file containing those markers; and an empty file. These controls exercise the string conjunction and PE checks. They do not establish a production false-positive rate or replace testing against a large cleanware corpus.
The rules cover the supplied source lineage when its package/function strings and suffix remain present. Packed, obfuscated or renamed builds may not match. A match establishes matching static markers, not execution, attribution, a matching private key or successful decryption. The builder, panel, Linux variants and encrypted victim files are outside this validation.
Facing a cyber security incident?
If you believe your organisation has been compromised by EByte or a related actor, please reach out to Ransom-ISAC.
Found this article helpful?
Share it with your network
