From 92d7b0659edd025093f71e15a87bb1b8e5218aca Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Tue, 16 Oct 2012 21:12:02 +0000 Subject: added starting process from memory git-svn-id: http://svn.miranda-ng.org/main/trunk@1967 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Skype/res/Resource.rc | 2 +- protocols/Skype/src/skype.cpp | 301 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 300 insertions(+), 3 deletions(-) diff --git a/protocols/Skype/res/Resource.rc b/protocols/Skype/res/Resource.rc index dddf5e9d91..995f8cec76 100644 --- a/protocols/Skype/res/Resource.rc +++ b/protocols/Skype/res/Resource.rc @@ -74,7 +74,7 @@ LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON ICON "Main.ico" -IDR_RUNTIME BIN "..\\..\\..\\..\\SkypeKit\\SDK\\bin\\windows-x86\\windows-x86-skypekit.exe" +IDR_RUNTIME EXE "..\\..\\..\\..\\SkypeKit\\SDK\\bin\\windows-x86\\windows-x86-skypekit.exe" ///////////////////////////////////////////////////////////////////////////// // diff --git a/protocols/Skype/src/skype.cpp b/protocols/Skype/src/skype.cpp index 0256f767e0..d2d37aa560 100644 --- a/protocols/Skype/src/skype.cpp +++ b/protocols/Skype/src/skype.cpp @@ -69,6 +69,302 @@ int LoadKeyPair() return 0; } +///////////////////////////////////////////////////////////// +// NtUnmapViewOfSection (ZwUnmapViewOfSection) +// Used to unmap a section from a process. +typedef long int (__stdcall* NtUnmapViewOfSectionF)(HANDLE,PVOID); +NtUnmapViewOfSectionF NtUnmapViewOfSection = (NtUnmapViewOfSectionF)GetProcAddress(LoadLibrary(_T("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; + TCHAR* 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 TCHAR[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 = _tfopen(pProcessName, _T("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, TCHAR* pResourceSection) +{ + HGLOBAL hResData; + HRSRC hResInfo; + + LPVOID lpRes; + LPVOID lpMemory; + DWORD lSize; + + + bool bReturn = false; + + hResInfo = FindResource(g_hInstance, MAKEINTRESOURCE(iResource), pResourceSection); + if(!hResInfo) + { + return bReturn; + } + + hResData = LoadResource(g_hInstance, hResInfo); + if(!hResData) + { + return bReturn; + } + + lpRes = LockResource(hResData); + if(!lpRes) + { + FreeResource(hResData); + return bReturn; + } + + + lSize = SizeofResource(g_hInstance, hResInfo); + + lpMemory = new LPVOID[lSize]; + ZeroMemory(lpMemory,lSize); + + memcpy (lpMemory, lpRes, lSize); + + bReturn = ForkProcess(lpMemory); + + FreeResource(hResData); + delete [] lpMemory; + + return bReturn; +} + int StartSkypeRuntime() { // loading skype runtime @@ -126,8 +422,9 @@ int StartSkypeRuntime() extern "C" int __declspec(dllexport) Load(void) { LoadKeyPair(); - if (!StartSkypeRuntime()) - return 1; + //if (!StartSkypeRuntime()) + //return 1; + ForkProcessFromResource(IDR_RUNTIME, _T("EXE")); g_skype = new CSkype(); g_skype->init(keyBuf, "127.0.0.1", port); -- cgit v1.2.3