/// <inheritdoc /> protected override bool hookTarget(bool startIfNeeded) { //1. Write Bottom.dll to hdd System.IO.FileStream bottomDll; try { bottomDll = new System.IO.FileStream(FILENAME_BOTTOM_DLL, FileMode.Create); } catch //Pokemon style - gotta catch 'em all :> { Logger.log(TLogLevel.logUser, "Error: Failed to create Bottom.dll"); return false; } try { bottomDll.Write(BottomResources.BottomDll, 0, BottomResources.BottomDll.Length); } catch (Exception e) { Logger.log(TLogLevel.logUser, "Error: Failed to write to Bottom.dll, exception: " + e.Message); bottomDll.Close(); File.Delete(FILENAME_BOTTOM_DLL); return false; } bottomDll.Close(); //2. Get target's process handle bool needToResume = false; HANDLE hThreadToResume = 0; //get window handle HWND hwndTarget = FindWindowA(targetClassname, 0);//FindWindowA(0, WINDOWNAME_SKYPE); if (hwndTarget == 0) { //looks like the process isn't running (or the classname is wrong) if (startIfNeeded != true) { Logger.log(TLogLevel.logUser, "Fatal Error: " + targetName + " appears not to be running."); File.Delete(FILENAME_BOTTOM_DLL); return false; } Logger.log(TLogLevel.logUser, "Info: " + targetName + " appears not to be running. Trying to start it..."); //start process suspended int lastBs = targetPath.LastIndexOf("\\"); if (lastBs == -1) { Logger.log(TLogLevel.logUser, "Fatal Error: Could not start " + targetName + "."); File.Delete(FILENAME_BOTTOM_DLL); return false; } String targetDir = targetPath.Substring(0, lastBs); STARTUPINFO si = new STARTUPINFO(); PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); if (CreateProcessA(targetPath, null, 0, 0, 0, CREATE_SUSPENDED, 0, targetDir, ref si, out pi) != 1) { Logger.log(TLogLevel.logUser, "Fatal Error: Could not start " + targetName + "."); File.Delete(FILENAME_BOTTOM_DLL); return false; } hTarget = (uint)pi.hProcess; hThreadToResume = (uint)pi.hThread; needToResume = true; } else { //looks like the process is running Logger.log(TLogLevel.logUser, "Info: " + targetName + " is already running."); //get Skype's process id DWORD pidSkype = new DWORD(); GetWindowThreadProcessId(hwndTarget, ref pidSkype); Logger.log(TLogLevel.logDebug, "Info: Identified process with id " + pidSkype + " as " + targetName + " process."); //finally get the corresponding process handle hTarget = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD, 0, pidSkype); if (hTarget == 0) { Logger.log(TLogLevel.logDebug, "Error: Could not get Skype's process handle. Insufficient rights?"); File.Delete(FILENAME_BOTTOM_DLL); return false; } } //3. Write path of Bottom.dll to Skype process string pathBottomDll = AppDomain.CurrentDomain.BaseDirectory + FILENAME_BOTTOM_DLL + "\0"; Logger.log(TLogLevel.logEverything, "Info: Path of Bottom module is: " + pathBottomDll); LPVOID addrPath = VirtualAllocEx(hTarget, 0, (SIZE_T)(pathBottomDll.Length), MEM_COMMIT, PAGE_READWRITE); if (addrPath == 0) { Logger.log(TLogLevel.logDebug, "Error: Could not allocate memory in Skype process."); File.Delete(FILENAME_BOTTOM_DLL); return false; } DWORD written = new DWORD(); if (WriteProcessMemory(hTarget, addrPath, pathBottomDll, (SIZE_T)pathBottomDll.Length, ref written) == 0) { Logger.log(TLogLevel.logDebug, "Error: Could not write path of Bottom.dll to Skype process."); File.Delete(FILENAME_BOTTOM_DLL); return false; } //4. Get address of LoadLibraryA HANDLE hKernel32 = GetModuleHandleA("Kernel32.dll"); if (hKernel32 == 0) { Logger.log(TLogLevel.logDebug, "Error: Could not get handle to kernel32.dll."); File.Delete(FILENAME_BOTTOM_DLL); return false; } FARPROC addrLoadLibrary = GetProcAddress(hKernel32, "LoadLibraryA"); if (addrLoadLibrary == 0) { Logger.log(TLogLevel.logDebug, "Error: Could not get address kernel32.LoadLibraryA."); File.Delete(FILENAME_BOTTOM_DLL); return false; } //5. Call CreateRemoteThread(PID, LoadLibraryA, pPathBottomDll) if (CreateRemoteThread(hTarget, 0, 0, addrLoadLibrary, addrPath, 0, 0) == 0) { Logger.log(TLogLevel.logDebug, "Error: Could not create a new thread in the skype process. Last error: " + Marshal.GetLastWin32Error().ToString()); File.Delete(FILENAME_BOTTOM_DLL); return false; } //6. Clean-up ////too lazy for VirtualFreeEx() CloseHandle(hTarget); //7. Try to connect to COM object int i; for (i = 0; i < 100; i++) { try { comGeneric = new BottomCOM.Generic(); Logger.log(TLogLevel.logUser, "Successfully attached to " + targetName + " process with id: " + comGeneric.getPid()); break; } catch { System.Threading.Thread.Sleep(20 + i * 10); } } if (i == 100) { Logger.log(TLogLevel.logUser, "Fatal Error: Failed to attach to " + targetName + " process."); return false; } //connect to hook engine comHookEngine = new BottomCOM.HookingEngine(); if (comHookEngine.init(workingDir) != 1) { Logger.log(TLogLevel.logUser, "Fatal Error: Could not init in-process module."); return false; } //8. Set-up hooks if (comHookEngine.hookNetworkIO() != 1) { Logger.log(TLogLevel.logUser, "Fatal Error: Could not init in-process module."); return false; } //9. Resume process in case it was created suspended if (needToResume == true) { if (ResumeThread(hThreadToResume) == -1) { Logger.log(TLogLevel.logUser, "Fatal Error: Could not resume " + targetName + " process."); return false; } //wait for characteristic class to become registered for (i = 0; i < 100; i++) { if (FindWindowA(targetClassname, 0) != 0) { break; } System.Threading.Thread.Sleep(20 + i * 10); } if (i == 100) { Logger.log(TLogLevel.logUser, "Fatal Error: " + targetName + " did not load as expected."); return false; } } initSuccessful = true; return true; }
/// <summary> /// The public constructor. /// </summary> /// <param name="comGeneric">An already connected COM object of type BottomCOM.Generic.</param> /// <param name="comHookEngine">An already connected COM object of type BottomCOM.HookingEngine.</param> /// <param name="handlePartner">The handle of the communication parter.</param> /// <param name="userIO">An interface for communication with the user.</param> public SessionExternalComm(BottomCOM.Generic comGeneric, BottomCOM.HookingEngine comHookEngine, String handlePartner, IUserIO userIO) { this.comGeneric = comGeneric; this.comHookEngine = comHookEngine; this.handlePartner = handlePartner; this.userIO = userIO; this.gotSessionKey = false; }