self-writing code?

This is a discussion on self-writing code? within the C++ Programming forums, part of the General Programming Boards category; Is it possible, in a windows program, to write machine code in memory and then be able to run that ...

  1. #1
    Registered User
    Join Date
    Jan 2002
    Posts
    75

    Question self-writing code?

    Is it possible, in a windows program, to write machine code in memory and then be able to run that code? If not, could one build a dll with a function in it, then load the dll from the same program, and run that function?

  2. #2
    UNBANNED OneStiffRod's Avatar
    Join Date
    Jan 2002
    Posts
    669
    Yes, that's what a DLL is, it is loaded once and is used by many apps or many instances of one app but the DLL is loaded only once.
    My Avatar says: "Stay in School"

    Rocco is the Boy!
    "SHUT YOUR LIPS..."

  3. #3
    C++ Developer XSquared's Avatar
    Join Date
    Jun 2002
    Location
    Ontario, Canada
    Posts
    2,718
    Originally posted by OneStiffRod
    Yes, that's what a DLL is, it is loaded once and is used by many apps or many instances of one app but the DLL is loaded only once.
    I think that he wants to know how to be able to have a user execute code at run-time.
    Naturally I didn't feel inspired enough to read all the links for you, since I already slaved away for long hours under a blistering sun pressing the search button after typing four whole words! - Quzah

    You. Fetch me my copy of the Wall Street Journal. You two, fight to the death - Stewie

  4. #4
    UNBANNED OneStiffRod's Avatar
    Join Date
    Jan 2002
    Posts
    669
    That's what a program does, it EXECUTES machine code at run-time.

    If he wants to know whether code can be CREATED in real time - u need to REAL-TIME COMPILE IT. It needs to be compiled into machine code before it can be run.
    My Avatar says: "Stay in School"

    Rocco is the Boy!
    "SHUT YOUR LIPS..."

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Sure, anything's possible. But there's no documented way to do that, as far as I know. One way you might do it would be to generate the bytecode, stuff it into the appropriate headers, and then use a system call to run the program from a file you've generated. Otherwise, you're looking at some sort of assembly hack probably...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User Frobozz's Avatar
    Join Date
    Dec 2002
    Posts
    546
    You could always make the program generate assembly code and then run it through an assembler.

  7. #7
    UNBANNED OneStiffRod's Avatar
    Join Date
    Jan 2002
    Posts
    669
    YES, just like a COMPILER
    My Avatar says: "Stay in School"

    Rocco is the Boy!
    "SHUT YOUR LIPS..."

  8. #8
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Here's a way:
    Compile without optimizations.
    Code:
    unsigned char data[10000];
    
    //Fill the memory with no-ops
    for (int i=0;i<10000;++i)
     data[i] = 0x90; //NOP
    
    data[9999] = 0xC3; // RET
    
    //Create a function pointer to the memory
    void (__stdcall*pf)() = reinterpret_cast<void(__stdcall*)()>(data);
    
    //Execute the memory
    pf();
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Nice solution.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,789

    Re: self-writing code?

    Originally posted by genghis
    Is it possible, in a windows program, to write machine code in memory and then be able to run that code?
    Yes its possible.

    You can set the EIP register of an intel based chip (and amd) on a windows machine to a portion of your memory using the SetThreadContext API........but doing so on the calling thread is undefined...so you should create a seperate, stalled thread and use that...resume the thread after the call...

    I did this a while ago and posted the code on my site (which is now pretty much gone)....but here's my code....it uses VC++6.....but I guess it should work with other Win compilers - though I havent tested it.....it's real messy code (learning as I went along) but it works

    Code:
    //////////////////////////////////////////
    // Dynamic Assembly
    //
    //
    // by Fordy May 2002
    // 
    //
    //
    // This program is a sort of Obfuscated "Hello World" that
    // implements API calls by dynamically writing handcrafted
    // opcode to a region in memory, and then creating a thread
    // and pointing it to that opcode.
    //
    //
    // Copyright ©2002, Rob J Ford, robjford.com
    // All rights reserved..
    //
    // Compile list:-
    //
    // Make sure project is a normal Win32 Application
    // Tested using VC++6 on the Windows 2000 platform
    // Not tested on any other platform!!!!!
    //
    // Definitions and preambles
    //
    #include <windows.h>
    
    int Assemble(void); //Creates opcodes to create MessageBox
    
    
    ///////////////////////////////////////////////////////////////
    //Class that represents a region in data that holds dynamically
    //generated opcodes and small lookup jump table
    //
    class HELLO{
    public:
    	UCHAR NULL1[2],
    	MEMPOS1[5],
    	MEMPOS2[5],
    	NULL2[2],
    	CALL1[5],
    	NULL3[2],
    	CALL2[5],
    	JUMP1[6],
    	JUMP2[6];
    	DWORD JUMPLOC1,
    	JUMPLOC2;
    }Hello;
    
    /*MessageBox Text & Caption*/
    char szMessage[] = "HelloWorld",
         szCaption[] = "Obfuscated!!!\nBy Rob J Ford\nMay 2002";
    HMODULE hModKern,hModUser;//Handles of libraries loaded
    
    
    
    ///////////////////////////////////////////////////////////////
    //Main entry point.....Create opcodes in memory, create thread in
    //suspended state, jig around with EIP on thread so it pointes to
    //my opcode.....then....well....Rock n Roll 
    //
    int WINAPI WinMain(HINSTANCE hThisInstance,
       HINSTANCE hPrevInstance,
       LPSTR lpszArgument,
       int nShowState){
    
    	HANDLE hThread,hThreadAccess;
    	DWORD dwThreadID;
    	CONTEXT cont;
    	char szTrace[256];
    
    	/*Create the opcodes & lookups and store in memory*/
    	if(Assemble())
    		return 0;
        /*Create a suspended thread with no start point*/
    	hThread = CreateThread(NULL,0,NULL,NULL,CREATE_SUSPENDED,
    		&dwThreadID);
    
    	if(hThread == NULL){
    		MessageBox(HWND_DESKTOP,"Could not create thread",
    			"Error",MB_OK | MB_ICONEXCLAMATION);
    		return 1;
    	}
    
    	/*Redifine handle to allow me to get & set contects*/
    	DuplicateHandle(GetCurrentProcess(),hThread,
    		GetCurrentProcess(),&hThreadAccess,
    		THREAD_GET_CONTEXT | THREAD_SET_CONTEXT |
    		SYNCHRONIZE | THREAD_ALL_ACCESS,0,0);
    
    	/*Access to most usefull registers*/
    	cont.ContextFlags = CONTEXT_FULL;
    
    	/*Get the registers & flag of the created thread*/
    	if(!GetThreadContext(hThreadAccess,&cont)){
    		MessageBox(HWND_DESKTOP,"Could not load context",
    			"Error",MB_OK | MB_ICONEXCLAMATION);
    		return 1;
    	}
    
    	/*Set thread entry point to start of my opcode block*/
    	cont.Eip = (unsigned long)&Hello.NULL1[0];
    
    	cont.ContextFlags = CONTEXT_FULL;
    
    	/*Set thread context*/
    	if(!SetThreadContext(hThreadAccess,&cont)){
    		MessageBox(HWND_DESKTOP,"Could not set context",
    			"Error",MB_OK | MB_ICONEXCLAMATION);
    		return 1;
    	}
    
    	/*Launch the thread and wait for it to exit*/
    	if(ResumeThread(hThreadAccess) != 0xFFFFFFFF)
    		WaitForSingleObject(hThread, INFINITE);
    	else{
    		wsprintf(szTrace,"Could not start thread\nError =  %d",
    		GetLastError());
    		MessageBox(HWND_DESKTOP,szTrace,
    		"Error",MB_OK | MB_ICONEXCLAMATION);
    	}
    
    
    	/*No need.... but free up the libs*/
    	FreeLibrary(hModKern);
    	FreeLibrary(hModUser);
     
        return 0;
    }
    
    ///////////////////////////////////////////////////////////////
    //Function creates links to 2 API calls dynamically and stores
    //info in memory as opcode....it also implements those functions
    //to display MessageBox and then finish thread
    //
    int Assemble(void){
    
    
    	UCHAR *pointer = 0,*pointer2 = 0;
    
    	int j;
    	union MYUNION{
    		UINT uiMemPos;
    		UCHAR ucMemPos;
    	}MyUnion;
    
    	/*Set basic of opcodes*/
    	pointer = Hello.NULL1;
    
    	*pointer = pointer[12] = pointer[19] = 'j';//push NULL start
    	pointer[1] = pointer[13] = pointer[20] = 0;//push NULL end
    	pointer[2] = pointer[7] = 'h'; //push mem start
    	pointer[14] = pointer[21] = 232;//call start
    	pointer[26] = pointer[32] = 255;//First part JUMP
    	pointer[27] = pointer[33] = '%';//Second part JUMP
    
    	/*Calculate distance between calls*/
    	Hello.CALL1[1] = (UINT)&Hello.JUMP1 - (UINT)&Hello.NULL3;
    	Hello.CALL2[1] = (UINT)&Hello.JUMP2 - (UINT)&Hello.JUMP1;
    
    	/*Set rest of call opcode to zero ..(debug help...not important)*/
    	for(j = 2;j<5;j++)
    		Hello.CALL1[j] = Hello.CALL2[j] = 0;
    
    	/*Get location of message*/
    	MyUnion.uiMemPos = (UINT)&szMessage;
    
    	pointer = &Hello.MEMPOS1[1];
    	pointer2 = &MyUnion.ucMemPos;
    
    	/*Copy to push statement (2nd param of MessageBoxA)*/
    	for(j = 0;j<4;j++)
    		pointer[j] = pointer2[j];
    
    	/*Do as above for caption (3rd Param)*/
    	MyUnion.uiMemPos = (UINT)&szCaption;
    
    	pointer = &Hello.MEMPOS2[1];
    	pointer2 = &MyUnion.ucMemPos;
    
    	for(j = 0;j<4;j++)
    		pointer[j] = pointer2[j];
    
    	/*Load for MessageBoxA*/
    	hModUser = LoadLibrary("user32.dll");
    
    	/*Load for ExitThread*/
    	hModKern = LoadLibrary("kernel32.dll");
    
    	if(hModKern == NULL || hModUser == NULL){
    		MessageBox(HWND_DESKTOP,"Could not load modules",
    			"Error",MB_OK | MB_ICONEXCLAMATION);
    		return 1;
    	}
    
    	/*Find memory location of MessageBox func*/
    	/*Copy that location to the first jmp lookup*/
    	Hello.JUMPLOC1  = (UINT)GetProcAddress(hModUser,
    		"MessageBoxA");
    
    	if(Hello.JUMPLOC1 == NULL){
    		MessageBox(HWND_DESKTOP,"Could not locate procs",
    			"Error",MB_OK | MB_ICONEXCLAMATION);
    		return 1;
    	}
    
    	/*Move location of lookup to the first jmp stat*/
    	MyUnion.uiMemPos = (UINT)&Hello.JUMPLOC1;
    	pointer2 = &MyUnion.ucMemPos;
    	pointer = Hello.JUMP1;
    
    	pointer += 2;
    
    	for(j = 0;j<4;j++)
    		pointer[j] = pointer2[j];
       
    	/*Same as above, but for ExitThread*/
    	Hello.JUMPLOC2 = (UINT)GetProcAddress(hModKern,
    		"ExitThread");
    
    	if(Hello.JUMPLOC2 == NULL){
    		MessageBox(HWND_DESKTOP,"Could not locate procs",
    			"Error",MB_OK | MB_ICONEXCLAMATION);
    		return 1;
    	}
    
    	MyUnion.uiMemPos = (UINT)&Hello.JUMPLOC2;
    	pointer2 = &MyUnion.ucMemPos;
    	pointer = Hello.JUMP2;
    
    	pointer += 2;
    
    	for(j = 0;j<4;j++)
    		pointer[j] = pointer2[j];
    
    
    	return 0;
    }
    Its a little tedious though...as you cant just copy reverse engineered code into the memory....you need to alter the jump tables and function addresses as well as the address of variables like the string used in my messagebox

  11. #11
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    To answer the original question:
    I think a DLL would be better.

    You learn a lot by pushing limits, though.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  12. #12
    Registered User
    Join Date
    Jan 2002
    Posts
    75
    Thanks, I appreciate the help.

    If you wanted to know, I'm trying to work on a project in which I accept a string from the user, such as "|x^2 + max(x, 5, y)|" and then try to compile a function that the programmer can call with the variables as parameters (in this case x and y). I'm doing it for practice as well as its future use considering I tend to use math quite a bit.

  13. #13
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Unhappy

    Dammit, Fordy, your code crashed my computer and erased my hard drive! j/k

    Interesting solution, BTW.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  14. #14
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Originally posted by genghis
    I'm trying to work on a project in which I accept a string from the user, such as "|x^2 + max(x, 5, y)|" and then try to compile a function that the programmer can call with the variables as parameters (in this case x and y).
    Then I advice you to forget about machine code (for now). A nice way to gain speed when evaluating expression repeatedly is to convert to RPN.
    3 + x * 2 - y
    becomes
    3 4 x * + y -

    When the RPN is generated, the expression can be evaluated fast for different values of x and y.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  15. #15
    Registered User
    Join Date
    Nov 2002
    Posts
    491
    If you want to cheat, you can use yacas. It is a CAS, but also comes with a dll you can load into your program and do things lik:
    yacas.eval("x^2+2");

    Depending on how complex of stuff you want, writing this yourself will not be a super easy task. I have an expression parser that takes an infix notion and converts it to postfix, you can PM me if you would like it.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Writing Code but am having problems
    By Choppers in forum C Programming
    Replies: 20
    Last Post: 06-25-2009, 07:18 PM
  2. Writing code for a program in C
    By Sure in forum C Programming
    Replies: 7
    Last Post: 06-11-2005, 02:33 PM
  3. professional programmers, do you spend more time writing or modifying code
    By Terrance in forum A Brief History of Cprogramming.com
    Replies: 29
    Last Post: 11-25-2002, 10:54 PM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 06:06 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21