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?
Printable View
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?
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.Quote:
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.
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.
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...
You could always make the program generate assembly code and then run it through an assembler.
YES, just like a COMPILER
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();
Nice solution. :)
Yes its possible.Quote:
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?
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
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 messageboxCode://////////////////////////////////////////
// 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;
}
To answer the original question:
I think a DLL would be better. :D
You learn a lot by pushing limits, though.
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.
Dammit, Fordy, your code crashed my computer and erased my hard drive! :D j/k
Interesting solution, BTW.
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.Quote:
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).
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.
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.
What is RPN?
>>What is RPN?
Reverse Polish Notation
Thanks Cela,
I got this from a site I found on google:
"Thus, the compilers on on almost all modern computers converted statements to RPN for execution."
http://www.hpmuseum.org/rpn.htm
so doesn't that mean the compiler does postfix anyway and u don't have to add yurself?
I once wrote a fairly long post on how to convert an expression to RPN.
But I guess I'm a poor tutor, because none answered my post. :)
Here it is:
http://www.cprogramming.com/cboard/s...threadid=27699
How do you expect the compiler to convert an input value into RPN while your program is running?Quote:
so doesn't that mean the compiler does postfix anyway and u don't have to add yurself?