[HN Gopher] Writing a Self-Mutating x86_64 C Program (2013)
       ___________________________________________________________________
        
       Writing a Self-Mutating x86_64 C Program (2013)
        
       Author : kepler471
       Score  : 62 points
       Date   : 2025-05-25 17:00 UTC (6 hours ago)
        
 (HTM) web link (ephemeral.cx)
 (TXT) w3m dump (ephemeral.cx)
        
       | belter wrote:
       | I guess in OpenBSD because of W ^ X this would not work?
        
         | akdas wrote:
         | I was thinking the same thing. Usually, you'd want to write the
         | new code to a page that you mark as read and write, then switch
         | that page to read and execute. This becomes tricky if the code
         | that's doing the modifying is in the same page as the code
         | being modified.
        
         | timewizard wrote:
         | The way it's coded it wouldn't; however, you can map the same
         | shared memory twice. Once with R|W and a second time with R|X.
         | Then you can write into one region and execute out of it's
         | mirrored mapping.
        
         | rkeene2 wrote:
         | In Linux it also needs mprotect() to change the permissions on
         | the page so it can write it. The OpenBSD man page[0] indicate
         | that it supports this as well, though notes that not all
         | implementations are guaranteed to allow it, but my guess is it
         | would generally work.
         | 
         | [0] https://man.openbsd.org/mprotect.2
        
           | Retr0id wrote:
           | It's not _required_ on linux, if the ELF headers are set up
           | such that the page is mapped rwx to begin with. (but rwx
           | mappings are generally frowned upon from a security
           | perspective)
        
         | mananaysiempre wrote:
         | Not as is, but I think OpenBSD permits you to map the same
         | memory twice, once as W and once as X (which would be a
         | reasonable hoop to jump through for JITs etc., except there's
         | no portable way to do it). ARM64 MacOS doesn't even permit
         | that, and you need to use OS-specific incantations[1] that
         | essentially prohibit two JITs coexisting in the same process.
         | 
         | [1] https://developer.apple.com/documentation/apple-
         | silicon/port...
        
       | alcover wrote:
       | I often think this could maybe allow fantastic runtime
       | optimisations. I realise this would be hardly debuggable but
       | still..
        
         | Retr0id wrote:
         | It already does, in the form of JIT compilation.
        
           | alcover wrote:
           | OK but I meant in already native code, like in a C program -
           | no bytecode.
        
             | Retr0id wrote:
             | I mean that, too.
        
             | connicpu wrote:
             | LuaJIT has a wonderful dynamic code generation system in
             | the form of the DynASM[1] library. You can use it
             | separately from LuaJIT for dynamic runtime code generation
             | to create machine code optimized for a particular problem.
             | 
             | [1]: https://luajit.org/dynasm.html
        
         | vbezhenar wrote:
         | I used GNU lightning library once for such optimisation. I
         | think it was ICFPC 2006 task. I had to write an interpreter for
         | virtual machine. Naive approach worked but was slow, so I
         | decided to speed it up a bit using JIT. It wasn't a 100% JIT, I
         | think I just implemented it for loops but it was enough to
         | tremendously speed it up.
        
         | userbinator wrote:
         | Programs from the 80s-90s are likely to have such tricks. I
         | have done something similar to "hardcode" semi-constants like
         | frame sizes and quantisers in critical loops related to audio
         | and video decompression, and the performance gain is indeed
         | measurable.
        
           | alcover wrote:
           | > "hardcode" semi-constants
           | 
           | You mean you somehow avoided a _load_. But what if the
           | constant was already placed in a register ? Also how could
           | you pinpoint the reference to your constant in the machine
           | code ? I 'm quite profane about all this.
        
             | ronsor wrote:
             | > Also how could you pinpoint the reference to your
             | constant in the machine code?
             | 
             | Not OP, but often one uses an easily identifiable dummy
             | pattern like 0xC0DECA57 or 0xDEADBEEF which can be
             | substituted without also messing up the machine code.
        
               | mananaysiempre wrote:
               | If you're willing to parse object files (a much easier
               | proposition for ELF than for just about anything else),
               | another option is to have the source code mention the
               | constants as addresses of external symbols, then parse
               | the relocations in the compiled object. Unfortunately,
               | I've been unable to figure out a reliable recipe to get a
               | C compiler to emit absolute relocations in position-
               | independent code, even after restricting myself to GCC
               | and Clang for x86 Linux; in some configurations it works
               | and in others you (rather pointlessly) get a PC-relative
               | one followed by an add.
        
             | userbinator wrote:
             | All the registers were already taken.
             | 
             | You use a label.
        
       | oxcabe wrote:
       | It's impressive how well laid out the content in this article is.
       | The spacing, tables, and code segments all look pristine to me,
       | which is especially helpful given how dense and technical the
       | content is.
        
       | ivanjermakov wrote:
       | I had a great experience writing self modified programs is a
       | single instruction programming game SIC-1:
       | https://store.steampowered.com/app/2124440/SIC1/
        
       ___________________________________________________________________
       (page generated 2025-05-25 23:00 UTC)