-1

I have searched considerably for an answer to this without success. In a debugger, one may write instructions and then execute them. This requires special permissions in the executable image. I seek to perform this function without the debugger.

Please show me an ASM "hello world" program that has self-modifying code (perhaps replacing a series of 090H with code to uppercase the 'h' in hello) and the commands necessary to enable its execution. The next 2 lines are the before and after machine code for the h->H replacement.

90 90 90 90 90 90 90 90 90 90 90 ; 11 NOPs
8a 26 50 00 80 e4 df 88 26 50 00 ; MOV AH,[BX]; AND AH,0DFH; MOV [BX],AH;

I have complete competence and confidence constructing iAPX86 machine code. My problem is convincing linux, darwin/yosemite, and windows to allow execution. In the end, I want to be able to construct and modify an executable on-the-fly for a new language I am writing. The architecture of the new language has no parallels in modern practice.

I expect much criticism for flying in the face of convention, but I will proceed with my plans notwithstanding.

jlettvin
  • 1,113
  • 7
  • 13
  • I don't believe there's a platform agnostic way of doing that. I could show you how to do it on Windows in 32 or 64-bit code, but I'm sure you could google that information as well. - What you show there in the comments is 16-bit code - was that intentional? – 500 - Internal Server Error Sep 29 '15 at 20:52
  • Also, you say you want to eliminate the debugger, but your code must execute in something, some process context - what will that be without the debugger? – 500 - Internal Server Error Sep 29 '15 at 20:53
  • 1
    You'll have to use an OS specific mechanism to mark the code segment as writable. On Linux and BSD the way you would do it is via [mprotect](http://linux.die.net/man/2/mprotect) – Michael Petch Sep 29 '15 at 21:36
  • The given code was not to be considered as "desirable" but merely representative, and yes it is 16 bit. What I am writing is an interpreter which also operates as a debugger to be operated in 64 bit environments. It will permit hex opcodes, opcode names, macro names, and new abstractions. The foundation code will be in nasm (or yasm, or clang). What I need are the command-line options to make the executable .text sections writeable, or other recommendations. These will be needed separately for the 3 main operating systems in 64 bit mode. – jlettvin Sep 29 '15 at 22:08
  • What you wrote in your comment really should be part of the question. I assume you are also aware of this http://superuser.com/questions/140953/why-cant-a-64-bit-os-run-a-16-bit-application – Michael Petch Sep 30 '15 at 00:32
  • During the linking stage you could try changing the attributes of the text segment. This answer might be useful. http://stackoverflow.com/a/27581305/3857942 . However this isn't cross platform. If you are targeting Windows and Linux your likely going to come up with a solution for each platform. – Michael Petch Sep 30 '15 at 01:34
  • I am about to try it, but here is what sounds right: "gcc --static -g -Wl,--omagic -o test test.c". Thank you for offering the links. – jlettvin Sep 30 '15 at 03:08
  • Sorry to say it didn't work. gcc -g -o bar bar.c; objcopy --set-section-flags .text=contents,alloc,load,code bar bar1; objdump -h bar1 | fgrep -A1 .text; This only resulted in "Killed: 9". Still need help. – jlettvin Sep 30 '15 at 04:31

1 Answers1

1

Thank you all for taking my question seriously. This code works! It turned out to be far simpler than I thought; without special compiler flags, or ELF or MACHO specialization. In iAPX86 machine code, C3 is near RET without a return value. I have a few improvements to make, listed after the code, but this question, as asked, is completely answered to my satisfaction.

working code

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

typedef void (*fptr)();

int main(int argc, char **argv) {
  try {
    fptr p = (fptr)"\xc3";
    p();
    cout << "Hello world" << endl;
  }
  catch (const int     e) { cout << "int     exception: " << e << endl; }
  catch (const char    e) { cout << "char    exception: " << e << endl; }
  catch (const string &e) { cout << "string  exception: " << e << endl; }
  catch (...)             { cout << "default exception"        << endl; }
  exit(0);
}

TODO

  • bracket opcode strings with safety code.
  • prevent certain opcodes from appearing in strings.
  • catch signals as well as exceptions.
jlettvin
  • 1,113
  • 7
  • 13
  • Your question said to "construct and modify an executable on-the-fly". That is not exactly what you are doing here. You are effectively creating new code (not modifying the executable) with the assumption that the target OS allows for an executable stack. This is exactly how buffer overrun exploits work. And if your concern is that strings will contain embedded nul characters and break up the string, I think that can easily dealt with. But if for whatever reason you need to encode the nuls as something else then I suggest you look at some JMP-CALL-POP encoder/decoders. – Michael Petch Sep 30 '15 at 07:47
  • Thank you. You grasp my intentions well, although I failed to ask my question with sufficient clarity. By creating a new language, my goal is to construct novel machine code fragments unlikely to be produced by any compiler I know, to achieve valuable efficiency goals. I intend this both to experiment with doing the "forbidden" and implementing a neural model inconsistent with standard practices. I was in antivirus work for 10 years, so the buffer overrun exploit is familiar. I want to mix the value of compiled code, old-fashioned spaghetti-code, and distribution. p(); is what I wanted. – jlettvin Oct 01 '15 at 03:17
  • Can you explain what exactly the code does? I compiled it with g++ and it prints "Hello world\n". What does the character literal stand for? – Joonazan Jul 27 '16 at 16:14
  • Sorry for the delay in answering. Intel opcode C3 is a RETURN. In other words it is an empty function that simply returns. This is a demo showing how to construct your own machine code sequences. If you want to write a targeted compiler, code eventually you must emit machine code. This shows how to actually run such machine code fragments. – jlettvin Aug 05 '16 at 14:27