FazBrowse Wikipedia Viewer | Main Page |
Search Wikipedia:
|
Viewing: https://en.wikipedia.org/wiki/Self-modifying_code

Self-modifying code

Contents
    Specialization
    Use as camouflage
    Self-referential machine-learning systems
    Operating systems
Interaction of cache and self-modifying code
References
Further reading

In computer science, self-modifying code (SMC or SMoC) is code that alters its own instructions while it is executing – usually to reduce the instruction path length and improve performance or simply to reduce otherwise repetitively similar code, thus simplifying maintenance. The term is usually only applied to code where the self-modification is intentional, not in situations where code accidentally modifies itself due to an error such as a buffer overflow.

Self-modifying code can involve overwriting existing instructions or generating new code at run time and transferring control to that code.

Self-modification can be used as an alternative to the method of "flag setting" and conditional program branching, used primarily to reduce the number of times a condition needs to be tested.

The method is frequently used for conditionally invoking test/debugging code without requiring additional computational overhead for every input/output cycle.

The modifications may be performed:

In either case, the modifications may be performed directly to the machine code instructions themselves, by overlaying new instructions over the existing ones (for example, altering a compare and branch to an unconditional branch or alternatively a NOP).

In the IBM System/360 architecture and its successors up to z/Architecture, an EXECUTE (EX) instruction logically overlays the second byte of its target instruction with the low-order 8 bits of register 1. This provides the effect of self-modification, although the actual instruction in storage is not altered.

N and the frequency of state changing.

Specialization

edit

Suppose a set of statistics such as average, extrema, location of extrema, standard deviation, etc. are to be calculated for some large data set. In a general situation, there may be an option of associating weights with the data, so each xi is associated with a wi, and rather than test for the presence of weights at every index value, there could be two versions of the calculation, one for use with weights and one not, with one test at the start. Now consider a further option, that each value may have associated with it a Boolean to signify whether that value is to be skipped or not. This could be handled by producing four batches of code, one for each permutation and code bloat results. Alternatively, the weight and the skip arrays could be merged into a temporary array (with zero weights for values to be skipped), at the cost of processing and still there is bloat. However, with code modification, to the template for calculating the statistics could be added as appropriate the code for skipping unwanted values, and for applying weights. There would be no repeated testing of the options and the data array would be accessed once, as also would the weight and skip arrays, if involved.

Use as camouflage

edit

Self-modifying code is more complex to analyze than standard code and can therefore be used as a protection against reverse engineering and software cracking. Self-modifying code was used to hide copy-protection instructions in 1980s disk-based programs for systems such as IBM PC compatibles and Apple II. For example, on an IBM PC, the floppy disk drive access instruction int 0x13 would not appear in the executable program's image but would be written into the executable's memory image after the program started executing.

Self-modifying code is also sometimes used by programs that do not want to reveal their presence, such as computer viruses and some shellcodes. Viruses and shellcodes that use self-modifying code mostly do this in combination with polymorphic code. Modifying a piece of running code is also used in certain attacks, such as buffer overflows.

Self-referential machine-learning systems

edit

Traditional machine-learning systems have a fixed, pre-programmed learning algorithm to adjust their parameters. However, since the 1980s Jürgen Schmidhuber has published several self-modifying systems with the ability to change their own learning algorithm. They avoid the danger of catastrophic self-rewrites by making sure that self-modifications will survive only if they are useful according to a user-given fitness, error or reward function.

Operating systems

edit

The Linux kernel notably makes wide use of self-modifying code; it does so to be able to distribute a single binary image for each major architecture (e.g. IA-32, x86-64, 32-bit ARM, ARM64...) while adapting the kernel code in memory during boot depending on the specific CPU model detected, e.g. to be able to take advantage of new CPU instructions or to work around hardware bugs. To a lesser extent, the DR-DOS kernel also optimizes speed-critical sections of itself at loadtime depending on the underlying processor generation.

Regardless, at a meta-level, programs can still modify their own behavior by changing data stored elsewhere (see metaprogramming) or via use of polymorphism.

Massalin's Synthesis kerneledit

The Synthesis kernel presented in Alexia Massalin's Ph.D. thesis is a tiny Unix kernel that takes a structured, or even object-oriented, approach to self-modifying code, where code is created for individual quajects, like filehandles. Generating code for specific tasks allows the Synthesis kernel to (as a JIT interpreter might) apply a number of optimizations such as constant folding or common subexpression elimination.

The Synthesis kernel was very fast, but was written entirely in assembly. The resulting lack of portability has prevented Massalin's optimization ideas from being adopted by any production kernel. However, the structure of the techniques suggests that they could be captured by a higher-level language, albeit one more complex than existing mid-level languages. Such a language and compiler could allow development of faster operating systems and applications.

Paul Haeberli and Bruce Karsh have objected to the "marginalization" of self-modifying code, and optimization in general, in favor of reduced development costs.

Interaction of cache and self-modifying code

edit

On architectures without coupled data and instruction cache (for example, some SPARC, ARM, and MIPS cores) the cache synchronization must be explicitly performed by the modifying code (flush data cache and invalidate instruction cache for the modified memory area).

In some cases short sections of self-modifying code execute more slowly on modern processors. This is because a modern processor will usually try to keep blocks of code in its cache memory. Each time the program rewrites a part of itself, the rewritten part must be loaded into the cache again, which results in a slight delay, if the modified codelet shares the same cache line with the modifying code, as is the case when the modified memory address is located within a few bytes to the one of the modifying code.

The cache invalidation issue on modern processors usually means that self-modifying code would still be faster only when the modification will occur rarely, such as in the case of a state switching inside an inner loop. Other systems provide a "backdoor" of sorts, allowing multiple mappings of a page of memory to have different permissions. A relatively portable way to bypass W^X is to create a file with all permissions, then map the file into memory twice. On Linux, one may use an undocumented SysV shared-memory flag to get executable shared memory without needing to create a file.

  1. ↑ Later versions of DOS (since version 6.0) introduced the external CHOICE command (in DR-DOS also the internal command and CONFIG.SYS directive SWITCH), so, for this specific example application of a menu system, it was no longer necessary to refer to self-modifying batchjobs, however for other applications it continued to be a viable solution.
  2. 1 2 For example, when running on 386 or higher processors, later Novell DOS 7 updates as well as DR-DOS 7.02 and higher will dynamically replace some default sequences of 16-bit REP MOVSW ("copy words") instructions in the kernel's runtime image by 32-bit REP MOVSD ("copy double-words") instructions when copying data from one memory location to another (and half the count of necessary repetitions) in order to speed up disk data transfers. Edge cases such as odd counts are taken care of.
  3. ↑ As an example, the DR-DOS MBRs and boot sectors (which also hold the partition table and BIOS Parameter Block, leaving less than 446 respectively 423 bytes for the code) were traditionally able to locate the boot file in the FAT12 or FAT16 file system by themselves and load it into memory as a whole, in contrast to their MS-DOS/PC DOS counterparts, which instead relied on the system files to occupy the first two directory entries in the file system and the first three sectors of IBMBIO.COM to be stored at the start of the data area in contiguous sectors containing a secondary loader to load the remainder of the file into memory (requiring SYS to take care of all these conditions). When FAT32 and LBA support was added, Microsoft even switched to require 386 instructions and split the boot code over two sectors for size reasons, which was not an option for DR-DOS as it would have broken backward- and cross-compatibility with other operating systems in multi-boot and chain load scenarios, as well as with older PCs. Instead, the DR-DOS 7.07 boot sectors resorted to self-modifying code, opcode-level programming in machine language, controlled utilization of (documented) side effects, multi-level data/code overlapping and algorithmic folding techniques to still fit everything into a physical sector of only 512 bytes without giving up any of their extended functionality.

References

edit
{{Cite thesis |author-first1=Calton |author-last1=Pu |author-link1=Calton Pu |author-first2=Henry |author-last2=Massalin |author-link2=Henry Massalin |author-first3=John |author-last3=Ioannidis |degree=PhD |title=Synthesis: An Efficient Implementation of Fundamental Operating System Services |publisher=Department of Computer Sciences, [[Columbia University]] |location=New York, USA |id=UMI Order No. GAX92-32050 |date=1992 |url=https://www.scs.stanford.edu/nyu/04fa/sched/readings/synthesis.pdf |access-date=2023-04-25}} [https://www.cs.columbia.edu/~library/TR-repository/reports/reports-1992/cucs-039-92.ps.gz]</ref>\n<ref name=\"Henson_2008\">{{cite news |title=KHB: Synthesis: An Efficient Implementation of Fundamental Operating Systems Services |author-first=Valerie |author-last=Henson |author-link=Valerie Henson |date=2008-02-20 |work=LWN.net |url=https://lwn.net/Articles/270081/ |access-date=2022-05-19 |url-status=live |archive-url=https://web.archive.org/web/20210817175159/https://lwn.net/Articles/270081/ |archive-date=2021-08-17}}</ref>\n<ref name=\"Haeberli_1994_GraficaObscura\">{{cite web |author-first1=Paul |author-last1=Haeberli |author-link1=Paul Haeberli |author-first2=Bruce |author-last2=Karsh |title=Io Noi Boccioni - Background on Futurist Programming |work=Grafica Obscura |date=1994-02-03 |url=https://www.graficaobscura.com/future/index.html |access-date=2023-04-25}}</ref>\n<ref name=\"Bashe-Buchholz-Hawkins-Ingram-Rochester_1981\">{{cite journal |title=The Architecture of IBM's Early Computers |author-first1=Charles J. |author-last1=Bashe |author-first2=Werner |author-last2=Buchholz |author-link2=Werner Buchholz |author-first3=George V. |author-last3=Hawkins |author-first4=J. James |author-last4=Ingram |author-first5=Nathaniel |author-last5=Rochester |journal=[[IBM Journal of Research and Development]] |issn=0018-8646 |date=September 1981 |volume=25 |issue=5 |pages=363–376 |doi=10.1147/rd.255.0363 |url=https://www.ece.ucdavis.edu/~vojin/CLASSES/EEC272/S2005/Papers/IBM-Architecture-Bashe_sep81.pdf |access-date=2023-04-25 |quote-page=365 |quote=The SSEC was the first operating computer capable of treating its own stored instructions exactly like data, modifying them, and acting on the result.}}</ref>\n<ref name=\"Miller_2006\">{{cite web |title=Binary Code Patching: An Ancient Art Refined for the 21st Century. |author-first=Barton P. |author-last=Miller |date=2006-10-30 |publisher=[[NC State University]], Computer Science Department |series=Triangle Computer Science Distinguished Lecturer Series - Seminars 2006–2007 |url=https://arcb.csc.ncsu.edu/~mueller/seminar/fall06/miller.html |access-date=2023-04-25}}</ref>\n<ref name=\"Wenzl-Merzdovnik-Ullrich-Weippl_2019\">{{cite journal |title=From hack to elaborate technique - A survey on binary rewriting |author-first1=Matthias |author-last1=Wenzl |author-first2=Georg |author-last2=Merzdovnik |author-first3=Johanna |author-last3=Ullrich |author-first4=Edgar R. |author-last4=Weippl |location=Vienna, Austria |journal=[[ACM Computing Surveys]] |volume=52 |number=3 |id=Article 49 |date=June 2019 |orig-date=<!-- accepted -->February 2019, <!-- revised -->November 2018, May 2018 |doi=10.1145/3316415 |pages=49:1–49:36 [49:1] |s2cid=195357367 |url=https://publications.sba-research.org/publications/201906%20-%20GMerzdovnik%20-%20From%20hack%20to%20elaborate%20technique.pdf |access-date=2021-11-28 |url-status=live |archive-url=https://web.archive.org/web/20210115224807/https://publications.sba-research.org/publications/201906%20-%20GMerzdovnik%20-%20From%20hack%20to%20elaborate%20technique.pdf |archive-date=2021-01-15 |quote-page=49:1 |quote=[…] Originally, [[binary rewriting]] was motivated by the need to change parts of a program during execution (e.g., run-time patching on the [[PDP-1]] in the 1960's) […]}} (36 pages)</ref>\n<ref name=\"Knuth_MMIX\">{{cite web |title=MMIX 2009 - a RISC computer for the third millennium |author-first=Donald Ervin |author-last=Knuth |author-link=Donald Ervin Knuth |date=2009 |orig-date=1997 |url=https://www-cs-faculty.stanford.edu/~knuth/mmix.html |access-date=2021-11-28 |url-status=live |archive-url=https://web.archive.org/web/20211127194354/https://www-cs-faculty.stanford.edu/~knuth/mmix.html |archive-date=2021-11-27}}</ref>\n<ref name=\"Ortiz_2015\">{{cite web |title=On Self-Modifying Code and the Space Shuttle OS |author-first=Carlos Enrique |author-last=Ortiz |date=2015-08-29 |orig-date=2007-08-18 |url=https://weblog.cenriqueortiz.com/computing/2007/08/18/on-self-modifying-code-and-the-space-shuttle-os/ |access-date=2023-04-25}}</ref>\n<ref name=\"MicroFocus_ALTER\">{{cite book |chapter=The ALTER Statement |publisher=[[Micro Focus]] |title=COBOL Language Reference |url=https://www.microfocus.com/documentation/visual-cobol/vc80/VS2022/HRLHLHPDF803.html}}</ref>\n<ref name=\"Push\">{{cite web |title=Evolutionary Computing with Push: Push, PushGP, and Pushpop |author-first=Lee |author-last=Spector |date= |publisher= |url=https://faculty.hampshire.edu/lspector/push.html |access-date=2023-04-25}}</ref>\n<ref name=\"Schmidhuber\">[[Jürgen Schmidhuber]]'s publications on [https://people.idsia.ch/~juergen/metalearner.html self-modifying code for self-referential machine learning systems]</ref>\n<ref name=\"Fosdal_2001\">{{cite web |title=Self-modifying Batch File |author-first=Lars |author-last=Fosdal |date=2001 |url=http://www.csd.net/~cgadd/knowbase/DOS0019.HTM |archive-url=https://web.archive.org/web/20080421173331/http://www.csd.net/~cgadd/knowbase/DOS0019.HTM |archive-date=2008-04-21}}</ref>\n<ref name=\"Paul_1996\">{{cite book |title=Konzepte zur Unterstützung administrativer Aufgaben in PC-Netzen und deren Realisierung für eine konkrete Novell-LAN-Umgebung unter Benutzung der Batchsprache von DOS |language=de |author-first=Matthias R. |author-last=Paul |version=3.11 |date=1996-10-13 |orig-date=1996-08-21<!-- v3.05-->, 1994 |location=Aachen, Germany |publisher=Lehrstuhl für Kommunikationsnetze ([[ComNets]]) & [[Institut für Kunststoffverarbeitung]] (IKV), RWTH |pages=51, 71–72}} (110+3 pages, diskette) (NB. Design and implementation of a centrally controlled modular distributed management system for automatic [[client (computing)|client]] configuration and [[software deployment]] with [[self-management (computer science)|self-healing]] update mechanism in [[local area network|LAN]] environments based on [[self-replication|self-replicating]] and indirectly self-modifying batchjobs with zero memory footprint instead of a need for [[terminate and stay resident|resident]] management software on the clients.)</ref>\n<ref name=\"Wilkinson_1996\">{{cite web |title=The H89 Worm: Memory Testing the H89 |author-first=William \"Bill\" Albert |author-last=Wilkinson |date=2003 |orig-date=1996, 1984 |work=Bill Wilkinson's Heath Company Page |url=https://www.heco.wxwilki.com/h89worm.html |access-date=2021-12-13 |url-status=live |archive-url=https://web.archive.org/web/20211213130013/https://www.heco.wxwilki.com/h89worm.html |archive-date=2021-12-13 |quote=[…] Besides fetching an instruction, the [[Z80]] uses half of the cycle to [[RAM refresh|refresh]] the [[dynamic RAM]]. […] since the Z80 must spend half of each [[instruction fetch]] cycle performing other chores, it doesn't have as much time to fetch an [[instruction byte]] as it does a data byte. If one of the [[RAM chip]]s at the memory location being accessed is a little slow, the Z80 may get the wrong bit pattern when it fetches an instruction, but get the right one when it reads data. […] the built-in memory test won't catch this type of problem […] it's strictly a data read/write test. During the test, all instruction fetches are from the [[ROM]], not from RAM […] result[ing] in the [[Heath H89|H89]] passing the memory test but still operating erratically on some programs. […] This is a program that tests memory by relocating itself through RAM. As it does so, the CPU prints the current address of the program on the [[cathode-ray tube|CRT]] and then fetches the instruction at that address. If the RAM ICs are okay at that address, the CPU relocates the test program to the next memory location, prints the new address, and repeats the procedure. But, if one of the RAM ICs is slow enough to return an incorrect bit pattern, the CPU will misinterpret the instruction and behave unpredictably. However, it's likely that the display will lock up showing the address of faulty IC. This narrows the problem down eight ICs, which is an improvement over having to check as much as 32. […] The […] program will perform a worm test by pushing an RST 7 (RESTART 7) instruction from the low end of memory on up to the last working address. The rest of the program remains stationary and handles the display of the current location of the RST 7 command and its [[relocation (computing)|relocation]]. Incidentally, the program is called a [[computer worm|worm]] test because, as the RST 7 instruction moves up through memory, it leaves behind a [[NOP trail|slime trail]] of [[NOP (code)|NOP]]s (NO OPERATION). […]}}</ref>\n<ref name=\"Caldera_1997_DOSSRC\">{{cite web |title=Caldera OpenDOS Machine Readable Source Kit (M.R.S) 7.01 |publisher=[[Caldera (company)|Caldera, Inc.]] |date=1997-05-01 |url=https://archive.sundby.com/retro/DR-DOS/dossrc.zip |access-date=2022-01-02 |archive-url=https://web.archive.org/web/20210807095409/https://archive.sundby.com/retro/DR-DOS/dossrc.zip |archive-date=2021-08-07}} [https://web.archive.org/web/20220102102656/https://archive.sundby.com/retro/OpenDOS/OPENDOS_7.01_CODE.ZIP]</ref>\n<ref name=\"Paul_1997_OD-A3\">{{cite web |author-first=Matthias R. |author-last=Paul |title=Caldera OpenDOS 7.01/7.02 Update Alpha 3 IBMBIO.COM README.TXT |url=http://www.uni-bonn.de/~uzs180/download/ibmbioa3.zip |date=1997-10-02 |access-date=2009-03-29 |archive-url=https://web.archive.org/web/20031004074600/http://www-student.informatik.uni-bonn.de/~frinke/ibmbioa3.zip |archive-date=2003-10-04}} [https://web.archive.org/web/20181225154705/http://mirror.macintosharchive.org/max1zzz.co.uk/+Windows%20&%20DOS/DOS/System/Novell/Support/Bins/Op702src.zip<!-- Op702src.zip is an unofficial renamed distribution of the ibmbioa3.zip file -->]</ref>\n<ref name=\"HP9100A_1998\">{{cite web |title=HP 9100A/B |date=1998 |work=MoHPC - The Museum of HP Calculators |at=Overlapped Data and Program Memory / Self-Modifying Code|url=https://www.hpmuseum.org/hp9100.htm |access-date=2023-09-23 |url-status=live |archive-url=https://web.archive.org/web/20230923125424/https://www.hpmuseum.org/hp9100.htm |archive-date=2023-09-23}}</ref>"}},"i":0}}]}'>"The ALTER Statement". COBOL Language Reference. Micro Focus.
  • ↑ Paul, Matthias R. (1996-10-13) [1996-08-21, 1994]. Konzepte zur Unterstützung administrativer Aufgaben in PC-Netzen und deren Realisierung für eine konkrete Novell-LAN-Umgebung unter Benutzung der Batchsprache von DOS. 3.11 (in German). Aachen, Germany: Lehrstuhl für Kommunikationsnetze (ComNets) & Institut für Kunststoffverarbeitung (IKV), RWTH. pp. 51, 71–72. (110+3 pages, diskette) (NB. Design and implementation of a centrally controlled modular distributed management system for automatic client configuration and software deployment with self-healing update mechanism in LAN environments based on self-replicating and indirectly self-modifying batchjobs with zero memory footprint instead of a need for resident management software on the clients.)
  • ↑ Miller, Barton P. (2006-10-30). "Binary Code Patching: An Ancient Art Refined for the 21st Century". Triangle Computer Science Distinguished Lecturer Series - Seminars 2006–2007. NC State University, Computer Science Department. Retrieved 2023-04-25.
  • ↑ "Caldera OpenDOS Machine Readable Source Kit (M.R.S) 7.01". Caldera, Inc. 1997-05-01. Archived from the original on 2021-08-07. Retrieved 2022-01-02.
  • 1 2 3 Wieczorkiewicz, Pawel. "Linux Kernel Alternatives". Retrieved 2022-11-27.
  • ↑ Haeberli, Paul; Karsh, Bruce (1994-02-03). "Io Noi Boccioni - Background on Futurist Programming". Grafica Obscura. Retrieved 2023-04-25.
  • Further reading

    edit