Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Self modifying C code.

Posted on 1999-06-30
Medium Priority
Last Modified: 2011-08-18
The technique used to be big to prevent assembly programs being hacked.
Can/Has this been done for C?
Just a link or two :)
Question by:Lab_Rat
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
  • +7

Expert Comment

ID: 1263091

Author Comment

ID: 1263092
Give it a bit longer, and if noone else surfs by, post an answer.
LVL 27

Expert Comment

ID: 1263093
I have only ever done this in assembler. The ICL 1301 machine had no modifier so that indexing an array consisted of fishing out the accessor instruction, adding the array offset to the address part, sticking it back into the code and falling into it to get the damm thing executed. And that of couse in 64 words of page memory because we then have to fetch the next code page from drum otherwise we wrap round and start fromn the beginning again. All good clean fun and very warm in winter with this 80K Watt machine.
   An interesting anecdote which I might be permitted to add here is that the Programming Manual for the built-in Line Printer explicitly warns you about print sequences which could make the printer burst into flames. As the paper feed drum went round you had to raise and lower a pawl on a ratchet. The timing was critical to get a certain amount of paper through. One line feed or a vertical tab or whatever.  If you raised and lowered the pawl too fast the electromagnet would get hot which in turn could alight the paper and eventually the printer would catch fire.
   We ought to start a thread in the lounge for this machine. It was a marvel of complexity and intricacy only for those who were, for example, undaunted at the task of doing the Times Crossword during the tea break (as a relaxing diversion).
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

LVL 13

Expert Comment

ID: 1263094
In Win32 this has become harder. You are not allowed to write to your own code segment always..
You use to have programs like lzexe who compressed executables as executables, so they use what you said.
The problem with this code is the jump tables and scheduling.

Expert Comment

ID: 1263095
I once read how to write to a code segment in the book Undocumented Windows.  There's an undocumented system call PrestoChangeSelector that converts a read-only code segment to a writeable data segment and back again by toggling a bit in the selector.

I'm afriad I don't have the book with me at work right now, it's at home, so I can't provide the details until tomorrow.

Expert Comment

ID: 1263096
This is something I got out of a book on C Techniques.  If I remember, I'll try to check the full name of it when I get home.  2 files -> modify.h and modify.c
Hope this helps.

/*MODIFY.H - Header file for MODIFY.C.*/

struct exeheader
  unsigned id;            /* EXE file id. */
  unsigned bytemod;      /* Load module image size mod 512. */
  unsigned pages;            /* File size (including header) div 512. */
  unsigned reloc_items;      /* Number of relocation table items. */
  unsigned size;            /* Header size in 16-byte paragraphs. */
  unsigned minparagraphs;  /* Min number of paragraphs above program. */
  unsigned maxparagraphs;  /* Max number of paragraphs above program. */
  unsigned stackseg;      /* Displacement of stack segment. */
  unsigned spreg;            /* Initial SP register value. */
  int checksum;            /* Negative checksum (not used). */
  unsigned ipreg;            /* Initial IP register value. */
  unsigned codeseg;      /* Displacement of code segment. */
  unsigned first_reloc;      /* First relocation item. */
  unsigned ovln;            /* Overlay number. */

#define EXEH_SIZE  sizeof(struct exeheader)

/* EXE file signature. */
#define EXE_ID  0x5A4D

#if !defined(TRUE)
#define FALSE  0
#define TRUE   (!FALSE)

/* Function prototypes. */
int exemodify(const char *progname, int keepdt, ...);

/*****  END .H FILE *****/

MODIFY.C - Modify global variables in EXE or COM file.
For Turbo C versions 2.0 and above.  This code is public domain.

#include <dir.h>
#include <dos.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#include <modify.h>

int exemodify(char *progname, int keepdt, [void *data1,
     unsigned n1, [void *data2, unsigned n2, [ ... ]]]

int exemodify(const char *progname, int keepdt, ...)
char _progname[MAXPATH];      /* Program name. */
char ext[MAXEXT];                  /* Program extension. */
struct exeheader exe;            /* EXE file header. */
char *pathptr;                  /* Pointer to program path. */
int progfile;                  /* Program file handle. */
int iscomfile;                  /* TRUE if program is a COM file. */
long filelen;                  /* Program file length. */
struct ftime dtstamp;            /* Program date/time stamp. */
va_list datalist;            /* List of data items to be written to file. */
char *data;                  /* Pointer to current data item. */
unsigned n;                  /* Size of current data item. */
long seeklen;                  /* Seek length into program file. */
int retcode;                  /* Function return code. */

if (_osmajor < 3)
  /* Search DOS PATH for program. */
  if ((pathptr = searchpath(progname)) != NULL)
    strcpy(_progname, pathptr);
    _progname[0] = 0;
  /* Program name is 0th parameter in DOS versions 3.0 and up. */
  strcpy(_progname, _argv[0]);

/* Assume error. */
retcode = -1;

if (_progname[0])
  if ((progfile = open(_progname, O_RDWR | O_BINARY)) != -1)
    iscomfile = fnsplit(_progname, NULL, NULL, NULL, ext) & EXTENSION && !strnicmp(ext, ".COM", 4);

    if (!iscomfile && (read(progfile, &exe, EXEH_SIZE) != EXEH_SIZE || != EXE_ID))
      /* File is not a COM file and does not have a valid EXE file header. */
      errno = EINVFMT;
      /* Cannot write beyond end of file. */
      filelen = filelength(progfile);

      if (keepdt)
      /* Save date/time stamp. */
      getftime(progfile, &dtstamp);

      retcode = 0;
      va_start(datalist, keepdt);

      while ((data = va_arg(datalist, char *)) != NULL)
      if (iscomfile)
        /* Seek length is data offset - PSP size. */
        seeklen = FP_OFF(data) - 256;
        /* Seek length is (data segment - (PSP + PSP size) + EXE size) * 16 + data offset. */
        seeklen = ((unsigned long)(FP_SEG(data) - (_psp + 16) + exe.size) << 4) + (unsigned long)FP_OFF(data);

      n = va_arg(datalist, unsigned);

      if (seeklen + n <= filelen && lseek(progfile, seeklen, SEEK_SET) != -1L && write(progfile, data, n) == n)
        /* Seek and write was successful. */


      if (keepdt)
      /* Restore date/time stamp. */
      setftime(progfile, &dtstamp);

  /* File not found. */
  errno = ENOENT;

return (retcode);

LVL 86

Expert Comment

ID: 1263097

>>In Win32 this has become harder. You are not allowed to
>>write to your own code segment always..

This will do it ;-)

VirtualProtect( ..., PAGE_EXECUTE_READWRITE, ...);

LVL 13

Expert Comment

ID: 1263098
Doing something is harder than doing nothing...
You have to agree with me. It's a lot harder to make
LZEXE for NT than it is to make LZEXE for Dos.

Accepted Solution

jhurst earned 0 total points
ID: 1263099
You CAN still write assembly code for Win32, you can also include assembly code with most C compilers.  It is relatively easy, as you know to write assembly code that self-modifies.  The problem with C is that you rarely know at source-coding time what the generated code would be, so you would be asiming at a moving target.  Also, it would change if you re-compiled with different options or a different compiler.

I have seen and used code that does this for Win32, it uses assembly language insertes into the C source.  Horrible, but it does work.

With many REAL operating systems there would be a further problem that the code would be executed from a segment that is marked read-only and so self modification would be a further problem.
LVL 27

Expert Comment

ID: 1263100
What, no more anecdotes? I was looking forward to old hands dithering on about what it was like in the old days when you HAD to do this sort of thing.

Expert Comment

ID: 1263101
Self-modifying code is a pain in the arse.  I had to do it on the Commodore 64 a few times...there are only three 8-bit registers for you to use, so sometime the only way to get things done fast was to modify operands rather than use the turtle-on-ritalin indexed indirect mode.

Author Comment

ID: 1263102
BigRat, I'm too younf to be using anecdotes, give me a few more years and I'll be waffling on about the Sinclair ZX Spectrum 128k+2a (Revision 2), now THERE was a computer that you could spill coke on and it.........

Expert Comment

ID: 1263103
Self modifying code is easy.  Just use LISP! :)
(dodges C-coder launched rotten fruits)

Author Comment

ID: 1263104
Thanks everyone,
but it's time to lock up and go home.

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode ( They will have you believe that Unicode requires you to use…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.

664 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question