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