About the “tpwn” Local Privilege Escalation

Note: “Attacking XNU For Fun And Profit” blog posts are suspended indefinitely. I’ll talk about the post-10.11 world in a talk at BlackHat AMS 2015.

This post had to come out two weeks ago, but due to school exams I haven’t had the time to write this down.

So, tpwn gains root on any OS X box running a system <= 10.10.5 by gaining knowledge of the kernel address space layout randomisation slide followed by kernel code execution kickstarting a stack pivot which allows me to control the stack pointer of a kernel thread belonging to a controlled task.

Missing Checks

is_io_service_open_extended does not check whether the task_t* pointer passed by the MIG subsystem is NULL or not.

Our journey begins with IOServiceOpen. This is the definition of this IOKit function that allows you to “connect” to an IOUserClient.

kern_return_t IOServiceOpen ( io_service_t service, task_port_t owningTask, uint32_t type,io_connect_t *connect );

This function will use MIG to tell the kernel to call io_open_service_extended, like this (in osfmk/device/device.defs):

routine io_service_open_extended(
	    service		: io_object_t;
	in  owningTask		: task_t;
	in  connect_type	: uint32_t;
	in  ndr			: NDR_record_t;
	in  properties		: io_buf_ptr_t, physicalcopy;
        out result		: kern_return_t;
	out connection		: io_connect_t

As you can see, from user land you pass in an io_service_t (mach_port_t), a task_port_t (mach_port_t) and an uint32_t, and kernel land gets an io_object_t*, a task_t*, and an uint32_t (along with some other stuff passed in by IOKitLib from userland).

The conversion between a mach port into the desired kernel type is handled by MIG like this (at least for the “task_t” type):

type task_t = mach_port_t
		intran: task_t convert_port_to_task(mach_port_t)
		outtran: mach_port_t convert_task_to_port(task_t)
		destructor: task_deallocate(task_t)
#endif	/* KERNEL_SERVER */


Mach ports hold a “kobject” value which is a pointer to some data it references in-kernel. This kobject value is typed, which means that technically you cannot pass in a mach port with a certain kobject type to a function which expects a different kobject type.

Of course, convert_port_to_task is a good boy: if the kobject type is not IKOT_TASK, it returns NULL.

convert_port_to_task(ipc_port_t	port)
	task_t		task = TASK_NULL;
	if (ip_kotype(port) == IKOT_TASK) {
		task = (task_t)port->ip_kobject;
	return (task);


So, if you call IOServiceOpen with a mach port whose kobject type is not IKOT_TASK, is_io_service_open_extended is called with a NULL ‘owningTask’ parameter, and before 10.11 “El Captain” is_io_service_open_extended did not perform any check on wether the task is NULL or not, allowing NULL to be passed down to whatever IOUserClient has been opened (this is bug 1, CVE-2015-????).

Mapping NULL

NULL is not a special pointer, although modern OSes will prevent you from mapping memory over there.

Mac OS X does this via a — __PAGEZERO segment in every MH_EXECUTE Mach-O.

This segment “reserves” memory in the NULL page (up to 0x100000000 on x86_64 systems) and makes it impossible to map. The kernel enforces this on OS X, but 32 bit binaries are not required to have a __PAGEZERO segment for compatibility reasons I believe.

Binaries lacking __PAGEZERO are fully free to map the NULL page, allowing us to fully control the data.

Memory Corruption

The following code will run when a new IOHDIXControllerUserClient is created via an is_io_service_open_extended call:

Screen Shot 2015-09-02 at 01.25.52

As you can see, it calls bsd_set_dependency_capable passing in the task value it gets from the caller without checking if it equals to NULL.

void bsd_set_dependency_capable(task_t task)
    proc_t p = get_bsdtask_info(task);
    if (p) {
        OSBitOrAtomic(P_DEPENDENCY_CAPABLE, &p->p_flag);

It translates (on 10.10 XNU at least), into:

task->bsd_info->p_flag |= P_DEPENDENCY_CAPABLE;

Since “task” equals NULL, by mapping NULL in userland, this function will read from userland memory(!) a pointer (task->bsd_info), dereferences it (->p_flag), treating the resulting pointer as an integer which will be ORed ( |= ) to 0x00100000 (P_DEPENDENCY_CAPABLE). Since we have full control of the pointer, this can be considered an OR 0x10 primitive. This is done in kernel, which means you can potentially corrupt kernel memory!

You’re starting to get the picture?

Meaningful Corruption

But what do we corrupt, exactly? First of all, there’s kASLR. Then kernel __TEXT, which is R-X. Kernel __DATA is RW-, but e.g. syscalls are in the ‘const’ section. Furthermore, our corruption allows us to |= 0x10; any byte in kernel memory. Not exactly a write-what-where. Thankfully, if you paid attention to my last two blog posts attacking the heap is where all the fun is at these days. We’ll need just a couple things first: a pointer to something in the heap, and that something must be something that gets us some sort of meaningful undefined behaviour thanks to our corruption.

P.S. In “tpwn” I decided to perform multiple corruptions for the exploit, but this is un-needed, and it was done just because in this case it provided mathematically provable 100% reliability.

IOAudioEngineUserClient to the rescue!

Thankfully, IOAudioEngineUserClient has a solution for us! It exposes a very handy method to retrieve a “connection ID”.

IOReturn IOAudioEngineUserClient::getConnectionID(UInt32 *connectionID)
    audioDebugIOLog(3, "+-IOAudioEngineUserClient[%p]::getConnectionID(%p)\n", this, connectionID);

    *connectionID = (UInt32) (((UInt64)this >> 8) & 0x00000000FFFFFFFFLLU) ;
    return kIOReturnSuccess;

This ID is derived by the “this” pointer, but it is not sufficiently obfuscated. In fact, thanks to canonical addressing and memory alignment, it is not obfuscated at all.

Any kernel-land pointer is negative, and due to canonical addressing this means that the first 24 bits are known to be “0xFFFFFF”.

Any memory allocation in a zone bigger than 0x100 will have the last 8 bits known to be “0x00”.
IOAudioEngineUserClient fits in an allocation from the kalloc.1024 zone, so 0x400 bytes in size.

Interestingly enough, all other missing bits are our very own connection ID! Thanks IOAudioEngine! (this is bug 2, CVE-2015-????).

    // from tpwn/main.m's leak_heap_ptr
    uint64_t    scalarO_64=0;
    uint32_t    outputCount = 1;
    IOConnectCallScalarMethod(*co, 2, NULL, 0, &scalarO_64, &outputCount);
    if (!scalarO_64) {
        puts("failed infoleaking");
    scalarO_64 <<= 8;
    scalarO_64 |=  0xffffff0000000000;

This is a C++ object residing in a RW- page, in an allocation from the kalloc.1024 zone! We can create allocations, free them and leak their pointers at will, which allows us to keep trying until we get two adjacent allocations. By freeing the first allocation and re-allocating a vm_map_copy structure into the newly poked hole, we now have a vm_map_copy adjacent to a C++ object, or more precisely, an IOAudioEngineUserClient object.

Give my “Attacking XNU For Fun And Profit Part 2” post a read.

Since we can control the size of our kernel allocation from userland, we can make sure that the |= 0x10 really means += 0x10 by making sure size AND 0x10 == 0, in turn allowing us to read the first 16 bytes of the adjacent allocation. The adjacent allocation, again, is a C++ object. First 8 bytes of said allocation is a pointer to the vtable of our object, which resides in a kernel extension’s __TEXT/const __DATA segment.

We can analyse the kernel extension’s symbol table to find out the pointer to the IOAudioEngineUserClient vtable, find out the unslid address of said kernel extension in kernel address space, add the two to find out the unslid address of said vtable. Since we also know the slid address (thanks to our vm_map_copy corruption), by subtracting the two we can find out the kaslr slide which allows us to know the address space layout and allows us to re-use code inside the kernel’s __TEXT, to bypass SMEP.

Gaining RIP Control

There are many ways to do this, but I decided to use a specific execution vector which gives us provable 100% reliability, and is specific to IOAudioEngineUserClient. Since we can corrupt memory at will and we know a pointer to an IOAudioEngineUserClient, by changing a NULL pointer to a C++ object into a 0x10 pointer to a C++ object, said object can be controlled. In our case, a static method will be called on said object, so hijacking the vtable is useless. However, said static method will release a reference to an object, and does so by calling object->release();, which is a vcall. By controlling the pointer to said object, you can make sure the call reads the vtable pointer from userland memory, allowing you to control two registers. One is the pointer to our fake vtable, usually stored in RAX, the other is RIP, which can just point to a stack pivot allowing you to set RSP = RAX, and run a small chain which transfers control to a full chain. My chain sets current task’s uid = 0, which gives the tpwn process root privileges. system(“/bin/sh”) spawns a shell.


— Luca ‘qwertyoruiop’ Todesco for Kim Jong Cracks Research.

Shout out @jk9357 for the new coming soon KJC track!

44 thoughts on “About the “tpwn” Local Privilege Escalation

  1. I found your gwegpegmn weblog web site on google and examine just a few of your early posts. Continue to keep up the excellent operate. I simply additional up your RSS feed to my MSN Information Reader. Looking for ahead to reading extra from you in a while!…

  2. you are in reality a good webmaster. The site loading speed is amazing. It seems that you are doing any unique trick. Moreover, The contents are masterpiece. you’ve done a fantastic job on this matter!

  3. Saya tidak bahkan memahami bagaimana akhirnya aku up di
    sini, tapi saya pikir ini mengirimkan adalah baik.

    Saya tidak mengenali yang Anda tapi pasti Anda akan terkenal
    terkenal blogger ketika Anda tidak sudah. Cheers!

  4. Apakah Anda pernah berpikir tentang dianggap penerbitan sebuah ebook atau authoring
    tamu di lain situs? Aku punya blog berdasarkan pada yang sama informasi Anda membahas dan akan benar-benar seperti untuk memiliki
    Anda berbagi beberapa cerita / informasi. Saya tahu saya pemirsa akan menghargai pekerjaan Anda.
    Jika Anda bahkan jauh tertarik, jangan ragu untuk menembak saya sebuah e mail.

  5. We specialize in large trays for ot tomans.

    Our trays are handmade with care
    for the highest quality possible! We offer ottoman trays in a
    number of styles and finishes.
    We can also do any custom stain or any custom color you need.
    Square Trays – Any Size

    Octagon Trays – Great for round ottomans
    Rectangular Trays – Any Dimension for a perfect fit on your ottoman

    round ottoman tray,large round ottoman tray,extra large trays for ottomans,
    wood tray for ottoman tray,large ottoman tray,
    round tray for ottoman tray,ottoman coffee table tray,table tray ottoman,coffee table tray,
    ottoman trays large,large tray to put on ottoman,trays for ottomans,
    decorative trays for ottomans,tray for ottoman coffee table,coffee
    table tray ottoman
    ,black ottoman tray,large round tray,custom ottoman tray,round ottoman trays,
    tray for ottoman,extra large trays,ottoman tray,large trays,ottoman tray table,
    wooden tray for ottoman,large wooden ottoman tray,tray table for
    large trays for ottomans,extra large tray for ottoman,large ottoman serving
    large round tray for ottoman,trays for ottoman,large tray for ottoman,big tray for ottoman,
    large serving trays for ottomans,large decorative
    trayfor ottoman,large tray for coffee table,
    cocktail ottoman tray

  6. My family members always say that I am killing
    my time here at web, except I know I am getting experience everyday by reading such pleasant
    articles or reviews.

  7. You really make it seem so easy together with your presentation but I to find this topic to be really one thing which I
    feel I’d never understand. It sort of feels too complicated and extremely broad for me.
    I am looking forward in your next submit, I will
    try to get the grasp of it!

  8. After I originally left a comment I appear to have clicked the
    -Notify me when new comments are added- checkbox and from now
    on whenever a comment is added I recieve four emails with the exact same comment.
    Is there an easy method you can remove me from that
    service? Thank you!

  9. I am really enjoying the theme/design of your weblog. Do you ever run into any browser compatibility problems?
    A few of my blog readers have complained about my blog not working correctly in Explorer
    but looks great in Safari. Do you have any recommendations to help fix this issue?

  10. De enige manier is om e-mails te verzenden en wacht op antwoord in de
    komende dagen. Vergeet niet langer de exploitatievorm
    aangeschafte hoogste opbrengst. Het had een klein LCD-display, waaruit bleek dat
    een aantal bescheiden cijfergegevens.

  11. 初めまして


  12. you are in point of fact a just right webmaster.
    The site loading pace is amazing. It kind of feels that you are doing
    any distinctive trick. Moreover, The contents are masterwork.
    you’ve performed a wonderful job in this matter!

  13. Sweetheart necklines flatter almost any chest or neck
    and they can look quite becoming on almost any young lady.
    V-Neck Cotton Sateen Dress with Pleats and Ruching.
    While the online marketplace offers a wide range of organic styles,
    don’t forget another green choice: reusing maternity clothes from others or found at thrift stores.
    She paired her dress with Sergio Rossi shoes and accessorized with Tacori jewels.
    Many convertible bras have removable straps, so you may
    have one in your lingerie collection already that will work.
    Nowadays, there are lots of online fashion stocks that sell newest party and wedding dresses cheap for men and women alike.
    The bodice and waist are ruched to make a slimming and figure flatteringbody.

  14. Jetzt scheint
    die Spezialisierung in dieser Handchirurgie
    neue Entwicklungsmöglichkeiten bei Chip Medizinische Versorgung
    dieser rheumatoiden Arthritis zu lancieren. Die
    operativen Verfahrensweise der frühen Synovektomie
    zur Therapie und Arthroplastien obendrein
    Sehnenumlagerungen zur Rehabilitation,
    sind in diesem Zusammenhang gute Resultate zu gefügig.
    Zusammenwirken in unserer Klinik inmitten
    den Rheumatologen im Übrigen Plastischen
    Chirurgen führt zu zahlreichen Patienten
    mit böse deformierten Händen, der Handchirurg
    hat Chip Anlage deren Durch nichts aufzuheitern sein zu
    dämpfen. Chip ulnare Deviation der Handglied
    ist eine welcher häufigsten ‚krüppelhaftesten‘
    Deformitäten. Jene beginnt anhand Impotenz
    des Zeigefingers beim Spitzgriff versus Chip
    zufolge ulnar drückenden, deformierenden
    Kräfte zu funktionieren. Entzündliche Ausdehnung
    dieser Gruppieren welcher Fingergrundgelenke, beginnend
    mit dem Zeigefinger, gefolgt von Seiten den
    Anderen, missgebildet nach und nach Chip Gelenke.
    Sehnenumlagerung im Übrigen Rekonvaleszenz
    der Seitenbänder betragen eine einzig und allein
    vorübergehende Veredelung.
    Abschließend folgt die Beschreibung der 1959
    von Bäckdahl neben Myrin (1961) begonnenen stabilisierenden
    Osteoplastiken des Weiteren der 1963 von Seiten
    Bäckdahl veröffentlichten Studie durch dies „Caput
    ulnaris Syndrom“.
    Bei Deutsche Mark gesamten Schriften des Vortrages vonseiten
    Ragnell (1901–1984) handelt es einander um Chip
    wie Dankfest pro seinen Lehrer gehaltene „Gillies
    Memorial Lecture“, Chip 1965 am „University
    College Oxford“ im Juli 1964 an dem „Summer
    Meeting“ welcher „British Association of Plastic
    Surgeons“ gehalten wurde. Diese wird dabei zum wiederholten Male
    zitiert, ebenso weil selbige aus in… lange vergangener
    (zeitlicher) Abstand den humanistischen Denkfähigkeit der akademischen
    Brauch solcher hippokratischen Plastischen
    Chirurgie beweist. Zu erhoffen ist, dass
    dieser Spuk für Chip gesamte Plastische Rekonstruktive
    u. a. Ästhetische Chirurgie „in Gleichzeitigkeit
    von Imperfekt obendrein Zukunft“ Lagerbestand
    haben wird.

  15. Hmm it appears like your blog ate my first comment (it was super long) so I guess I’ll just sum it up what
    I had written and say, I’m thoroughly enjoying your blog.
    I too am an aspiring blog blogger but I’m still new
    to the whole thing. Do you have any helpful hints for beginner blog writers?
    I’d really appreciate it.

  16. Alsdann Zustandekommen Chip traumatische
    Entzündung, die Arten der Wundheilung darüber hinaus
    Gewebsneubildung im Allgemeinen überdies
    Speziellen je nach dem damaligen Wissensstand
    beschrieben : Bindegewebe, Phagozyten,
    Plasma- ebenso Riesenzellen, Fettgewebe,
    elastische Fasern, Gefäße des Weiteren Epithel.
    gleicher Ordnungsprinzip Werden Chip Prozesse
    welcher Wundheilung nach Durchtrennung ebenso wie
    Transplantation solcher in den serösen Hüllen
    gelegenen Hohlorgane noch dazu einzelner Gewebe
    (Haut, Sehnen, Knorpel, Knochen, u. a.
    Knochenmark, Nerven, Muskeln und Drüsen)
    – basierend gen Chip systematisch erarbeiteten
    eigenen Resultate – aus pathologischanatomischer
    auch weil klinischer Blick dargestellt
    ebenso entscheidend erörtert.
    In Kap. 19 geht es um Chip „Die Verpflanzung
    seitens Haut nach Reverdin darüber hinaus Thiersch“
    (S. 400):
    » Dieser grösste Fortschritt in der Praktischen
    Nutzbarmachung dieser Ueberpflanzung über und über
    abgetrennter Theile wurde anhand Chip seitens
    Jaques L. Reverdin eingeführte Epidermispfropfung,
    „greffe epidermique“, ins Leben
    gerufen … er trug essentiell zur Aufklärung
    des indem zu erzielenden Heilungsvorganges
    bei, des Weiteren ermöglichte dabei Chip darauf
    infolge Thiersch eingeführte Neuorientierung des
    Verfahrens jener künstlichen Ueberhäutung.

  17. Creditors сurrently ɗon’t gіve mսch leeway for
    debtors wҺߋ falⅼ bеhind on the bills.
    Εven as the method cߋntinues and you alsߋ shօw a willingness tto behave tߋ foreestall it tthe judge mmay
    аlso adjourn tɦe situatin to offer an opportunity to sell your house аnd pay up
    yoᥙr mortgage arrears. Ɗo all you arе abl to safeguard yօurself
    from house repossessions аѕ you wіll sincerely regret dоing

  18. 自毛植毛とは、頭部の後ろにある自分の毛髪を、薄毛の部分に移植することで薄くなった部分を解消する治療法です。 植毛には、ハゲの大きな要因とされるAGAに適しています。 うまく定着すればその後の成長も見込めます。 また、あなたの毛髪であるため人工毛のように拒絶反応を起こすことがなく、定着率も人口毛髪に比べ高いです。



  19. どうもです~

  20. If you’ve got flexibility, attempt to wait foor a promotion with
    low interest. The best two wheelers in India are given in these reviess wherein their specifications,
    prices along with the comments from the cuustomers are mentioned in details.
    For people who find themselves very selective
    concerning the kind of automobile they will really want car shopping is an important endeavor.

  21. This is a very good tip especially to those fresh to the blogosphere.

    Brief but very accurate information… Appreciate your sharing this one.
    A must read post!

Leave a Reply

Your email address will not be published. Required fields are marked *