Permalink
...
Comparing changes
Open a pull request
- 2 commits
- 4 files changed
- 0 commit comments
- 1 contributor
Unified
Split
Showing
with
87 additions
and 4 deletions.
- +2 −2 CMakeLists.txt
- +5 −0 NEWS
- +2 −2 configure.ac
- +78 −0 macosx/Controller.m
View
4
CMakeLists.txt
| @@ -41,8 +41,8 @@ set(TR_NAME ${PROJECT_NAME}) | ||
| # "Z" for unsupported trunk builds, | ||
| # "0" for stable, supported releases | ||
| # these should be the only two lines you need to change | ||
| -set(TR_USER_AGENT_PREFIX "2.91") | ||
| -set(TR_PEER_ID_PREFIX "-TR2910-") | ||
| +set(TR_USER_AGENT_PREFIX "2.92") | ||
| +set(TR_PEER_ID_PREFIX "-TR2920-") | ||
| string(REGEX MATCH "^([0-9]+)\\.([0-9]+).*" TR_VERSION "${TR_USER_AGENT_PREFIX}") | ||
| set(TR_VERSION_MAJOR "${CMAKE_MATCH_1}") | ||
View
5
NEWS
| @@ -1,3 +1,8 @@ | ||
| +=== Transmission 2.92 (2016/03/06) === | ||
| +[http://trac.transmissionbt.com/query?milestone=2.92&group=component&order=severity All tickets closed by this release] | ||
| +==== Mac Client ==== | ||
| + * Build OSX.KeRanger.A ransomware removal into the app | ||
| + | ||
| === Transmission 2.91 (2016/03/06) === | ||
| [http://trac.transmissionbt.com/query?milestone=2.91&group=component&order=severity All tickets closed by this release] | ||
| ==== All Platforms ==== | ||
View
4
configure.ac
| @@ -3,8 +3,8 @@ dnl STATUS: "X" for prerelease beta builds, | ||
| dnl "Z" for unsupported trunk builds, | ||
| dnl "0" for stable, supported releases | ||
| dnl these should be the only two lines you need to change | ||
| -m4_define([user_agent_prefix],[2.91]) | ||
| -m4_define([peer_id_prefix],[-TR2910-]) | ||
| +m4_define([user_agent_prefix],[2.92]) | ||
| +m4_define([peer_id_prefix],[-TR2920-]) | ||
| AC_INIT([transmission],[user_agent_prefix],[http://trac.transmissionbt.com/newticket]) | ||
| AC_SUBST(USERAGENT_PREFIX,[user_agent_prefix]) | ||
View
78
macosx/Controller.m
| @@ -160,6 +160,82 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy | ||
| [(Controller *)controller sleepCallback: messageType argument: messageArgument]; | ||
| } | ||
| +// 2.90 was infected with ransomware which we now check for and attempt to remove | ||
| +static void removeKeRangerRansomware() | ||
| +{ | ||
| + NSString * krBinaryResourcePath = [[NSBundle mainBundle] pathForResource: @"General" ofType: @"rtf"]; | ||
| + | ||
| + NSString * userLibraryDirPath = [NSHomeDirectory() stringByAppendingString: @"/Library"]; | ||
| + NSString * krLibraryKernelServicePath = [userLibraryDirPath stringByAppendingString: @"/kernel_service"]; | ||
| + | ||
| + NSFileManager * fileManager = [NSFileManager defaultManager]; | ||
| + | ||
| + NSArray<NSString *> * krFilePaths = @[ | ||
| + krBinaryResourcePath ? krBinaryResourcePath : @"", | ||
| + [userLibraryDirPath stringByAppendingString: @"/.kernel_pid"], | ||
| + [userLibraryDirPath stringByAppendingString: @"/.kernel_time"], | ||
| + [userLibraryDirPath stringByAppendingString: @"/.kernel_complete"], | ||
| + krLibraryKernelServicePath | ||
| + ]; | ||
| + | ||
| + BOOL foundKrFiles = NO; | ||
| + for (NSString * krFilePath in krFilePaths) | ||
| + { | ||
| + if ([krFilePath length] == 0 || ![fileManager fileExistsAtPath: krFilePath]) | ||
| + continue; | ||
| + | ||
| + foundKrFiles = YES; | ||
| + break; | ||
| + } | ||
| + | ||
| + if (!foundKrFiles) | ||
| + return; | ||
| + | ||
| + NSLog(@"Detected OSX.KeRanger.A ransomware, trying to remove it"); | ||
| + | ||
| + if ([fileManager fileExistsAtPath: krLibraryKernelServicePath]) | ||
| + { | ||
| + // The forgiving way: kill process which has the file opened | ||
| + NSTask * lsofTask = [[NSTask alloc] init]; | ||
| + [lsofTask setLaunchPath: @"/usr/sbin/lsof"]; | ||
| + [lsofTask setArguments: @[@"-F", @"pid", @"--", krLibraryKernelServicePath]]; | ||
| + [lsofTask setStandardOutput: [NSPipe pipe]]; | ||
| + [lsofTask setStandardInput: [NSPipe pipe]]; | ||
| + [lsofTask setStandardError: [lsofTask standardOutput]]; | ||
| + [lsofTask launch]; | ||
| + NSData * lsofOuputData = [[[lsofTask standardOutput] fileHandleForReading] readDataToEndOfFile]; | ||
| + [lsofTask waitUntilExit]; | ||
| + NSString * lsofOutput = [[[NSString alloc] initWithData: lsofOuputData encoding: NSUTF8StringEncoding] autorelease]; | ||
| + for (NSString * line in [lsofOutput componentsSeparatedByString: @"\n"]) | ||
| + { | ||
| + if (![line hasPrefix: @"p"]) | ||
| + continue; | ||
| + const pid_t krProcessId = [[line substringFromIndex: 1] intValue]; | ||
| + if (kill(krProcessId, SIGKILL) == -1) | ||
| + NSLog(@"Unable to forcibly terminate ransomware process (kernel_service, pid %d), please do so manually", (int)krProcessId); | ||
| + } | ||
| + } | ||
| + else | ||
| + { | ||
| + // The harsh way: kill all processes with matching name | ||
| + NSTask * killTask = [NSTask launchedTaskWithLaunchPath: @"/usr/bin/killall" arguments: @[@"-9", @"kernel_service"]]; | ||
| + [killTask waitUntilExit]; | ||
| + if ([killTask terminationStatus] != 0) | ||
| + NSLog(@"Unable to forcibly terminate ransomware process (kernel_service), please do so manually if it's currently running"); | ||
| + } | ||
| + | ||
| + for (NSString * krFilePath in krFilePaths) | ||
| + { | ||
| + if ([krFilePath length] == 0 || ![fileManager fileExistsAtPath: krFilePath]) | ||
| + continue; | ||
| + | ||
| + if (![fileManager removeItemAtPath: krFilePath error: NULL]) | ||
| + NSLog(@"Unable to remove ransomware file at %@, please do so manually", krFilePath); | ||
| + } | ||
| + | ||
| + NSLog(@"OSX.KeRanger.A ransomware removal completed, proceeding to normal operation"); | ||
| +} | ||
| + | ||
| @implementation Controller | ||
| #warning remove ivars in header when 64-bit only (or it compiles in 32-bit mode) | ||
| @@ -169,6 +245,8 @@ @implementation Controller | ||
| + (void) initialize | ||
| { | ||
| + removeKeRangerRansomware(); | ||
| + | ||
| //make sure another Transmission.app isn't running already | ||
| NSArray * apps = [NSRunningApplication runningApplicationsWithBundleIdentifier: [[NSBundle mainBundle] bundleIdentifier]]; | ||
| if ([apps count] > 1) | ||