by Vrillon
I've noticed some custom made anti-cheats like to start a process from memory pointer rather than a
file for extra protection.
I wrote a little code a while back to do the same, for those who would like to know how to do so.
Código://-------------------------------------------------------- // Dynamic Process Forking of Portable Executable // Author : Vrillon / Venus // Date : 07/14/2008 //-------------------------------------------------------- /*********************************************************/ /* With this header, you can create and run a process */ /* from memory and not from a file. */ /*********************************************************/ #ifdef WIN32 #include#else #error Process Forking Requires a Windows Operating System #endif #include ///////////////////////////////////////////////////////////// // NtUnmapViewOfSection (ZwUnmapViewOfSection) // Used to unmap a section from a process. typedef long int (__stdcall* NtUnmapViewOfSectionF)(HANDLE,PVOID); NtUnmapViewOfSectionF NtUnmapViewOfSection = (NtUnmapViewOfSectionF)GetProcAddress(LoadLibrary("ntdll.dll"),"NtUnmapViewOfSection"); ///////////////////////////////////////////////////////////// // Fork Process // Dynamically create a process based on the parameter 'lpImage'. The parameter should have the entire // image of a portable executable file from address 0 to the end. bool ForkProcess(LPVOID lpImage) { // Variables for Process Forking long int lWritten; long int lHeaderSize; long int lImageSize; long int lSectionCount; long int lSectionSize; long int lFirstSection; long int lPreviousProtection; long int lJumpSize; bool bReturnValue; LPVOID lpImageMemory; LPVOID lpImageMemoryDummy; IMAGE_DOS_HEADER dsDosHeader; IMAGE_NT_HEADERS ntNtHeader; IMAGE_SECTION_HEADER shSections[512 * 2]; PROCESS_INFORMATION piProcessInformation; STARTUPINFO suStartUpInformation; CONTEXT cContext; // Variables for Local Process FILE* fFile; char* pProcessName; long int lFileSize; long int lLocalImageBase; long int lLocalImageSize; LPVOID lpLocalFile; IMAGE_DOS_HEADER dsLocalDosHeader; IMAGE_NT_HEADERS ntLocalNtHeader; ///////////////////////////////////////////////////////////////// // End Variable Definition bReturnValue = false; pProcessName = new char[MAX_PATH]; ZeroMemory(pProcessName,MAX_PATH); // Get the file name for the dummy process if(GetModuleFileName(NULL,pProcessName,MAX_PATH) == 0) { delete [] pProcessName; return bReturnValue; } // Open the dummy process in binary mode fFile = fopen(pProcessName,"rb"); if(!fFile) { delete [] pProcessName; return bReturnValue; } fseek(fFile,0,SEEK_END); // Get file size lFileSize = ftell(fFile); rewind(fFile); // Allocate memory for dummy file lpLocalFile = new LPVOID[lFileSize]; ZeroMemory(lpLocalFile,lFileSize); // Read memory of file fread(lpLocalFile,lFileSize,1,fFile); // Close file fclose(fFile); // Grab the DOS Headers memcpy(&dsLocalDosHeader,lpLocalFile,sizeof(dsLocalDosHeader)); if(dsLocalDosHeader.e_magic != IMAGE_DOS_SIGNATURE) { delete [] pProcessName; delete [] lpLocalFile; return bReturnValue; } // Grab NT Headers memcpy(&ntLocalNtHeader,(LPVOID)((long int)lpLocalFile+dsLocalDosHeader.e_lfanew),sizeof(dsLocalDosHeader)); if(ntLocalNtHeader.Signature != IMAGE_NT_SIGNATURE) { delete [] pProcessName; delete [] lpLocalFile; return bReturnValue; } // Get Size and Image Base lLocalImageBase = ntLocalNtHeader.OptionalHeader.ImageBase; lLocalImageSize = ntLocalNtHeader.OptionalHeader.SizeOfImage; // Deallocate delete [] lpLocalFile; // Grab DOS Header for Forking Process memcpy(&dsDosHeader,lpImage,sizeof(dsDosHeader)); if(dsDosHeader.e_magic != IMAGE_DOS_SIGNATURE) { delete [] pProcessName; return bReturnValue; } // Grab NT Header for Forking Process memcpy(&ntNtHeader,(LPVOID)((long int)lpImage+dsDosHeader.e_lfanew),sizeof(ntNtHeader)); if(ntNtHeader.Signature != IMAGE_NT_SIGNATURE) { delete [] pProcessName; return bReturnValue; } // Get proper sizes lImageSize = ntNtHeader.OptionalHeader.SizeOfImage; lHeaderSize = ntNtHeader.OptionalHeader.SizeOfHeaders; // Allocate memory for image lpImageMemory = new LPVOID[lImageSize]; ZeroMemory(lpImageMemory,lImageSize); lpImageMemoryDummy = lpImageMemory; lFirstSection = (long int)(((long int)lpImage+dsDosHeader.e_lfanew) + sizeof(IMAGE_NT_HEADERS)); memcpy(shSections,(LPVOID)(lFirstSection),sizeof(IMAGE_SECTION_HEADER)*ntNtHeader.FileHeader.NumberOfSections); memcpy(lpImageMemoryDummy,lpImage,lHeaderSize); // Get Section Alignment if((ntNtHeader.OptionalHeader.SizeOfHeaders % ntNtHeader.OptionalHeader.SectionAlignment) == 0) { lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders; } else { lJumpSize = (ntNtHeader.OptionalHeader.SizeOfHeaders/ntNtHeader.OptionalHeader.SectionAlignment); lJumpSize += 1; lJumpSize *= (ntNtHeader.OptionalHeader.SectionAlignment); } lpImageMemoryDummy = (LPVOID)((long int)lpImageMemoryDummy + lJumpSize); // Copy Sections To Buffer for(lSectionCount = 0; lSectionCount < ntNtHeader.FileHeader.NumberOfSections; lSectionCount++) { lJumpSize = 0; lSectionSize = shSections[lSectionCount].SizeOfRawData; memcpy(lpImageMemoryDummy,(LPVOID)((long int)lpImage + shSections[lSectionCount].PointerToRawData),lSectionSize); if((shSections[lSectionCount].Misc.VirtualSize % ntNtHeader.OptionalHeader.SectionAlignment)==0) { lJumpSize = shSections[lSectionCount].Misc.VirtualSize; } else { lJumpSize = (shSections[lSectionCount].Misc.VirtualSize/ntNtHeader.OptionalHeader.SectionAlignment); lJumpSize += 1; lJumpSize *= (ntNtHeader.OptionalHeader.SectionAlignment); } lpImageMemoryDummy = (LPVOID)((long int)lpImageMemoryDummy + lJumpSize); } ZeroMemory(&suStartUpInformation,sizeof(STARTUPINFO)); ZeroMemory(&piProcessInformation,sizeof(PROCESS_INFORMATION)); ZeroMemory(&cContext,sizeof(CONTEXT)); suStartUpInformation.cb = sizeof(suStartUpInformation); // Create Process if(CreateProcess(NULL,pProcessName,NULL,NULL,false,CREATE_SUSPENDED,NULL,NULL,&suStartUpInformation,&piProcessInformation)) { cContext.ContextFlags = CONTEXT_FULL; GetThreadContext(piProcessInformation.hThread,&cContext); // Check image base and image size if(lLocalImageBase == (long int)ntNtHeader.OptionalHeader.ImageBase && lImageSize <= lLocalImageSize) { VirtualProtectEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,PAGE_EXECUTE_READWRITE,(unsigned long*)&lPreviousProtection); } else { if(!NtUnmapViewOfSection(piProcessInformation.hProcess,(LPVOID)((DWORD)lLocalImageBase))) VirtualAllocEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE); } // Write Image to Process if(WriteProcessMemory(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lpImageMemory,lImageSize,(unsigned long*)&lWritten)) { bReturnValue = true; } // Set Image Base if(WriteProcessMemory(piProcessInformation.hProcess,(LPVOID)((long int)cContext.Ebx + 8),&ntNtHeader.OptionalHeader.ImageBase,4,(unsigned long*)&lWritten)) { if(bReturnValue == true) bReturnValue = true; } if(bReturnValue == false) { delete [] pProcessName; delete [] lpImageMemory; return bReturnValue; } // Set the new entry point cContext.Eax = ntNtHeader.OptionalHeader.ImageBase + ntNtHeader.OptionalHeader.AddressOfEntryPoint; SetThreadContext(piProcessInformation.hThread,&cContext); if(lLocalImageBase == (long int)ntNtHeader.OptionalHeader.ImageBase && lImageSize <= lLocalImageSize) VirtualProtectEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,lPreviousProtection,0); // Resume the process ResumeThread(piProcessInformation.hThread); } delete [] pProcessName; delete [] lpImageMemory; return bReturnValue; } ///////////////////////////////////////////////////////////// // Fork Process From Resource // Dynamically create a process from a resource file. bool ForkProcessFromResource(int iResource,char* pResourceSection) { HGLOBAL hResData; HRSRC hResInfo; LPVOID lpRes; LPVOID lpMemory; long int lSize; HMODULE hModule; bool bReturn; hModule = GetModuleHandle(0); bReturn = false; if(!hModule) return bReturn; hResInfo = FindResource(hModule, MAKEINTRESOURCE(iResource), pResourceSection); if(!hResInfo) { return bReturn; } hResData = LoadResource(hModule, hResInfo); if(!hResData) { return bReturn; } lpRes = LockResource(hResData); if(!lpRes) { FreeResource(hResData); return bReturn; } lSize = SizeofResource(hModule, hResInfo); lpMemory = new LPVOID[lSize]; ZeroMemory(lpMemory,lSize); memcpy (lpMemory, lpRes, lSize); bReturn = ForkProcess(lpMemory); FreeResource(hResData); delete [] lpMemory; return bReturn; }
Can be used like this:
Código:ForkProcess(pointer to executable memory); or ForkProcessFromResource(IDE_FILE1,"EXE"); (If you wanna load it from a resource)
0 comentarios:
Publicar un comentario