Skip to content

v2.0.2

Latest

Choose a tag to compare

@EgeBalci EgeBalci released this 01 May 22:55
· 2 commits to master since this release
c97adb5

Changelogs

Encoding & Obfuscation Fixes

  • Schema Size & Alignment Issue:
    • Bug: The schema size calculation incorrectly divided the payload length by the architecture size (e.g., 8 bytes for x64). However, SchemaCipher always operates in 4-byte (32-bit) chunks regardless of architecture. If a payload wasn't perfectly aligned to a 4-byte multiple, the decoding loop would experience out-of-bounds reads/writes or partial decoding.
    • Fix: Hardcoded the divisor to 4 for all architectures and added padding (0x90 NOPs) to ensure the payload perfectly aligns with the required schema boundaries.
  • ADD/SUB Cipher Arithmetic:
    • Bug: The ADD/SUB ciphers used % 0xFFFFFFFF to simulate 32-bit wrapping. This is mathematically incorrect because the max value of uint32 is 0xFFFFFFFF, so val % 0xFFFFFFFF evaluates to 0 instead of wrapping correctly.
    • Fix: Removed the modulo completely. In Go, uint32 natively wraps around, so standard addition and subtraction inherently provide the correct behavior.
  • Unsafe Garbage Instructions (JMP 2):
    • Bug: JMP 2 was included in the SafeGarbageInstructions list. This is a relative jump that skips exactly two bytes. If it executes in the middle of a larger instruction block or without two bytes of trailing instructions, it corrupts the instruction pointer and crashes the payload.
    • Fix: Removed JMP 2 from the safe instructions list to prevent execution crashes.
  • Obfuscation Limit Ignored:
    • Bug: The encoder previously continued to generate garbage instructions even if the obfuscation limit was explicitly set to 0.
    • Fix: Added an explicit check (if encoder.ObfuscationLimit <= 0) to bypass garbage assembly entirely when disabled.

Register Selection & Stack Management

  • Incorrect Register Definitions:
    • Bug: The 32-bit definitions for ESI and EDI incorrectly assigned their 8-bit Low representations to AL and BL. This meant if the encoder substituted an 8-bit instruction targeting ESI, it would clobber AL/BL instead. Additionally, the 64-bit RDI register incorrectly had its High representation mapped to DX (which belongs to RDX).
    • Fix: Removed the 8-bit Low representations for ESI and EDI, and corrected RDI's High mapping to DI.
  • Stack Pointer (RSP) Clobbering:
    • Bug: The x64 register save/restore stubs pushed and popped the RSP register (PUSH RSP / POP RSP). Pushing and popping the stack pointer manually inside a decoder stub breaks stack alignment and offset calculations, resulting in immediate segmentation faults.
    • Fix: Removed RSP from the save/restore prefixes and suffixes.
  • Random Register Selection Panic/Errors:
    • Bug: The GetRandomRegister logic blindly picked a random register and asked for a specific size representation (like .Low or .High). Since some registers don't have these representations (like ESI 8-bit), it returned empty strings, causing the Keystone assembler to fail.
    • Fix: Rewrote the random selection logic to filter and build an array of only valid register representations for the requested size before picking one randomly.

CLI & Core Logic

  • Broken Payload Selection Constraints:
    • Bug: In the main CLI loop, the condition to validate a generated payload used an || (OR) operator for ASCII and bad-byte checks. This meant a payload would be accepted if it was ASCII (but contained bad bytes) OR had no bad bytes (but failed the ASCII constraint).
    • Fix: Refactored the checks to strictly enforce && (AND), ensuring payloads pass both constraints simultaneously before being saved. Option application was also moved inside the loop.
  • File Overwrite Truncation:
    • Bug: When saving a payload over an existing file, the file wasn't truncated. If the new payload was smaller than the old one, the generated file would contain trailing garbage data. The file descriptor was also never explicitly closed.
    • Fix: Added the os.O_TRUNC flag when opening the output file and added defer out.Close().
  • Example Import Casing:
    • Bug: encode_x64_binary.go used a lowercase import path github.com/egebalci/sgn/pkg, which fails to compile on strict module resolution systems because the actual repository is EgeBalci.
    • Fix: Corrected the import path to github.com/EgeBalci/sgn/pkg.

Performance & Testing

  • String Search Optimization:
    • Optimization: Replaced a manual array loop and bytes.Contains check in the ContainsBytes helper with the much faster bytes.IndexByte.
  • Execution Stress Test:
    • Testing: Added TestIntegrationExecution on Windows, which generates, allocates, and executes dummy payloads 1000 times to continuously verify that none of the encoder/decoder logic introduces crashes.

Many thanks to @Drewsif

cf6209e4bcdd99938bafdcc8e99988fd69d0b7ef7bf9898123edce89b63fb903  sgn_linux_amd64_2.0.2.zip
de8418cc4cb087baa8df80677cfcd2d29f107a1d5f95b6009ca31f73b0680be3  sgn_windows_386_2.0.2.zip
ebb5129979c8f71af1940e92e53ceacd5343891d57bc4ead47dc4a10996ea5a9  sgn_windows_amd64_2.0.2.zip