kxploit 660 revisit

Note from Wololo, a bit of context on this article: if you’re running a CFW on your 6.60 PSP such as Pro CFW, you are regularly using the 6.60 kxploit without knowing it. The vulnerability was exploited and released by developers Davee and some1, about a year ago, and pro CFW relies on it. Today jigsaw gives a full explanation of the inner working of this exploit.

660 kxploit is within ifhandle.pfx, which is the PSP port of mbuf[1]. mbuf is the basic unit of memory management for network packets and socket buffers. It’s originated from BSD, and is widely adopted by commercial products due to BSD license. ifhandle is obviously ported from FreeBSD 4 release with slight changes. Some routines of ifhandle are 100% duplication of original mbuf code[2].

Before we inspect the kxploit, let’s understand what we want to achieve from a kxploit. The answer is straightforward: to be able to run our own routine with kernel privilege. With kernel privilege we are able to patch kernel so as to run unsigned homebrew, to skip version check, so on and so forth.

The answer is not complete, however, since the next question is how to gain kernel privilege. Remember that by issuing a syscall we can execute the kernel routines[3]. If we could somehow redirect the kernel routines to our own routine, our own routine instanly becomes a kernel level routine. We will see how we could redirect a kernel routine. It’s different from case to case. In most cases it requires modification to kernel space, where the kernel routines locate.

It sounds like a dilemma: to gain kernel privilege we have to modify kernel space, which again requires kernel privilege. This is why we need a kxploit. A kxploit, in most cases, is a bug in kernel that allows us to write values to kernel space.

Usually kxploits have this and that limiations. For instance 639 kxploit allows writing value 0xFFFFFFFF to anywhere; 620 allows writing value 0×0 to anywhere. In these 2 cases we have control over the address, but we can’t control the value that is to be written. This is fine, however, coz we need no more than that. We are able to redirect kernel routines by modifying only one word, which is either the check for kernel privilege, or loading offset of a routine. By masking the vital checkpoint, we manage to ask kernel to load the address of our own routine and call it.

Normally we want to write value zero to kernel space. This is because zero in MIPS stands for NOP, a.k.a. no-operation, which is a good candidate for masking other MIPS instructions.

As a conclusion let me put it this way: We need to find out a way to write value zero to an arbitrary address in kernel space.[4]

Now we are ready to check kxploit 660 in detail.

Note this line in sceNetMCopydata:

0x00001DDC: 0x0C000C8C '....' - jal memcpy

We are interested in the first and second arguments of memcpy, which are
destination and source of the data, respectively.
So we search above for $a0 which is the first argument of routines by
convention[5].

...
...
0x00001D18: 0x00E09021 '!...' - addu $s2, $a3, $zr
...
...
0x00001D98: 0x02402021 '! @.' - addu $a0, $s2, $zr

The 4th argument ($a3) of sceNetMCopydata is the destination of memcpy, and the argument is not checked at all. So if we could set this argument to be an address in kernel space…
But sceNetMCopydata is not exported to user space, which means we are not able to call it directly. Fortunetly sceNetMCopydata is called by other syscalls which can be easily accessed from user space. sceNetMPulldown is our target in this case.

We are going to reverse major part of sceNetMPulldown to find the way to sceNetMCopydata. There are two calls to sceNetMCopydata within sceNetMPulldown, and we are interested in the call at 0×00003018. The reason is that the call at 0x00002E9C copies data to a mbuf which is allocated by sceNetMallocInternal, which is not in our hand.

As I mentioned that ifhandle is based on mubf implementation, so we can grab the original FreeBSD code as a reference. You’ll notice a line-to-line mapping in ifhandle. The implemetation of m_pulldown is at http://fxr.watson.org/fxr/source/kern/uipc_mbuf2.c?v=FREEBSD4

Be prepared for a deep dive to MIPS asm. The code is heavily commented so as to be understood easily.

struct m_hdr {
  struct mbuf *mh_next; /* next buffer in chain */
  struct mbuf *mh_nextpkt; /* next chain in queue/record */
  caddr_t mh_data; /* location of data */
  int mh_len; /* amount of data in this mbuf */
  short mh_type; /* type of data in this mbuf */
  short mh_flags; /* flags; see below */
};

struct mbuf {
  struct m_hdr m_hdr;
  union {
    struct {
      struct pkthdr MH_pkthdr; /* M_PKTHDR set */
      union {
        struct m_ext MH_ext; /* M_EXT set */
        char MH_databuf[MHLEN];
      } MH_dat;
    } MH;
    char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */
  } M_dat;
};

#define mtod(m, t) ((t)((m)->m_data))
#define m_next m_hdr.mh_next // 0
#define m_len m_hdr.mh_len // c
#define m_data m_hdr.mh_data // 8
#define m_type m_hdr.mh_type // 10
#define m_flags m_hdr.mh_flags // 12

struct mbuf *sceNetMPulldown(struct mbuf *m, int off, int len, int *offp)
{
  struct mbuf *n, *o;
  int hlen, tlen, olen;
  // fp = offp
  // s6 = len
  // s4 = m
  // s2 = off
  // s1 = n
  //0x00002C10
  if (m == NULL)
    return NULL;
  //0x00002C18
  if (m 0x800) {
    sceNetMFreem(m);
    return NULL;
  }
  //0x00002C4C
  n = m; // s1 = n
  //0x00002C50
  while (n != NULL && off > 0) {
    if (n->m_len > off)
      break;
    off -= n->m_len;
    n = n->m_next;
  }
  //0x00002C84
  while (n != NULL && n->m_len == 0) {
    n = n->m_next;
    if (n < 0) //kernel space pointer?
      return NULL;
  }
  //0x00002CB8
  if (n == NULL) {
    sceNetMFreem(m);
    return NULL;
  }
  //0x00002CBC
  if ((off == 0 || offp) && len m_len - off)
    goto out;
  //0x00002CE0
  if (len m_len - off) {
    goto loc_00003050; //not interested
  }
  //0x00002CEC
  hlen = n->m_len - off; // s3 = hlen
  tlen = len - hlen; // s7 = tlen
  olen = 0; // v1 = olen
  // s0 = o
  //0x00002D00
  for (o = n->m_next; o != NULL; o = o->m_next)
    olen += o->m_len;
  //0x00002D18
  if (hlen + olen m_flags & 1)) {
    //0x00002D3C
    if (_lw(n + 0x34) != 0) {
      // we can't go now
      goto loc_00002D50;
    }
    //0x00002D4C
    a2 = (_lw(n + 0x44) == n); // a2 MUST equal to 0
  }
  //loc_00002D50
  if ((off == 0 || offp)) {
    //0x00002D60
    if ((m->m_flags & 1) == 0) {
      // we have to stay here
      goto loc_00003040;
    }
    //0x00002D7C
    x = (_lw(n + 0x30) + _lw(n + 0x3c)) - (n->m_data + n->m_len);
    // x is the macro M_TRAILINGSPACE
    if (x >= tlen && a2 == 0) {
      // finally...
      //0x00003018
      m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len);
    }
  }
}

As you can see, the code is almost duplicated from mbuf.
To reach sceNetMCopydata at 0×00003018 we have to dodge several traps.
For instance we have to set m_flags, m_len, m_next etc. properly. Besides, we will need 2 mbufs linked together to make this trip. I’m not going to show you how to activate this kxploit, coz you can either work it out yourself, or you can check how procfw does this job.
The idea is to demostrate what does a kxploit look like, and how to find a kxploit. Almost all kxploits that have been published so far fall into this category: a missing check against memory address.

In theory, any pointer (memory address) given from user space to kernel space should be validated. In practice, however, after PSP has been announced nearly ten years, there are still such kind of kxploit unleashed. Of course it has been farely difficult to spot a kxploit like this; even worse, a kxploit is not always useful due to syscall limitations[6].

On the other hand, there are other types of kxploits, such as stack overflow, which enalbes user code to be called directly without modifying kernel memory. We will see an example in the next blog of the series.

BTW, heap overflow is another type of kxploit, which is quite usual in mainstream OS such as Windows and Linux. But it has never been found/published in PSP. Hopefully someday I can show you the beauty of heap overflow.

Stay tuned.

[1] http://people.freebsd.org/~hmp/documentation/manpages/mbuf.pdf
[2] http://fxr.watson.org/fxr/source/kern/?v=FREEBSD4
[3] http://wololo.net/2012/05/30/syscalls-nids-imports/
[4] This is one of various possibilities. We will see other alternatives in this series.
[5] http://www.cygwin.com/ml/binutils/2003-06/msg00436.html
[6] http://wololo.net/2012/06/07/syscall-internals/

 

Tags: , ,

  1. exudos194’s avatar

    What lol….

    Reply

    1. fate6’s avatar

      if you dont understand or do not wish to learn then GTFO from a post that tries to do just that

      Reply

      1. naki’s avatar

        there’s no need to be that agressive man! I read it and I’m kind of feeling the same :) (not everyone here is a programmer, btw)

        Reply

        1. fate6’s avatar

          its not that he does not understand that bugs me, its the fact he just made a useless comment that makes no attempt at even trying to learn or understand

          heck even a simple

          “dont know what any of this means but goodpostisgood”

          would have been fine

          Reply

          1. D’s avatar

            Fate,Why are you so Autistic with a god complex?All of your posts you are just trying to be better than somebody.How about instead of “Hurr Durr,You do not wish to learn,Hurr GTFO.” You give an explanation if you are some super genius.

  2. cnjsk’s avatar

    Great post!

    Thank you for the consideration, jigsaw, amazing reading!

    Reply

  3. OMightyBuggy’s avatar

    I enjoyed the info. :)

    Reply

  4. ???’s avatar

    The Vita’s psp emulator runs on 6.60, so can we use this kxploit in the same way we use in the psp?

    Reply

    1. fate6’s avatar

      no as there is no way to say in example run a modified eboot on the Vita

      Reply

    2. wololo’s avatar

      We’ve all considered this question, and Sony is not as lazy as we’d expect. The Firmware on the Vita *is* 6.60, but with a fix for this exploit, as far as I could tell.

      Reply

      1. OMightyBuggy’s avatar

        Makes me wonder what is stopping Sony from patching the PSP already?

        Reply

        1. jigsaw’s avatar

          PSP is abandoned, evidently. Sony can’t afford two teams working parallely, I guess.

          Reply

  5. booler’s avatar

    Lol, lets post about all previous psp hacks and exploits.
    It’s so interesting.

    Reply

    1. wololo’s avatar

      It’s to teach you how it’s done, so you’ll be less dumb when you go to bed tonight.
      “Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime”. Ever heard that?

      Edit: Hmm, I automatically assumed you were being sarcastic, but maybe you’re not?

      Reply

      1. ???’s avatar

        How can you teach a man how to fish if he has no hands? :o

        Reply

      2. booler’s avatar

        Actually I wasn’t sarcastic,since psp vulnerabilities are very interesting.

        F/e gta save exploit

        Reply

        1. wololo’s avatar

          Apologies then, I did reply quite aggressively for no reason

          Reply

          1. Viral_Weaponry’s avatar

            lol

  6. jigsaw’s avatar

    btw, I think it’s Davee (instead of some1) who found this kxploit – according to the note of the release:

    “To Davee for making the original 6.35/6.31 downgrader, and for finding this exploit.”

    Reply

    1. wololo’s avatar

      Hmm, thanks, I will contact them for confirmation on how I should credit them properly

      Reply

  7. surVfate’s avatar

    OMG Great Post ever…! Learning is the best…

    Reply

  8. Green Ranger’s avatar

    Thanks jigsaw :)

    The best explanation of a kxploit i’ve ever seen :) i’ll take a deeper look on this post tomorrow (since it’s 00.36 am here in Germany ^^)

    Reply

  9. Dovahkiin’s avatar

    Great job jigsaw!!!
    Very informative. :D

    Reply

  10. SSJ-Vita’s avatar

    I not too long ago thankx to a wololo post got curious looked up c and c++, even though the guy spoke klingon for the most part, because this is upper level programming it was like playing FF X and decyphering al bhed language. I caught the meanings to a degree and will learn more sooner or later. I like to juggle my interests, so I don’t get bored with them and quit. Great stuff man!

    Reply

    1. npissoawsome’s avatar

      Upper level programming is like Java, than a little lower that that you would find C/C++, and even lower than that you would find MIPS/ASM, which is extremely low level coding, I think you got them mixed up

      Reply

  11. RetroHelix’s avatar

    Nice read!

    Reply

  12. DeadlyData’s avatar

    This is a great example of developers copying and pasting code and it causing vulnerabilities in their systems.

    Which is so common in other areas then just gaming, it’s so ridiculous it shows they don’t have proper auditing teams to go through the software before it goes out onto the market to be honest.

    Irresponsible,
    Yet anti-virus, and other companies do things like this every day and leave consumer systems open to the flaws.

    Reply

  13. j4n83’s avatar

    OMG… I don´t understand nothing… But wololo you are a genius i love you!! and im not gay xD

    Reply

    1. wololo’s avatar

      The article is not by me but by jigsaw. I myself am majorly lost when it comes to kernel exploits :)

      Reply

  14. ChaosAgent’s avatar

    Thanks for the tech articles! Keep them coming (dumbing down is appreciated when possible)!

    Reply

Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>