Author Topic: "Hello world" with a very simple encoding  (Read 778 times)

Offline andyz74

  • Jr. Member
  • *
  • Posts: 35
"Hello world" with a very simple encoding
« on: April 16, 2025, 09:23:11 AM »
Hello world! ;-)

Just out of curiosity I have tried this :  a simple Hello-World-program, step for step with ean easy encoding of code and the message.  This is none-professional stuff, but it works (for me // Debian Linux, 64-bit) .  The main thing is for sure the definition of the code-section as read, write and executable. We all know, this is evil sin, not to be done, but there seems to be no other way.
So, for testing purposes, have a look at the original program we will start with :

Code: [Select]
; 64-bit "Hello World!" uncodiert... 1 von 4
; by myself
; nasm -f elf64 hello-cod01.asm
; ld -s -o hello-cod01 hello-cod01.o


[bits 64]

global _start ; global entry point export for ld

section .mycode alloc exec write

_start:

jmp decode
db 90h
db 90h
db 90h
db 90h

sss:
mov eax,1
mov edi,1
mov rsi,msg
mov edx,msg_size
syscall

mov eax,60
xor rdi, rdi
syscall

msg db 'Hello world!',0xA
msg_size equ $-msg

decode:
jmp sss
db 90h
db 90h
db 90h
db 90h

As easy, as it looks. the db 90h are "nop"-commands, mostly for being able to find our relevant code inside the debugger or hex-dump.
After compiling and linking, the program should work, and we can do a "hexdump -C [progname]" to get the opcodes.

Second part is, changing our program-code to opcodes. (For now, really only the code, not the message) We get the following :

Code: [Select]
; 64-bit "Hello World!" uncodiert, aber als opcodes... 2 von 4
; by myself
; nasm -f elf64 hello-cod02.asm
; ld -s -o hello-cod02 hello-cod02.o


[bits 64]

global _start ; global entry point export for ld

section .mycode exec write

_start:


jmp decode
db 90h
db 90h
db 90h
db 90h

sss:
db 0b8h
db 01h
db 00h
db 00h
db 00h
db 0bfh
db 01h
db 00h
db 00h
db 00h
db 48h
db 0beh
db 2bh
db 10h
db 40h
db 00h
db 00h
db 00h
db 00h
db 00h
db 0bah
db 0dh
db 00h
db 00h
db 00h
db 0fh
db 05h
db 0b8h
db 3ch
db 00h
db 00h
db 00h
db 48h
db 31h
db 0ffh
db 0fh
db 05h


msg db 'Hello world!',0xA
msg_size: equ $-msg


decode:
jmp sss
db 90h
db 90h
db 90h
db 90h


After compiling and linking, it should work as the first. So we can try a little very simple encoding (add a fix number to each opcode by hand and tell the "decoder" to subtract this, before jumping and executing the original code.
Let's try :

Code: [Select]
; 64-bit "Hello World!" codiert (nur Programm, nicht Message), als opcodes + 18h... 3 von 4
; by myself
; nasm -f elf64 hello-cod03.asm
; ld -s -o hello-cod03 hello-cod03.o


[bits 64]

global _start ; global entry point export for ld


section .mycode alloc exec write
_start:


jmp decode
db 90h
db 90h
db 90h
db 90h

sss:
zeugs db 0b8h + 18h
db 01h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 0bfh + 18h
db 01h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 48h + 18h
db 0beh + 18h
db 2bh + 18h
db 10h + 18h
db 40h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 0bah + 18h
db 0dh + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 0fh + 18h
db 05h + 18h
db 0b8h + 18h
db 3ch + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 48h + 18h
db 31h + 18h
db 0ffh + 18h
db 0fh + 18h
db 05h + 18h

msg db 'Hello world!',0xA
msg_size: equ $-msg


decode:
xor rcx, rcx
dec2:
sub byte [zeugs+rcx],18h
inc rcx
cmp rcx, 37
jne dec2
jmp sss
db 90h
db 90h
db 90h

You see, first line jumps to decoder , then decoding, then jump back to original start.

Now, finally encoding the message too.

Code: [Select]
; 64-bit "Hello World!" alles codiert, auch message, opcodes + 18h... 4 von 4
; by myself
; nasm -f elf64 hello-cod04.asm
; ld -s -o hello-cod04 hello-cod04.o


[bits 64]

global _start ; global entry point export for ld


section .mycode alloc exec write
_start:


jmp decode
db 90h
db 90h
db 90h
db 90h

sss:
zeugs db 0b8h + 18h
db 01h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 0bfh + 18h
db 01h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 48h + 18h
db 0beh + 18h
db 2bh + 18h
db 10h + 18h
db 40h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 0bah + 18h
db 0dh + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 0fh + 18h
db 05h + 18h
db 0b8h + 18h
db 3ch + 18h
db 00h + 18h
db 00h + 18h
db 00h + 18h
db 48h + 18h
db 31h + 18h
db 0ffh + 18h
db 0fh + 18h
db 05h + 18h

msg db 'H' + 18h
db 'e' + 18h
db 'l' + 18h
db 'l' + 18h
db 'o' + 18h
db ' ' + 18h
db 'w' + 18h
db 'o' + 18h
db 'r' + 18h
db 'l' + 18h
db 'd' + 18h
db '!' + 18h
db 0xA + 18h
msg_size: equ $-msg


decode:
xor rcx, rcx
dec2:
sub byte [zeugs+rcx],18h
inc rcx
cmp rcx, 50
jne dec2
jmp sss
db 90h
db 90h
db 90h


For me, all worked, hexdump shows no more plain text, and the original opcodes are others too. Program ran on my computer.

...and remember, this is none-professional stuff, just for fun and try. :-)

Offline marknoble

  • Jr. Member
  • *
  • Posts: 3
Re: "Hello world" with a very simple encoding
« Reply #1 on: April 25, 2025, 03:00:24 PM »
Nice work messing around with this! I’ve dabbled in some assembly too, and it’s always a trip to see how low-level you can go. Your encoding trick with the +18h offset is a cool way to obfuscate things, and I like how you kept it simple but effective. I tried something similar a while back on a 32-bit setup, just playing with XOR encoding for the code section, and it was a pain to debug when I messed up the decoding loop, props for getting it running smoothly! One thing I’d maybe watch out for is that hardcoding the decode length (like 50 bytes) could bite you if you tweak the code later. Maybe a label-based size calc could save some headaches? Anyway, fun stuff, thanks for sharing!

Offline andyz74

  • Jr. Member
  • *
  • Posts: 35
Re: "Hello world" with a very simple encoding
« Reply #2 on: April 25, 2025, 05:48:11 PM »
A label bassed calculation of the opcodes to decode would really have been convinient, that's for sure. And easy to code too. But to be honest, I'm using micro as editor for programming, and there are shown the line numbers at the left side, so the substraction was really easy too...   ;)