Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This is a good list! Another fun quirk: because x86 is a register-memory architecture and allows all kinds of variants of reg/mem operand encodings, there are a handful of equivalent encodings with exactly the same lengths (and just slightly different ModR/M bytes). You can take advantage of this to do software fingerprinting or, in my case, steganography without changing an executable’s size or semantics[1].

[1]: https://github.com/woodruffw/steg86



The (in)famous A86/A386 assembler claimed to use this technique to identify code produced with it. As far as I know, it was just a simple inversion of reg-reg ModRMs depending on the register values being used, although I didn't test it too exhaustively.


Speaking of things with the same names, what happened to Linux a386 and what the heck was it even? I can't find a link nowadays, but it was something like User Mode Linux, but not really.



Used the exact same trick when researching dumb ways to break AV signatures at uni :)

You can also abuse the displacement math with eiz:

  ff 34 24 push   DWORD PTR [esp]
  ff 34 e4 push   DWORD PTR [esp+eiz*8]
Or some useless prefixes may work:

  80 c0 53 add    al,0x53
  36 04 53 ss add al,0x53


This is the first time I learned about eiz. Cool trick!

What’s eiz: https://stackoverflow.com/a/2553556/3125367


You won't find "eiz" in any Intel manual, and NASM doesn't recognize it either. x86 has no zero register¹.

This appears to be some GNU-specific syntax meaning "encode SIB byte with no index register". The only case where this would be required by the hardware is when using ESP/RSP as a base register, and every assembler should produce the correct encoding for that if you simply write [ESP].

So using "eiz" on GAS lets you control what is put into the (unused) scale field. One might call that a feature, but it is a meaningless encoding detail similar to which variant of "register to register" opcodes is emitted, something that I don't think any assembler gives you control over.

¹ except maybe on the microarchitectural level, but that isn't visible to the programmer


If I remember correctly there are also tricks like

  lea rax, [eiz+rbx*4]
instead of

  lea rax, [rbx*4]
because the latter will produce an heavier binary by being interpreted as

  lea rax, [00000000h+rbx*4]


The article itself exposes some encoding redundancy too: "[...] the count is masked against 1FH, essentially using only the lowest five bits".

So each rotation instruction is 3 bits free for out-of-band information.


Would love to learn more and help with this project if you need extra work done


It’s relatively feature complete, but there are some ideas for increasing the steganographic capacity listed in the README and issues! In particular, we could use the flexibility of the multi-byte NOP sequences to hide some more information.


What are some interesting use-cases for information hiding in the binaries?


Embed your customer's serial number in the binary at download time. When the file ends up on The Pirate Bay, send them a bill.


This is a huge issue in the cloud computing space.

“Golden Images” are often used to try to counter exploits hidden in the binaries of cloud images used by containers, etc


Why would I want to hide a message beside a program?


I think this has mostly curiosity/show off value. Encoding messages into executable binaries without changing their running behavior is kinda cool.


It gives you room to try to cause a hash collision. Could be used as a vector if a broken checksum is used.


Maybe to be able to trace individual copies of a piece of software back to a licensee.


It’s primarily a cute trick.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: