Wednesday, May 10, 2017

Analysis of the protection of Sony PlayStation 4

Don't know what to write - so will writhe about analysis of the protection of Sony PlayStation 4.

There will be a lot of codes and programs names. I will bring few links to software too. All right - lets start.

https://github.com/CTurt/PS4-playground

All stuff for hacking PS4.

Known facts about PS4.

As you most likely know, the PS4 uses a special eight-core x86-64 CPU from AMD, about the architecture of which is published a lot of research, and even if this particular version of the processor is slightly different from the standard standard, it will hardly be noticeable. For example, the PFLA (Page Fault Liberation Army) at 29C3 (29th Chaos Communication Congress) demonstrated a proof-of-concept proof that it is possible to implement a complete Turing machine using only page faults and x86 MMU, the video is available on YouTube . It will be interesting for those who, running the code in a virtual machine, at the same time wish to execute instructions on the CPU of the host.

And we are dealing not only with the well documented architecture of the CPU - the software used in PS4 is mostly related to open source.

For us, the most important thing is that Orbis OS, on which the console runs, is based on FreeBSD and uses separate parts of NetBSD, repeating the situation with PS3 in this regard; In addition to FreeBSD 9.0, Mono VM and WebKit are used from other notable large software.

Entry point - WebKit

WebKit is an open engine for rendering web pages in browsers for iOS, Wii U, 3DS, PS Vita and PS4.

Despite such a wide application and maturity of the project, WebKit does not lack individual vulnerabilities; Most of them you can find out by Pwn2Own records.

In particular, the browser in PS4 with firmware 1.76 uses the version of WebKit, vulnerable to CVE-2012-3748, buffer overflow in heap-based buffer overflow in JSArray :: sort (...) method.

In 2014, nas and Proxima said that they successfully ported this exploit for use on the PS4 browser, and laid out the PoC code in public, than they initiated the process of hacking the PS4.

This code gives you random access to reading and writing everything that the WebKit process can read / write, and this in turn can be used to dump modules and overwrite return addresses on the stack, allowing us to set control over the command counter (for ROP).

Since that time, many other vulnerabilities have been discovered in WebKit, which supposedly allow dumping modules and ROP on the latest PS4 firmware, but at the time of writing none of these exploits were ported to PS4.

What is ROP (return oriented programming)?

Unlike primitive devices like DS and PSP, PS4 uses a kernel that controls the options of different memory areas. Memory pages marked as executable can not be overwritten; Pages marked with writable can not be executed; This principle is known as Data Execution Prevention (DEP).

For us, this means the impossibility of using a simple path: copying the payload into memory and then executing it. However, we can execute code that is already loaded into memory and marked as executable.

By itself, the ability to jump to one address is not particularly useful if we can not write our own code at this address - that's why we'll resort to ROP.

Return-oriented programming (ROP) is just an improved version of the traditional stack smashing, but instead of overwriting one value that a PC jumps on, we can link together many different addresses, known as "gadgets"

Usually, a gadget is just the one desired design, followed by ret.

In assembler x86_64, when execution reaches the ret instruction, the 64-bit value is popped off the stack and the PC jumps on it; Since we can control the stack, we can force each ret instruction to jump to the next desired gadget.

For example, starting from 0x80000, instructions can be stored:

mov rax, 0
ret

And since 0x90000 the following instructions are stored:

mov rbx, 0
ret

If we overwrite the return address on the stack so that it will store 0x80000 and after 0x90000, as soon as execution reaches the first ret instruction, it will jump to mov rax, 0, and right after that the next ret instruction will pop out of the 0x90000 stack and jump to mov rbx , 0.

Thus, this chain will play into our hands and set both registers rax and rbx to 0, as if we just wrote the code in one place and executed sequentially.

ROP chains are not limited to an address list; Suppose that 0xa0000 is followed by the following instructions:

pop rax
ret

We can set the first element of the chain to 0xa0000 and the next element to any desired value for rax.

Gadgets are also not required to end with ret instructions; We can use gadgets that end with jmp:

add rax, 8
jmp rcx

Having done so that rcx points to the ret statement, the chain will be executed in the usual way:

chain.add("pop rcx", "ret");
chain.add("add rax, 8; jmp rcx");

Sometimes you will not be able to find exactly the gadget that you need, in itself - only with other instructions after it. For example, if you want to set r8 to some value, but you only have this gadget, then you'll have to set r9 to some dummy value:

pop r8
pop r9
ret

Although from time to time you will have to show your creativity when writing ROP-chains, nevertheless, it is generally assumed that if you use a sufficiently large code dump, the received gadgets will be sufficient for the Turing-complete functionality; This makes ROP a viable way to bypass DEP.

Search for gadgets

To understand ROP, the following metaphor will help you.

Imagine that you are writing a new chapter in the book, while using only the words that stood at the ends of the sentences of the previous chapters. Obviously, by virtue of the construction of phrases, you can hardly find the words "and" or "or" at the end of one sentence - but we need these connecting elements if we want to write something meaningful.

It is entirely possible, however, that one of the proposals ended with the word "sand". And, though according to the author's idea, we should read this word entirely starting with the letter "s", if we start our reading with "a", then by pure chance we will get a completely different word - "and", which we required.

These principles also apply to ROP.

Since the structure of almost all functions looks like this:

;Saving registers
push    rbp
mov     rbp, rsp
push    r15
push    r14
push    r13
push    r12
push    rbx
sub     rsp, 18h
;Functions body
;Registry Restore
add     rsp, 18h
pop     rbx
pop     r12
pop     r13
pop     r14
pop     r15
pop     rbp
ret

Therefore, you should expect to find only pop gadgets, or, less often, xor rax, rax, which set the value to 0 before returning.

Comparison of

cmp [rax], r12
ret

Does not make any sense, because the result of the comparison is not used by the function. However, the likelihood of finding such gadgets is still there.

The x86_64 instructions are similar to words in that they have a variable length, and can mean completely different things depending on where the decoding starts.

The x86_64 architecture is a set of variable-length CISC instructions. Return-oriented programming on x86_64 takes advantage of the fact that the instruction set is very "dense" - in the sense that any arbitrary sequence of bytes can most often be interpreted as a valid set of x86_64 instructions.

To demonstrate this, take a look at the end of this function from the WebKit module:

000000000052BE0D                 mov     eax, [rdx+8]
000000000052BE10                 mov     [rsi+10h], eax
000000000052BE13                 or      byte ptr [rsi+39h], 20h
000000000052BE17                 ret

Now take a look at what the code will look like if we start decoding with 0x52be14:

000000000052BE14                 cmp     [rax], r12
000000000052BE17                 ret

Although this code was never intended to be executed, it is located in the memory area that was marked "executable", which makes it very attractive for use as a gadget.

Of course, it would be incredibly expensive to waste time searching for all possible ways of interpreting the code before each manual ret; For us it is able to make existing utilities. To find ROP gadgets I prefer to use rp ++; To generate a text file filled with gadgets, simply enter the command:

rp-win-x64 -f mod14.bin --raw=x64 --rop=1 --unique > mod14.txt

Segmentation errors

If we try to execute an uncompleted page of memory, or we try to write it to an unrecordable page of memory, there will be a segmentation error.

For example, it looks like an attempt to execute code on the stack, which is "read" and "write" only (rw):

setU8to(chain.data + 0, 0xeb);
setU8to(chain.data + 1, 0xfe);

chain.add(chain.data);

And here it is - an attempt to write code that is "zamappen" only for reading and executing (rx):

setU8to(moduleBases[webkit], 0);

If a segmentation error occurs, the message "Insufficient free system memory" appears on the screen and the page does not load:

The cause of output of this message can be something else - for example, execution of an incorrect instruction or an unrealized system call, - but more often it comes out precisely because of a segmentation error.

ASLR

Address Space Layout Randomization (ASLR) is a security technology used in operating systems, which randomly changes the location of important structures in the address space of the process, namely: the image of the executable file, the libraries to load, the heap and the stack. Because of it, the base addresses of the modules change each time you start your PS4.

I received evidence that ASLR was disabled in the oldest firmware versions (1.05), but it appeared somewhere around 1.70. Note that ASLR for the kernel is disabled, at least for firmware versions 1.76 and below, and this will be proved further.

For most exploits, ASLR becomes a problem, because if you do not know the gadget addresses in memory, you will not know what to write to the stack.

Fortunately for us, we are not limited to writing static ROP-chains. We can use JavaScript to read the module table, which will help us get the base addresses of the loaded modules. Using these addresses, we can calculate the addresses of all our gadgets before running the ROP chain, bypassing ASLR.

The module table also includes the names of the module files:

WebProcess.self
libkernel.sprx
libSceLibcInternal.sprx
libSceSysmodule.sprx
libSceNet.sprx
libSceNetCtl.sprx
libSceIpmi.sprx
libSceMbus.sprx
libSceRegMgr.sprx
libSceRtc.sprx
libScePad.sprx
libSceVideoOut.sprx
libScePigletv2VSH.sprx
libSceOrbisCompat.sprx
libSceWebKit2.sprx
libSceSysCore.sprx
libSceSsl.sprx
libSceVideoCoreServerInterface.sprx
libSceSystemService.sprx
libSceCompositeExt.sprx

Although the PS4 mostly uses the [Signed] PPU Relocatable Executable ([S] PRX) format for modules, the lines referencing object files are noted in the libSceSysmodule.sprx dump. [Signed] Executable and Linking Format ([S] ELF ) - bdj.elf, web_core.elf and orbis-jsc-compiler.self.

This combination of modules and objects resembles the one used in the PSP and PS3.

A complete list of all available modules (and not just those that are loaded by the browser) can be found in libSceSysmodule.sprx. We can download and deface some of them thanks to several special system calls for the authorship of Sony, which will be discussed further.

JuSt-ROP

Using JavaScript to write and execute dynamic ROP-chains gives us a huge advantage over the usual buffer overflow attack.

In addition to bypassing ASLR, we can read the user agent of the browser, and substitute another ROP-chain for another version of the browser, giving our exploit the highest degree of possible compatibility.

We can use JavaScript even to read memory at our gadget addresses in order to make sure they are correct, which gives us almost perfect reliability.

Dynamic writing of ROP-chains makes sense in comparison with their preliminary generation by a script.

For these reasons, I created my own JavaScript framework for writing ROP-chains, JuSt-ROP.

Pitfalls JavaScript

JavaScript uses the representation of numbers in the format of double precision (64 bits) IEEE-754. This gives us 53 bits of accuracy (the mantissa VT_R8 has only 53 bits), which means that it is impossible to display each 64-bit value - some of them will have to apply an approximation.

If you just need to set the 64-bit number to some small value, like 256, then setU64to will cope with the task. But for cases where you need to write a buffer or data structure, there is a possibility that individual bytes will be written incorrectly if they were written in blocks of 64 bits. Instead, you need to write data in blocks of 32 bits (remembering that PS4 uses the order of little-endian) to make sure that each byte is identical.

System calls

Interestingly, the PS4 uses the same call format as Linux and MS-DOS for system calls, with arguments stored in registers rather than the traditional UNIX way (which FreeBSD uses by default) when arguments are stored on the stack:

Register                                          Value
Rax                                                 Number of the system call
Rdi                                                  Argument 1
Rsi                                                   Argument 2
Rdx                                                 Argument 3
R10                                                 Argument 4
R8                                                   Argument 5
R9                                                   Argument 6

We can try to execute any system call using the JuSt-ROP method:

this.syscall = function(name, systemCallNumber, arg1, arg2, arg3, arg4, arg5, arg6) {
                console.log("syscall " + name);
               
                this.add("pop rax", systemCallNumber);
                if(typeof(arg1) !== "undefined") this.add("pop rdi", arg1);
                if(typeof(arg2) !== "undefined") this.add("pop rsi", arg2);
                if(typeof(arg3) !== "undefined") this.add("pop rdx", arg3);
                if(typeof(arg4) !== "undefined") this.add("pop rcx", arg4);
                if(typeof(arg5) !== "undefined") this.add("pop r8", arg5);
                if(typeof(arg6) !== "undefined") this.add("pop r9", arg6);
                this.add("pop rbp", stackBase + returnAddress - (chainLength + 8) + 0x1480);
                this.add("mov r10, rcx; syscall");
}

The use of system calls can tell us a lot about the PS4 core. Moreover, the use of system calls is the only way we can interact with the kernel, and potentially can execute a kernel exploit.

If you reverse engineer modules to identify some of Sony's special system calls, you can detect an alternative call format:

Register                         Value
Rax                                0
Rdi                                 System call number
Rsi                                  Argument 1
Rdx                                Argument 2
R10                                Argument 3
R8                                  Argument 4
R9                                  Argument 5

Apparently, Sony has done so for easy compatibility with the agreement on calling functions, for example:

unsigned long syscall(unsigned long n, ...) {
                register unsigned long rax asm("rax");
               
                asm("mov r10, rcx");
                rax = 0;
                asm("syscall");
                return rax;
}

Using this approach, they can perform any system call from C.
When writing ROP chains, we can use the following convention:

//Both commands return the ID of the current process:

chain.syscall("getpid", 20);
chain.syscall("getpid", 0, 20);

This is useful to remember in case you can choose the most convenient of available gadgets.

getpid

A single system call at number 20, getpid (void), is already able to tell us a lot about the kernel.

The very fact that this system call is working tells us that Sony did not even bother to mix system call numbers as required by the "security through ambiguity" technique (and under the BSD license they could do this without publishing new system numbers on the Internet Calls).

Thus, we automatically got our hands on the list of system calls that you can try to make in the PS4 kernel.

Secondly, by calling getpid (), restarting the browser, and then calling it again, we get a return value 1 greater than the previous one. Although FreeBSD supports PID randomization since version 4.0, sequential PID allocation is the default behavior. Apparently, Sony has not bothered to increase its protection here either, as it was done in projects like HardenedBSD.

How many system calls are there?

The last system call on FreeBSD 9 is wait6 behind the number 523; All that has the number above - special system calls Sony.

Attempting to call any of Sony's special system calls without valid arguments will return 0x16 error, "Invalid argument"; However, any compatible system calls, or unrealized system calls, will result in a "There is not enough free system memory" error.

Through trial and error, I found out that the system call numbered 617 is Sony's last call, all calls are no longer implemented.

Based on this, we can make a logical conclusion that in the PS4 kernel there are 85 special system calls (617 - 532) for the authorship of Sony.

This is significantly less than it was in the PS3, which had almost 1000 system calls in general. Well, even if this indicates a lesser scope for potential attack vectors, but it will be easier for us to document all the calls.

We go further. 9 of these 85 system calls always return 0x4e, ENOSYS, which means a simple thing - these calls only work on test devices for developers, leaving us with only 76 useful calls.

Of these 76, libkernel.sprx only refers to 45 (all applications that are not part of the kernel use this module to make system calls). Total, the developer has only 45 available special system calls.

Interestingly, although only 45 calls were intended for use (since libkernel.sprx has wrappers for them), some of the remaining 31 are still accessible from the browser process. It is possible that in these unintentionally abandoned calls, the probability of finding a vulnerability is much higher, since the testing of the time has obviously taken the least.

libkernel.sprx

In order to understand how special kernel calls are used by the kernel, the main thing is to remember that this is just a modification of the standard FreeBSD 9.0 libraries.

Here is the excerpt of the _libpthread_init code from thr_init.c:

/*
 * Check for the special case of this process running as
 * or in place of init as pid = 1:
 */
if ((_thr_pid = getpid()) == 1) {
                /*
                 * Setup a new session for this process which is
                 * assumed to be running as root.
                 */
                if (setsid() == -1)
                                PANIC("Can't set session ID");
                if (revoke(_PATH_CONSOLE) != 0)
                                PANIC("Can't revoke console");
                if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0)
                                PANIC("Can't open console");
                if (setlogin("root") == -1)
                                PANIC("Can't set login to root");
                if (_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1)
                                PANIC("Can't set controlling terminal");
}

The same function can be found on offset 0x215F0 from libkernel.sprx. Here's how the above code looks in the libkernel dump:

call    getpid
mov     cs:dword_5B638, eax
cmp     eax, 1
jnz     short loc_2169F

call    setsid
cmp     eax, 0FFFFFFFFh
jz      loc_21A0C

lea     rdi, aDevConsole ; "/dev/console"
call    revoke
test    eax, eax
jnz     loc_21A24

lea     rdi, aDevConsole ; "/dev/console"
mov     esi, 2
xor     al, al
call    open

mov     r14d, eax
test    r14d, r14d
js      loc_21A3C
lea     rdi, aRoot       ; "root"
call    setlogin
cmp     eax, 0FFFFFFFFh
jz      loc_21A54

mov     edi, r14d
mov     esi, 20007461h
xor     edx, edx
xor     al, al
call    ioctl
cmp     eax, 0FFFFFFFFh
jz      loc_21A6C

Reversing module dumps for system call analysis

Libkernel is not fully open: it includes a large amount of Sony's own code that could reveal their system calls.

Although the analysis process will differ depending on the selected system call, for some of them it is fairly easy to find out the composition of the arguments that are passed to the call.

The wrapper of the system call will be declared somewhere in libkernel.sprx and will almost always follow the following pattern:

000000000000DB70 syscall_601     proc near
000000000000DB70                 mov     rax, 259h
000000000000DB77                 mov     r10, rcx
000000000000DB7A                 syscall
000000000000DB7C                 jb      short error
000000000000DB7E                 retn
000000000000DB7F
000000000000DB7F error:
000000000000DB7F                 lea     rcx, sub_DF60
000000000000DB86                 jmp     rcx
000000000000DB86 syscall_601     endp

Note that the instruction mov r10, rcx does not necessarily mean that the system call takes at least 4 arguments; This instruction is for all wrappers of system calls, and even for those that do not accept any arguments - for example, getpid.

Once you have found the wrapper, you can look at the xrefs to it:

0000000000011D50                 mov     edi, 10h
0000000000011D55                 xor     esi, esi
0000000000011D57                 mov     edx, 1
0000000000011D5C                 call    syscall_601
0000000000011D61                 test    eax, eax
0000000000011D63                 jz      short loc_11D6A

It's a good idea to look for a few more pieces, just to make sure that the registers have not been changed for something unrelated:

0000000000011A28                 mov     edi, 9
0000000000011A2D                 xor     esi, esi
0000000000011A2F                 xor     edx, edx
0000000000011A31                 call    syscall_601
0000000000011A36                 test    eax, eax
0000000000011A38                 jz      short loc_11A3F

We see how with the enviable consistency of the first three registers from the system call convention (rdi, rsi, and rdx), so we can confidently state that the call takes three arguments.

For understanding, here's how we will reproduce these calls using JuSt-ROP:

chain.syscall("unknown", 601, 0x10, 0, 1);
chain.syscall("unknown", 601, 9, 0, 0);

Like most system calls, these calls will return 0 if successful, as seen in the code above, where jz performs the transition after the test return value.

Finding out something more complex than the number of arguments will require a much deeper analysis of the code before and after the call to understand the context, but the narrative should be enough for you to start.

System call brute force

Despite the fact that reverse-engineering of module dumps is the most reliable way to identify system calls, some of them are not mentioned in the dumps, so we have to analyze them blindly.

If we assume that a particular system call can take a certain set of arguments, then we can generate a brute force on all system calls that return a certain value (0 for success) with the selected arguments, and ignore all returned errors.

We can also pass zeros to all arguments, and brute all system calls that return useful errors like 0xe, "Bad address", which indicate that calls take at least one pointer.

First, we need to execute the ROP-chain as soon as the page loads. We can do this by hanging our function on the onload of the body element:

<body onload="exploit()">

Next, we need to perform a special system call, depending on the value from the HTTP GET. Although this can be done with JavaScript, for simplicity I use PHP:

var Sony = 533;
chain.syscall("Sony system call", Sony + <?php print($_GET["b"]); ?>, 0, 0, 0, 0, 0, 0);
chain.write_rax_ToVariable(0);

As soon as the system call runs, we can check the return value, and if it does not give us anything interesting, make a redirect to the next system call:

if(chain.getVariable(0) == 0x16) window.location.assign("index.php?b=" + (<?php print($_GET["b"]); ?> + 1).toString());

Running the page with? B = 0 at the end will launch the brute force from the first Sony system call.

Although this method requires a lot of experiments, you can confidently say that it will allow you to find several system calls that you will be able to partially identify.

System call 538

As an example, let's look at the 538 system call without relying on dumps of any modules.

Here are the return values, depending on what is passed as the first argument:

0 — 0x16, «Invalid argument»
1 — 0xe, «Bad address»

The pointer to 0 is initially 0x64, but with each page refresh the value is incremented by 1.

Other potential arguments that you can try to substitute for are PID, thread ID, and file descriptor.

Despite the fact that most system calls return 0 on successful execution, some of the calls return a value increasing with each new call - apparently, these calls allocate any resource, like a file descriptor.

The next step will be to monitor the data before and after the system call to determine if something was written in them.

Since there is no change in the data, we can assume with good conscience that this is an input.

Then we try to feed the method a long string as the first argument. You should try this with every input that you will be able to detect, since there is a probability of detecting buffer overflow.

writeString(chain.data, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
chain.syscall("unknown", 538, chain.data, 0, 0, 0, 0, 0);

We get the return value 0x3f, ENAMETOOLONG. Alas, we see that the system call correctly constrains the name (32 bytes including the NULL delimiter), but now we know that the method expects a string, not a structure.

Well, now we have a few ideas about what this challenge can do. The most obvious option is some action related to the file system (for example, a special version of mkdir or open), but this version is unlikely to work for us - after all, the resource is allocated before we have written any data to the index.

Let's try to check if the first parameter is by. We split it with several symbols / and see if it will allow us to pass a long string to the method: 

writeString(chain.data, "aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa");
chain.syscall("unknown", 538, chain.data, 0, 0, 0, 0, 0);

Since this call also returns 0x3f, we can assume that the first argument is not the path; This is the name for something that will be placed in memory and will receive a sequential identifier.

After analyzing other system calls, I found that all of the following have the same behavior: 

533
538
557
574
580

With the help of the received information, it is almost impossible to guess what exactly these system calls are doing, but if you do other tests, you will gradually disclose the secret. I'll save you a bit of time - the system call 538 allocates memory for the event flag (and takes as a parameter not only the name).

With the help of basic knowledge of how the kernel works, you can assume, and then check what the system allocates memory with system calls - semaphores, mutextors, and so on.

Dump additional modules

We can dump additional modules as follows:
Download the module
We get the base address of the module
Dump the module.

All results are on psdevwiki - just google this word.

To load the module, we need to use the sceSysmoduleLoadModule function from libSceSysmodule.sprx + 0x1850. The first parameter is the identifier of the loadable module, in the remaining three simply passes 0.

The following JuSt-ROP method is useful for this call:

this.call = function(name, module, address, arg1, arg2, arg3, arg4, arg5, arg6) {
                console.log("call " + name);
               
                if(typeof(arg1) !== "undefined") this.add("pop rdi", arg1);
                if(typeof(arg2) !== "undefined") this.add("pop rsi", arg2);
                if(typeof(arg3) !== "undefined") this.add("pop rdx", arg3);
                if(typeof(arg4) !== "undefined") this.add("pop rcx", arg4);
                if(typeof(arg5) !== "undefined") this.add("pop r8", arg5);
                if(typeof(arg6) !== "undefined") this.add("pop r9", arg6);
                this.add("pop rbp", stack_base + return_va - (chainLength + 8) + 0x1480);
                this.add(module_bases[module] + address);
}

So, to load libSceAvSetting.sprx (0xb) we use:

chain.call("sceSysmoduleLoadModule", libSysmodule, 0x1850, 0xb, 0, 0, 0);

Like most system calls, this one should return 0 on success. To see the identifier of the module allocated in memory, we can use one of the Sony system calls at number 592 to get a list of the loaded modules:

var countAddress = chain.data;
var modulesAddress = chain.data + 8;

// System call 592, getLoadedModules(int *destinationModuleIDs, int max, int *count);
chain.syscall("getLoadedModules", 592, modulesAddress, 256, countAddress);

chain.execute(function() {
                var count = getU64from(countAddress);
                for(var index = 0; index < count; index++) {
                                logAdd("Module: 0x" + getU32from(modulesAddress + index * 4).toString(16));
                }
});

Running this code without loading any additional modules will display the following list:

0x0, 0x1, 0x2, 0xc, 0xe, 0xf, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x37, 0x59

However, if we run it after loading the 0xb module, we'll see an additional element, 0x65. Remember - the module ID is not the same as the ID of the loaded module.

Now we can use another Sony system call at number 593, which takes the loaded module ID and the buffer, and fills the buffer with information about the loaded module, including its base address. Since the ID of the loaded module is always 0x65, we can "cram" it into our chain, instead of storing the result from the list of modules.

The buffer must begin with the size of the structure that should be returned, otherwise error 0x16 will return, "Invalid argument":

setU64to(moduleInfoAddress, 0x160);
chain.syscall("getModuleInfo", 593, 0x65, moduleInfoAddress);

chain.execute(function() {
                logAdd(hexDump(moduleInfoAddress, 0x160));
});

If successful, 0 will return, and the buffer will be filled with a structure that can be read like this:

var name = readString(moduleInfoAddress + 0x8);
var codeBase = getU64from(moduleInfoAddress + 0x108);
var codeSize = getU32from(moduleInfoAddress + 0x110);
var dataBase = getU64from(moduleInfoAddress + 0x118);
var dataSize = getU32from(moduleInfoAddress + 0x120);

Now we have everything necessary for the module dump!

dump(codeBase, codeSize + dataSize);

There is another Sony system call, under the number 608, which works similar to the 593 way, but provides a little bit more information about the loaded module:

setU64to(moduleInfoAddress, 0x1a8);
chain.syscall("getDifferentModuleInfo", 608, 0x65, 0, moduleInfoAddress);
logAdd(hexDump(moduleInfoAddress, 0x1a8));

It is not known what this information can mean.

Let's explore the file system

PS4 uses standard FreeBSD 9.0 system calls to read files and directories.

However, despite the fact that reading separate directories like / dev / will work, reading others - for example, / - is not.

I do not know why this happens, but if you use gendents instead of read for directories, then everything will work more reliably:

writeString(chain.data, "/dev/");
chain.syscall("open", 5, chain.data, 0, 0);
chain.write_rax_ToVariable(0);

chain.read_rdi_FromVariable(0);
chain.syscall("getdents", 272, undefined, chain.data + 0x10, 1028);

Here is the resulting memory:

0000010: 0700 0000 1000 0205 6469 7073 7700 0000  ........dipsw...
0000020: 0800 0000 1000 0204 6e75 6c6c 0000 0000  ........null....
0000030: 0900 0000 1000 0204 7a65 726f 0000 0000  ........zero....
0000040: 0301 0000 0c00 0402 6664 0000 0b00 0000  ........fd......
0000050: 1000 0a05 7374 6469 6e00 0000 0d00 0000  ....stdin.......
0000060: 1000 0a06 7374 646f 7574 0000 0f00 0000  ....stdout......
0000070: 1000 0a06 7374 6465 7272 0000 1000 0000  ....stderr......
0000080: 1000 0205 646d 656d 3000 0000 1100 0000  ....dmem0.......
0000090: 1000 0205 646d 656d 3100 0000 1300 0000  ....dmem1.......
00000a0: 1000 0206 7261 6e64 6f6d 0000 1400 0000  ....random......
00000b0: 1000 0a07 7572 616e 646f 6d00 1600 0000  ....urandom.....
00000c0: 1400 020b 6465 6369 5f73 7464 6f75 7400  ....deci_stdout.
00000d0: 1700 0000 1400 020b 6465 6369 5f73 7464  ........deci_std
00000e0: 6572 7200 1800 0000 1400 0209 6465 6369  err.........deci
00000f0: 5f74 7479 3200 0000 1900 0000 1400 0209  _tty2...........
0000100: 6465 6369 5f74 7479 3300 0000 1a00 0000  deci_tty3.......
0000110: 1400 0209 6465 6369 5f74 7479 3400 0000  ....deci_tty4...
0000120: 1b00 0000 1400 0209 6465 6369 5f74 7479  ........deci_tty
0000130: 3500 0000 1c00 0000 1400 0209 6465 6369  5...........deci
0000140: 5f74 7479 3600 0000 1d00 0000 1400 0209  _tty6...........
0000150: 6465 6369 5f74 7479 3700 0000 1e00 0000  deci_tty7.......
0000160: 1400 020a 6465 6369 5f74 7479 6130 0000  ....deci_ttya0..
0000170: 1f00 0000 1400 020a 6465 6369 5f74 7479  ........deci_tty
0000180: 6230 0000 2000 0000 1400 020a 6465 6369  b0.. .......deci
0000190: 5f74 7479 6330 0000 2200 0000 1400 020a  _ttyc0..".......
00001a0: 6465 6369 5f73 7464 696e 0000 2300 0000  deci_stdin..#...
00001b0: 0c00 0203 6270 6600 2400 0000 1000 0a04  ....bpf.$.......
00001c0: 6270 6630 0000 0000 2900 0000 0c00 0203  bpf0....).......
00001d0: 6869 6400 2c00 0000 1400 0208 7363 655f  hid.,.......sce_
00001e0: 7a6c 6962 0000 0000 2e00 0000 1000 0204  zlib............
00001f0: 6374 7479 0000 0000 3400 0000 0c00 0202  ctty....4.......
0000200: 6763 0000 3900 0000 0c00 0203 6463 6500  gc..9.......dce.
0000210: 3a00 0000 1000 0205 6462 6767 6300 0000  :.......dbggc...
0000220: 3e00 0000 0c00 0203 616a 6d00 4100 0000  >.......ajm.A...
0000230: 0c00 0203 7576 6400 4200 0000 0c00 0203  ....uvd.B.......
0000240: 7663 6500 4500 0000 1800 020d 6e6f 7469  vce.E.......noti
0000250: 6669 6361 7469 6f6e 3000 0000 4600 0000  fication0...F...
0000260: 1800 020d 6e6f 7469 6669 6361 7469 6f6e  ....notification
0000270: 3100 0000 5000 0000 1000 0206 7573 6263  1...P.......usbc
0000280: 746c 0000 5600 0000 1000 0206 6361 6d65  tl..V.......came
0000290: 7261 0000 8500 0000 0c00 0203 726e 6700  ra..........rng.
00002a0: 0701 0000 0c00 0403 7573 6200 c900 0000  ........usb.....
00002b0: 1000 0a07 7567 656e 302e 3400 0000 0000  ....ugen0.4.....
00002c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

Some of these devices can be read, for example, reading / dev / urandom will fill the memory with random data.

You can also parse this memory and get a list of entities; Take a look at the browser.html from the repository, which acts as a file manager:

Alas, because of the sandbox, we do not have full access to the file system. An attempt to read files or directories that exist, but access to them is limited, will return error 2, ENOENT, "No such file or directory". However, we can still get access to various interesting things - encrypted save files, trophies and account information.

Sandbox

The problem with the operation of system calls is not limited to individual paths - there are other reasons why they can not be executed.

Most often, a prohibited system call simply returns error 1, EPERM, "Operation not permitted"; This statement is valid for calls like ptrace, because other system calls will not work for a variety of reasons.

Compatible system calls are disabled. For example, if you want to call mmap, you should use system call number 477, not 71 or 197; Otherwise, you will get a segment.

Other system calls, like exit, will also cause a segmentation fault:

chain.syscall("exit", 1, 0);

An attempt to create an SCTP socket will return a 0x2b, EPROTONOSUPPORT error indicating that the SCTP sockets were turned off in the PS4 kernel:

//int socket(int domain, int type, int protocol);
//socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
chain.syscall("socket", 97, 2, 1, 132);

And, although calling mmap with PROT_READ | PROT_WRITE | PROT_EXEC returns a valid pointer, the PROT_EXEC flag will be ignored. Reading its protection will return 3 (RW), and any attempt to execute memory will result in the segment:

chain.syscall("mmap", 477, 0, 4096, 1 | 2 | 4, 4096, -1, 0);
chain.write_rax_ToVariable(0);
chain.read_rdi_FromVariable(0);
chain.add("pop rax", 0xfeeb);
chain.add("mov [rdi], rax");
chain.add("mov rax, rdi");
chain.add("jmp rax");

The list of open source software used in PS4 does not include specialized software for sandboxes like Capsicum, so PS4 either uses "clean" jails from FreeBSD, or relies on its own proprietary system for isolating environments (which is unlikely).

http://doc.dl.playstation.net/doc/ps4-oss/

Jail

We can prove the existence of active use of jails from FreeBSD in the PS4 kernel with the auditon system call, which can not be performed in an isolated jailed environment:

chain.syscall("auditon", 446, 0, 0, 0);

The first thing that the audition system call does is check jailed here, and if so, it returns ENOSYS:

if (jailed(td->td_ucred))
                return (ENOSYS);

Otherwise, the system call will most likely return EPERM from mac_system_check_auditon here:

error = mac_system_check_auditon(td->td_ucred, uap->cmd);
if (error)
                return (error);

Or from priv_check here:

error = priv_check(td, PRIV_AUDIT_CONTROL);
if (error)
                return (error);

The farthest point the system call can reach is right after priv_check, here, before returning EINVAL because of the argument length equal to 0:

if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
                return (EINVAL);

Because mac_system_check_auditon and priv_check never return ENOSYS, the hit on the jailed check is the only option when ENOSYS returns.

When the chain is executed, ENOSYS (0x48) is returned.

This tells us that the sandbox system used by PS4 is at least based on jail because it uses jailed checks.

Exploits of the FreeBSD 9.0 kernel

There is not much point in finding new vulnerabilities in the source code of the FreeBSD 9.0 kernel, since several kernel exploits have been found since the release in 2012, to which the PS4 can potentially be vulnerable.

Some of them we can discard at once:

FreeBSD 9.0-9.1 mmap / ptrace - Privilege Escalation Exploit - does not work, because we do not have access to the ptrace system call.

FreeBSD 9.0 - Intel SYSRET Kernel Privilege Escalation Exploit - will not work, because the PS4 uses an AMD processor.
FreeBSD Kernel - Multiple Vulnerabilities - perhaps the first vulnerability in this package will work, but the other two rely on SCTP sockets, which are disabled in the PS4 kernel, as mentioned earlier.

Fortunately, there are a few smaller vulnerabilities that can lead us to something interesting.

getlogin

One vulnerability that can be easily tried is the use of the getlogin system call to leak a small amount of kernel memory.

The getlogin system call is designed to copy the user name of the current session to user memory, however, because of the bug, the buffer is always copied completely, not just the size of the string with the name. This means that we can read some uninitialized data from the kernel, which may come in handy.

Note that the system call (49) is actually int getlogin_r (char * name, int len); and not char * getlogin (void) ;.

So, let's try to copy a bit of kernel memory to an unused part of the user's memory:

chain.syscall("getlogin", 49, chain.data, 17);

Alas, we can not get more than 17 bytes, because:

The length of the user name is limited to MAXLOGNAME (from <sys / param.h>) characters, currently 17 characters, including blank characters.

FreeBSD Man Pages

After the execution of the chain, the return value is 0, which means that the system call worked! A great start. Now let's take a look at the memory we pointed out:

Before completing the chain:

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00

After completing the chain:

72 6f 6f 74 00 fe ff ff 08 62 61 82 ff ff ff ff
00

After decoding the first four bytes in ASCII:

root

It turns out that the browser is running from root! This is a surprise.

But what is even more interesting is that the leaked memory resembles a pointer to something in the kernel, which at each start of the chain remains the same; This testimony confirms the Yifanlu theory that PS4 does not have ASLR protection (address space randomization) at the kernel level!

Total

Judging by the information gathered, the PS4 core very much resembles the stock core of FreeBSD 9.0. It is important to note that the changes are more likely to change the standard kernel configuration than to modify the code. Although Sony also added several of its own special system calls to the core, the rest of the kernel appears to have remained virtually untouched.

For these reasons, I'm inclined to think that the PS4 has all the same "juicy" vulnerabilities as in the FreeBSD 9.0 kernel!

Unfortunately, most of the kernel exploits can not be performed from the WebKit entry point due to sandbox restrictions (which are most likely controlled by the standard jails engine from FreeBSD). Alas, we do not have to hope for the publication of private exploits for FreeBSD 9, so until suddenly a new one suddenly comes out, we are forced to work with what is. I assume that there is a possibility of exploiting the PS4 kernel using some of the existing vulnerabilities of memory corruption errors, but this will definitely not be easy.

The best approach here is reverse engineering of all the modules that will be obtained by dumping, in order to document the maximum possible number of special system calls from Sony; Intuition tells me that with them the chance to achieve success will be higher than with the standard system calls of FreeBSD.

Jaicrab recently discovered two UART ports on the PS4, which tells us about the potential interest of hardware hackers in the console. Although the role of hardware hackers was usually in the dumping of the RAM system (as it was with DSi), this time we already dealt with this task ourselves thanks to the exploit WebKit - however, it is possible to detect a kernel vulnerability that will be "turned on" by hardware, like this Was with the original hack of the hypervisor in PS3 for the authorship of geohot. However, this does not negate the fact that the PS4 kernel's exploit is likely to be made due to the vulnerability of the system call.


Wednesday, May 3, 2017

The most innovative solutionы

Today we will talk about devices that either really help people suffering from incurable (yet) diseases, or are the first serious steps to solve the problems of such people.

I chose two kinds of problems - Parkinson's disease and blindness. First problem, of course not decided, but now, such people can safely eat themselves. The second problem is partially solved, although there is still a lot of work ahead, but these are the first - the most important steps.

In November 2014, Google X introduced a new development in the field of medicine. The division of the Internet giant, engaged in promising research, began selling a spoon, which allows you to comfortably eat food for people with different forms of tremors. The development was carried out by a subsidiary company Google X under the name Lift Labs.

Tremor is a common symptom of various neurological disorders, the most common of which are essential tremor and Parkinson's disease. Uncontrolled hand trembling prevents millions of people from the Earth from performing everyday tasks: dressing, writing, washing, and, of course, eating. Google decided to help such people.

The interest of one of the founders of the company Sergei Brin to Parkinson's disease is known for a long time. His mother suffers from this disease, and he himself has a genetic predisposition to Parkinsonism. For this reason, Brin in 2012 donated $ 138 million for the creation of new anti-Parkinsonian medicines. In 2014, Calico (the biotechnology division of Google) agreed with the biopharmaceutical firm AbbVie on cooperation in developing methods for treating particular neurodegenerative disorders, including Parkinson's disease. The amount of planned investments in this partnership is $ 1.5 billion.

Google's work on a high-tech spoon began in September 2014, when the company acquired Lift Labs, a small start-up from San Francisco that received funds from the National Institutes of Health.

The collective of Lift Labs, led by Anupam Pathak (Anupam Pathak) for two years analyzed more than one hundred motor algorithms, which subsequently formed the basis of the Liftware. It consists of two parts moving relative to each other - the handle and the working part.

The instrument's sensors monitor the tremor of the hand holding it in real time. The built-in electric drive compensates for these oscillatory movements, preventing their transfer to the working part. In this case, Liftware distinguishes tremor from other movements and does not interfere with their implementation.
Efficiency of the device was studied in two clinical trials involving 11 and 15 patients with mild, moderate and severe tremor, respectively. All volunteers performed three tasks - eating, holding and moving the object - with the device turned off and on.

It turned out that, when performing any task, the included Liftware reduces the amplitude of the oscillations of the hand transferred to the working part by more than 70%. The developers' report on the testing of the new device in 2013 was awarded a special presentation at the conference of the American Academy of Neurology.

As they say on the site Lift Labs, the device can be not only a spoon - it also comes with replaceable nozzles in the form of a plug and a key holder. In the future, it is planned to expand the assortment of such attachments to perform various tasks.

Liftware is small in size and runs on a built-in battery, so it's easy to carry with you. The manufacturer guarantees that one charge will last for several days. The new device is sold online at a price of $ 295 per unit.

Google and medicine. (Just to know!)

Liftware was not the first medical development of Google X. The greatest success was achieved in the creation of diagnostic and therapeutic contact lenses. The prototype of such a lens is a "bloodless" glucometer - a device for measuring the level of sugar in the blood. Modern devices need a drop of blood for this, and since in some cases the analysis must be performed several times a day, their use is very inconvenient for patients with diabetes.

The Google X contact lens created in real time, without any discomfort, determines the sugar content in the tear fluid and transfers this data wirelessly to the mobile device. The idea was so successful that to develop and commercialize the technology together with Google began the company Alcon, recently included in the pharmaceutical giant Novartis. It is estimated that this could bring more than $ 12 billion by 2017.

"Smart" lenses are planned to be adapted to monitor the condition of patients with heart failure and other chronic diseases. They will find application not only in diagnosis, but also in the treatment of diseases. The experimental lens is designed to help people with presbyopia ("old farsightedness") - the mechanism of its action is similar to the autofocus of cameras.

In October 2014, Google X announced the development of nanoparticles, which are "tuned" to identify certain diseases and are a universal diagnostic platform. The company also launched the Baseline Study project, which aimed to create an "image of a healthy person" by collecting and analyzing the genetic and molecular information of many people.

In addition to its own development, Google actively invests in various biotechnology companies. Among its partners, the cloud data analysis service DNAnexus, the developer of non-injection methods for the introduction of large molecules Rani Therapeutics, helping children with developmental disorders, SynapDx, the developer of medical software One Medical Group and the company Transcriptic, engaged in the automation of molecular cloning, mouse genotyping and biobank management.

Well, since it's about glasses ... Electronic glasses for the blind then!

Almost 90 percent of all information about the world around the person gets through the visual organs. In the modern world, the burden on the eyesight has increased significantly, so the number of people who have certain visual impairments is constantly increasing. If the task of full restoration of vision is still unresolved, then it is quite possible to help patients who are experiencing similar problems in order that they can return to full-fledged life. Currently, these people can help the electronic glasses transforming visual information into images or signals that could be recognized by the user. For example:

E-sight

Perhaps one of the most interesting devices in this direction is the virtual E-sight glasses developed by the Canadian company of the same name. This system includes glasses and a manual control panel. In the glasses themselves there is a camera with the possibility of a 14-fold increase, which records everything that is happening in front of the person, and immediately transfers the data to the control unit. Further this information is transformed to individual features of the visually impaired person by means of special algorithms, and then sent back to the glasses.

Lenses of electronic E-sight glasses will be OLED-screens with high resolution. Since the processes of data transfer and processing are carried out quickly, the person begins to see the image in real time.

E-sight glasses can not help the fullness of blind people, but they can be a useful tool for visually impaired users. Using the remote, a person can work with the resulting visual image, in particular, bringing it up to 14 times. This allows him to look at far-away objects or read the page of the book.

With the help of the control unit, you can change the contrast and brightness of the picture. Virtual E-sight glasses have already been successfully applied in practice. For example, with their help, the Canadian Ketty Beetz, who has serious vision problems, which began to appear as a child, managed to see the face of her newborn son.

However, until the widespread use of such electronic glasses is still far away. First, they can not help all patients. And most importantly - it's a very high cost device (about 10-15 thousand dollars). After all, in fact, they are made to order, taking into account the individual characteristics of vision so that the video signal can be transformed into clearly discernible and visible to man images.

Smart-glasses.

The aforementioned E-sight is an attempt to use the residual vision that has survived in humans. Because many people who are considered blind, in fact can perceive light. The same principle is also found in other technological developments of recent times. In particular, Professor Stephen Hicks of Oxford University has created special glasses with two miniature cameras and an infrared projector capable of determining the distance to objects. The PDA analyzes and converts incoming data from the cameras, and then displays them on the lenses of the glasses in a visible form for the visually impaired person.

Lenses here also represent transparent OLED-displays. Information from the cameras and the projector is transformed into useful, pleasing to the person images.

For example, the distance to the obstacle can be determined by different brightness of the picture. Pilot tests of the novelty have already been completed, for the introduction and commercial distribution of his invention, Hicks created the company Assisted Vision. In the near future, it is planned to start the production and sale of electronic glasses. Of course, this device can not fully reproduce the functions of the eyes, but it can help visually impaired people to go shopping and use public transport.

Sound glasses.

Another version of eyeglasses for blind people was offered by Amir Amedi from the University of Jerusalem. He was able to create the so-called "spoofing device" (SSD), which allows the blind to "see" the nearest objects. True, this is achieved not by using a set of images, as in previous devices, but by a set of sounds.

In these electronic glasses, a small camera is built in, which connects to a PDA or a smartphone. With the help of a special program, visual information about the surrounding objects, coming from the camera, is converted into sound signals. In astnosti, the contrast line that goes up is transmitted by a growing audible signal, and the one that goes down - with a decreasing tone. After a short practice, a blind person can easily memorize this set of sounds to learn to understand them.

Tests of the device showed that even a blind person by means of electronic glasses becomes able to find people, recognize certain objects, read inscriptions. By the way, it was found that people with absolute blindness are much more dexterous with eyeglasses than healthy people with a gaze in their eyes or just visually impaired people. The reason is clear: in blind people the hearing develops more strongly, they are more sensitive to subtle variations in sound, different tonalities.

Bionic Eye

Electronic glasses complementing reality are, of course, good, but some research organizations and companies set themselves a much more ambitious task. We are talking about the creation of a real bionic eye that can almost completely replace our visual organs.

Second Sight company has been working in this direction for a long time. She remoteness to create an artificial arm. The device called Argus II functions as follows. A set of electrodes is implanted on a damaged eye gland. A compact camera on the glasses records the surrounding space, then the resulting image is processed by a portable PC. Finally, through wireless communication, information is transferred to the artificial arm, which, due to the built-in electrodes, stimulates the photoreceptor cells. As a result, the person becomes accessible though primitive, but vision.

Thanks to this device, blind people can see that there is an object in front of them, they can notice movement. However, the mass production of the device has not yet been discussed, since the cost of Argus II currently exceeds 100 thousand dollars. However, the appearance of such devices still gives a certain hope to blind people that they will someday be able to see the daylight and enjoy the beauty of the surrounding world.