summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-10-16 21:12:02 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-10-16 21:12:02 +0000
commit92d7b0659edd025093f71e15a87bb1b8e5218aca (patch)
treef624d98fdcd7bb25441d8689989b08a10b48904c /protocols
parent0e622404fe197f1ecf1c0f1857bff0b5be58b0b1 (diff)
added starting process from memory
git-svn-id: http://svn.miranda-ng.org/main/trunk@1967 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Skype/res/Resource.rc2
-rw-r--r--protocols/Skype/src/skype.cpp301
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);