5,317,180 members and growing! (17,554 online)
Email Password   helpLost your password?
General Programming » Programming Tips » General     Intermediate License: The Code Project Open License (CPOL)

Programming Self-generating Code for Windows Applications

By Jim Charles

Executing VC++ codes in STACK or HEAP
VC6, VC8.0, C++Windows, Win2K, WinXP, Win2003, Vista, MFC, VS2005, VS6, Visual Studio, CEO, Dev

Posted: 3 Oct 2007
Updated: 29 Feb 2008
Views: 53,348
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
591 votes for this Article.
Popularity: 13.33 Rating: 4.81 out of 5
7 votes, 1.2%
1
2 votes, 0.3%
2
1 vote, 0.2%
3
2 votes, 0.3%
4
577 votes, 98.0%
5

Introduction

Self-generating code technology is a very important means to counteract disassembler. You should use this technology to protect your applications although it's a "bad" programming style. There are two documented ways of modifying application code at least. First, kernel32.dll exports the WriteProcessMemory function, intended as follows from its name, for modifying the memory of a process. Second, practically all operating systems, Windows and Linux included, allow the code placed on the stack to be modified. I like the second way, because it is more freedom and less limitation when I try creating self-generating code for Windows applications in VC++ IDE. A FAQ is to cause an exception with the subsequent abnormal termination of the application.

Screenshot - error.jpg

I try to resolve these questions, and get some experience as follows:

The function code must be relocatable code:

  1. Only use local variable, don't use global variable, static variable, and constant string variable.
  2. If the function code wants to invoke another function, the pointer of the function should be passed to it.

Some may have a question about Self-generating code: What's the advantage of it?

The answer is that it can conceal crucial or key information, such as procedures for generating the key or for verifying the serial number.

Using the Code

Step 1: Encrypt My_function Code into a Header File

The following code is my function which I want to execute in the stack. Of course you can modify it, add your own code and test it, then you can get your own experience. If you like, you can share it here or write another article and publish it on The Code Project.

//
void __stdcall my_function( int x,
     int y,
     char* str_a,
     char* str_b,
     void* (__cdecl *_memcpy )( void *dest, const void *src, size_t count ),
     int (__cdecl *_sprintf )( char *buffer, const char *format, ... ),
     void* (__cdecl *_malloc )( size_t size ),
     void (__cdecl *_free )( void *memblock ),
     size_t (__cdecl *_strlen )( const char *string ),
     int (__stdcall* _MessageBox)(HWND hWnd, LPCTSTR lpText, 
     LPCTSTR lpCaption, UINT uType)
)
{
    char* pTemp;
    int str_a_len=_strlen(str_a);
    int str_b_len=_strlen(str_b);   
    pTemp=(char*)_malloc(str_a_len+str_b_len+20);

    if(x>y)
    {
        //_sprintf(pTemp,"%s%s",str_a,str_b);       
        //error:constant string variable
        _memcpy(pTemp,str_a,str_a_len);
        _memcpy(pTemp+str_a_len,str_b,str_b_len);
        pTemp[str_a_len+str_b_len]=0;

        //_MessageBox(NULL,pTemp,"",MB_OK);         
        //error:constant string variable
        _MessageBox(NULL,pTemp,str_a,MB_OK);
    }
    else
    {
        //_sprintf(pTemp,"%s%s",str_b,str_a);
        //error:constant string variable
        _memcpy(pTemp,str_b,str_b_len);
        _memcpy(pTemp+str_b_len,str_a,str_a_len);
        pTemp[str_a_len+str_b_len]=0;

        //MessageBox(NULL,pTemp,"title",MB_OK);
        //error:constant string variable
        _MessageBox(NULL,pTemp,str_b,MB_OK); 
    }

    for(int i=0;i<10;i++)
    {
        int j=1;
        j^=i;
    }

    _free(pTemp);
}  
//

In my_function, I try to invoke some running time library functions and Windows API function, in order to compare parameter X and Y to display different message boxes.

In order to execute this function in the stack, first I should encrypt my_function code. This job is implemented in the project named My_function. If you read it, you can find a function named void __stdcall my_function_END(). In order to calculate the length of my function, my_function_END function must follow on the heels of my_function.

void encrypt_my_function() and bool encrypt_function(BYTE* _my_function,unsigned int n_my_function_size,char* function_name) are used to encrypt my_function code data into a temporary buffer, void build_h(BYTE* pInBuf,int InBufSize,char* function_name) function will write the encrypted code data into a header file.

//
bool encrypt_function(BYTE* _my_function,unsigned int n_my_function_size,
    char* function_name)
{
    BYTE* buff=(BYTE*)malloc(n_my_function_size);
    if(buff==NULL) return false;

    //Note: Here is just a simple encryption algorithm,
    //you should replace it with your own.
    //There are a lot of encryption algorithms which you can get 
    //from the Internet.
    for(UINT i=0;i<n_my_function_size;i++) buff[i]=_my_function[i]^99;

    build_h(buff,n_my_function_size,function_name);
    free(buff);
    return true;
}

//
//
void encrypt_my_function()
{
    void ( __stdcall *_my_function)(int x,
        int y,
        char* str_a,
        char* str_b,
        void* (__cdecl *_memcpy )( void *dest, 
        const void *src, size_t count ),
        int (__cdecl *_sprintf )( char *buffer, const char *format, ... ),
        void* (__cdecl *_malloc )( size_t size ),
        void (__cdecl *_free )( void *memblock ),
        size_t (__cdecl *_strlen )( const char *string ),
        int (__stdcall* _MessageBox)(HWND hWnd, LPCTSTR lpText, 
        LPCTSTR lpCaption, UINT uType)
                                    );
    void ( __stdcall *_my_function_END)();
    unsigned int n_my_function_size;
    char* function_name="myfunction";

    _my_function=my_function;
    _my_function_END=my_function_END;
    n_my_function_size=abs((UINT)_my_function_END-(UINT)_my_function)+1;
    //calculate the length of my_function

    if(encrypt_function((BYTE*)_my_function,n_my_function_size,function_name))
    {
        AfxMessageBox(
            "My function is encrypted successfully ! 
            The encrypted code is included in myfunction.h file.");
    }
    else
    {
        AfxMessageBox("My function is encrypted unsuccessfully !");
    }
}
//

Myfunction.h is generated by My_function project.

A header file which includes the encrypted code data would look as follows:

//
//myfunction.h

unsigned char myfunction_00001_code[]="\
\xe8\x27\x47\x6f\x30\x36\x35\xe8\x17\x47\x53\x34\x33\
x9c\xb5\xe8\x0f\x47\x47\xe8\
\x9b\x36\x9c\xb5\xe8\xbb\xee\x2f\x58\x77\x32\x9c\x37\
x47\x5b\xe8\x37\x47\x43\xe8\
\x93\xe8\x27\x47\x47\xe0\xa7\x6f\x58\xb3\x1d\x5f\xe8\
x27\x47\x7f\x34\x33\x35\x9c\
\x37\x47\x53\x30\xee\x6f\x5d\x36\x32\x9c\x37\x47\x5f\
xe8\x27\x47\x57\xe0\xa7\x7b\
\xee\x77\x7d\x09\x63\x33\x35\x09\x63\xa5\x67\x59\x63\
x9c\x37\x47\x2b\x35\x9c\x37\
\x47\x57\xe0\xa7\x67\x3c\x3d\x3e\x38\xa1\x4b\x63\x30\
x36\x35\x9c\x37\x47\x53\xe8\
\x2f\x47\x4b\x60\xbd\x34\x32\x30\x9c\x37\x47\x5f\xe0\
xa7\x7b\xa5\x67\x58\x63\x09\
\x63\x0b\x17\x33\x23\x63\x35\x09\x63\x9c\x76\x1b\x50\
x23\x63\x09\x63\x36\x35\x09\
\x63\x9c\x37\x47\x2b\x35\x9c\x37\x47\x57\xe0\xa7\x67\
x3c\x3d\x3e\x38\xa1\x4b\x63\
\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xa0";
#define myfunction_00001_code_LEN 193

#define myfunction_ARRAY_NUM 1
#define myfunction_CODE_LEN 193

//

Note: If you want to define an unsigned char variable like unsigned char myfunction_00001_code[], it's maxlength is 2048. This is the limitation of VC++ 6.0 IDE. So, if the function code is too long, I must write the encrypted code data into multi unsigned char variables.This function can be realized in build_h which looks as follows:

//
void build_h(BYTE* pInBuf,int InBufSize,char* function_name)
{
    DWORD syslen=InBufSize;
    BYTE* sysbuffer=pInBuf;

    char hname[MAX_PATH];
    sprintf(hname,"%s%s",function_name,".h");

    HANDLE hHandle=CreateFileA(hname,
        GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);

    SetFilePointer(hHandle,0,0,FILE_BEGIN);

    DWORD RW;
    char _code_end[]="\";
    int l_end=strlen(&_code_end[0]);

    char cname[MAX_PATH];
    char* pszSlash=hname;

    char TX[5];
    int count=0;
    int arrary_num=1;
    int ar_num=0;

    WriteFile(hHandle,"\r",1,&RW,NULL);
    WriteFile(hHandle,"\n",1,&RW,NULL);

    WriteFile(hHandle,"//",2,&RW,NULL);
    WriteFile(hHandle,hname,strlen(hname),&RW,NULL);
    WriteFile(hHandle,"\r",1,&RW,NULL);
    WriteFile(hHandle,"\n",1,&RW,NULL);
    WriteFile(hHandle,"\r",1,&RW,NULL);
    WriteFile(hHandle,"\n",1,&RW,NULL);

    WriteFile(hHandle,
        "//Created by Your Name",strlen("//Created by Your Name"),&RW,NULL);
    WriteFile(hHandle,"\r",1,&RW,NULL);
    WriteFile(hHandle,"\n",1,&RW,NULL);

    WriteFile(hHandle, "//your email", strlen("//your email"), &RW, NULL);

    WriteFile(hHandle,"\r",1,&RW,NULL);
    WriteFile(hHandle,"\n",1,&RW,NULL);

    for(UINT i=0;i<syslen;i++){
        if(ar_num==0){
            WriteFile(hHandle,"\r",1,&RW,NULL);
            WriteFile(hHandle,"\n",1,&RW,NULL);

            int ee=sprintf(cname,"%s","unsigned char ");
            ee+=sprintf(cname+ee,"%s",pszSlash);
            ee=ee-2;
            ee+=sprintf(cname+ee,"%s%05d","_",arrary_num);
            ee=sprintf(cname+ee,"%s",_code[]=\"\\\r\n");
            int l=strlen(&cname[0]);
            WriteFile(hHandle,cname,l,&RW,NULL);
        }

        WriteFile(hHandle,"\\x",2,&RW,NULL);
        sprintf(TX,"%02x",sysbuffer[i]);
        WriteFile(hHandle,TX,2,&RW,NULL);
        count++;
        ar_num=ar_num+4;

        if (count==20){
        count=0;
        WriteFile(hHandle,"\\",1,&RW,NULL);
        WriteFile(hHandle,"\r",1,&RW,NULL);
        WriteFile(hHandle,"\n",1,&RW,NULL);
        }

        if(ar_num>2030){

        arrary_num=arrary_num+1;
        WriteFile(hHandle,_code_end,l_end,&RW,NULL);

        WriteFile(hHandle,"\r",1,&RW,NULL);
        WriteFile(hHandle,"\n",1,&RW,NULL);

        char len[MAX_PATH];
        int ee=sprintf(len,"%s","#define ");
        ee+=sprintf(len+ee,"%s",cname+14);
        ee=ee-7;
        ee+=sprintf(len+ee,"%s","_LEN ");
        ee+=sprintf(len+ee,"%d",ar_num/4);
        WriteFile(hHandle,len,ee,&RW,NULL);

        WriteFile(hHandle,"\r",1,&RW,NULL);
        WriteFile(hHandle,"\n",1,&RW,NULL);

        ar_num=0;
        count=0;
        }
    } 

    double yushu=fmod(syslen*1.0,508.0);
    if(yushu!=0){
        WriteFile(hHandle,_code_end,l_end,&RW,NULL);

        WriteFile(hHandle,"\r",1,&RW,NULL);
        WriteFile(hHandle,"\n",1,&RW,NULL);

        char len[MAX_PATH];
        int ee=sprintf(len,"%s","#define ");
        ee+=sprintf(len+ee,"%s",cname+14);
        ee=ee-7;
        ee+=sprintf(len+ee,"%s","_LEN ");
        ee+=sprintf(len+ee,"%d",ar_num/4);
        WriteFile(hHandle,len,ee,&RW,NULL);

        WriteFile(hHandle,"\r",1,&RW,NULL);
        WriteFile(hHandle,"\n",1,&RW,NULL);
    }

    WriteFile(hHandle,"\r",1,&RW,NULL);
    WriteFile(hHandle,"\n",1,&RW,NULL);

    char lLen[MAX_PATH];
    int ee=sprintf(lLen,"%s","#define ");
    ee+=sprintf(lLen+ee,"%s",cname+14);
    ee=ee-17;
    ee+=sprintf(lLen+ee,"%s","ARRAY_NUM ");
    ee+=sprintf(lLen+ee,"%d",arrary_num);


    WriteFile(hHandle,lLen,ee,&RW,NULL);

    WriteFile(hHandle,"\r",1,&RW,NULL);
    WriteFile(hHandle,"\n",1,&RW,NULL);


    ee=sprintf(lLen,"%s","#define ");
    ee+=sprintf(lLen+ee,"%s",cname+14);
    ee=ee-17;
    ee+=sprintf(lLen+ee,"%s","CODE_LEN ");
    ee+=sprintf(lLen+ee,"%d",syslen);


    WriteFile(hHandle,lLen,ee,&RW,NULL);

    WriteFile(hHandle,"\r",1,&RW,NULL);
    WriteFile(hHandle,"\n",1,&RW,NULL);
    CloseHandle(hHandle);
}
//

After generating myfunction.h which includes the encrypted code data of my_funcion, I create a project named self_engendered_code. In this project, My_function is decrypted and then executed in the stack or any other memory buffer such as heap buffer allocated by malloc although some consider that it is not permitted.

Step 2: Decrypt My_function Code and Execute

First, include myfunction.h in the self_engendered_code project. Second, define some macro in order to load the multi unsigned char variables into one memory buffer.

//
#include "..\\\self_engendered_code\\My_function\\myfunction.h"
#define _founc(x) myfunction_##x##_code
#define _founc_len(x) myfunction_##x##_code_LEN
unsigned char p_my_function[1024];
//

void Load_my_function() can decrypt My_function code into a memory buffer: p_my_function here is a global variable. It can be replaced with a local variable which is defined in the function body, that is the local function stack.

//
void Load_my_function()
{
    int code_len=myfunction_CODE_LEN;
    unsigned char* pcode=
        (unsigned char*)malloc(code_len*sizeof(unsigned char));

    if(pcode==NULL)
    {
        #ifdef _DEBUG
            AfxMessageBox("Memory used up!");
        #endif

        return;
    }

    int p;
    int hp=0;

    for(int k=1;k<=myfunction_ARRAY_NUM;k++)
    {
        switch (k)
        {
        //The number of case equal to myfunction_ARRAY_NUM 
        //defined in myfunction.h.
            case 1:
                for(p=0;p<_founc_len(00001);p++) pcode[hp+p]=_founc(00001)[p];
                hp=hp+p;
                break;
            /*
            case 2:
                for(p=0;p<_founc_len(00002);p++) pcode[hp+p]=_founc(00002)[p];
                hp=hp+p;
                break;
            case 3:
                for(p=0;p<_founc_len(00003);p++) pcode[hp+p]=_founc(00003)[p];
                hp=hp+p;
                break;
            case 4:
                for(p=0;p<_founc_len(00004);p++) pcode[hp+p]=_founc(00004)[p];
                hp=hp+p;
            break;
            .
            .
            .

            */
            default:
            break;
        } 
    }

    //Note: Here is just a simple encryption algorithm, you should 
    //replace it with your own.
    //There are a lot of encryption algorithms which you can get 
    //from the Internet. 
    for(int i=0;i<code_len;i++) p_my_function[i]=pcode[i]^99;
}
//

At last, execute My_function in the STACK.

//
void Run_my_function()
{
    int x=1;//8
    int y=2;
    char str_a[]=" HELLO MY_FOUNCTION ! ";
    char str_b[]=" Hello my_function ! ";

    void* (__cdecl *_memcpy )( void *dest, const void *src, size_t count );
    int (__cdecl *_sprintf )( char *buffer, const char *format, ... );
    void* (__cdecl *_malloc )( size_t size );
    void (__cdecl *_free )( void *memblock );
    size_t (__cdecl *_strlen )( const char *string );
    int (__stdcall* _MessageBox)(HWND hWnd, LPCTSTR lpText, 
        LPCTSTR lpCaption, UINT uType);

    _memcpy=memcpy;
    _sprintf=sprintf;
    _malloc=malloc;
    _free=free;
    _strlen=strlen;
    _MessageBox=MessageBox;

    void ( __stdcall *_my_function)(int x,
        int y,
        char* str_a,
        char* str_b,
        void* (__cdecl *_memcpy )( void *dest, 
        const void *src, size_t count ),
        int (__cdecl *_sprintf )( char *buffer, const char *format, ... ),
        void* (__cdecl *_malloc )( size_t size ),
        void (__cdecl *_free )( void *memblock ),
        size_t (__cdecl *_strlen )( const char *string ),
        int (__stdcall* _MessageBox)(HWND hWnd, LPCTSTR lpText, 
        LPCTSTR lpCaption, UINT uType)
                                    );
    _my_function=(void ( __stdcall *)(int x,
        int y,
        char* str_a,
        char* str_b,
        void* (__cdecl *_memcpy )( void *dest, 
        const void *src, size_t count ),
        int (__cdecl *_sprintf )( char *buffer, const char *format, ... ),
        void* (__cdecl *_malloc )( size_t size ),
        void (__cdecl *_free )( void *memblock ),
        size_t (__cdecl *_strlen )( const char *string ),
        int (__stdcall* _MessageBox)(HWND hWnd, LPCTSTR lpText, 
        LPCTSTR lpCaption, UINT uType)
        )) &p_my_function[0];

    _my_function(x,
                 y,
                 str_a,
                 str_b,
                 _memcpy,
                 _sprintf,
                 _malloc,
                 _free,
                 _strlen,
                 _MessageBox
                 );
}
//

Summary

If you want to conceal crucial information, you shouldn't invoke the MessageBox API function. Certainly, the resistance of this protection is insignificant. However, it may be increased. There are numerous programming tips for this purpose, including dynamic asynchronous decoding, substituting the results of comparison for factors in various expressions, and placing the crucial part of code directly in the key. However self-generating code technology is so important that it has been adopted by Antidebug LIB. The purpose of this article is not to offer ready-to-use protection (which hackers could study), but to prove and show that it is possible theoretically to create self-generating code under the control of Windows. How to make use of this possibility is your task.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jim Charles


I have become a member of the forum for a long time,during the period,I have learnt a lot from it.
So I want to do something which will be useful to some software developers.I choose the software encryption field where there are a lot of rivals and huge challenges.There are so many hackers all over the world that no software can escape the doom of being cracked.And even almost everybody believe that it is impossible to protect their applications through the technology means.But I don't think so,I can find an applications protection solution and nobody can crack the software protected by it.My basic theory is that if the protected softwares or applications always occupy or depend on the essential resources of debugger when they are running,then it is impossible to be cracked.It's easier said than done.I have been working for a long time since I had the idea. When I have worked it out.I hope software developers to use it,then I try to write some articles which include crucial technology adopted by my solution in order to redound on the forum.Of course the source codes presented in the articles should be predigested and different from the source codes existing in my software protection solution.
However, Something attempted, something done --Longfellow.

Occupation: Chief Technology Officer
Company: AntiDebug LIB International Inc
Location: United States United States

Other popular Programming Tips articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 25 of 47 (Total in Forum: 47) (Refresh)FirstPrevNext
Subject  Author Date 
General..memberMurderDolls12:20 16 Jun '08  
QuestionExecuting Function Code in Heap/Stack Memorymembermaxtheterrible19:42 8 Jun '08  
AnswerRe: Executing Function Code in Heap/Stack MemorymemberJim Charles7:22 9 Jun '08  
QuestionRe: Executing Function Code in Heap/Stack MemorymemberMax Kukartsev12:58 9 Jun '08  
AnswerRe: Executing Function Code in Heap/Stack Memory [modified]memberJim Charles15:30 9 Jun '08  
GeneralRe: Executing Function Code in Heap/Stack MemorymemberMax Kukartsev6:32 10 Jun '08  
GeneraltnkmemberMurderDolls1:52 30 May '08  
GeneralRe: tnk [modified]memberMurderDolls14:02 4 Jun '08  
GeneralWindows Vista ErrormemberRoberto Loreto12:25 21 Apr '08  
GeneralRe: Windows Vista ErrormemberJim Charles20:31 21 Apr '08  
GeneralRe: Windows Vista ErrormemberLeonhardt Wille7:25 23 Apr '08  
GeneralRe: Windows Vista ErrormemberMystery12322:57 10 Jul '08  
GeneralRe: Windows Vista ErrormemberJim Charles3:23 11 Jul '08  
GeneralCool!! But not work in VISTA...¿?¿?memberRoberto Loreto12:16 21 Apr '08  
GeneralRe: Cool!! But not work in VISTA...¿?¿?memberJim Charles20:37 21 Apr '08  
GeneralRe: Cool!! But not work in VISTA...¿?¿?memberRoberto Loreto13:20 22 Apr '08  
GeneralDecode and then call a routine!membertydok4:48 25 Feb '08  
GeneralRe: Decode and then call a routine!memberJim Charles5:04 25 Feb '08  
GeneralRe: Decode and then call a routine!membertydok5:11 25 Feb '08