Reversing sceLibCamera


Well, first thanks to all people involved in WebKit exploit. Without their tools i could't dump module and reverse it.

1) We need dump the module. Load libSceCamera.sprx its id is 31. So load it first.

2) Dump it. its index is 20 when it is loaded.

3) Idapro to the rescue. We need offset for all functions that can be called from other modules. Only a brief view and you can see that Sony is using printf("%s ...\n",__FUNCTION__,..) in his code (Thanks of this help Sony) so many function names are you waiting for you with the offset ready :P and plenty of them are the same names that we know from vita and ps3.

you can use getFunctionAddressByName sycall 591 with the names that you see in idapro so you can confirm all function names and the offsets.

The list is:

sceCameraAudioOpen Offset = 0x6d00
sceCameraClose Offset = 0x5550
sceCameraCloseByHandle Offset = 0x55b0
sceCameraGetAttribute Offset = 0x5a10
sceCameraGetAutoExposureGain Offset = 0x5ba0
sceCameraGetAutoWhiteBalance Offset = 0x5d00
sceCameraGetConfig Offset = 0x5710
sceCameraGetContrast Offset = 0x5e60
sceCameraGetDefectivePixelCancellation Offset = 0x5fc0
sceCameraGetDeviceConfig Offset = 0x6dc0
sceCameraGetDeviceInfo Offset = 0x5af0
sceCameraGetExposureGain Offset = 0x6120
sceCameraGetFrameData Offset = 0x5950
sceCameraGetGamma Offset = 0x62c0
sceCameraGetHue Offset = 0x6460
sceCameraGetLensCorrection Offset = 0x65c0
sceCameraGetSaturation Offset = 0x6720
sceCameraGetSharpness Offset = 0x6880
sceCameraGetWhiteBalance Offset = 0x69e0
sceCameraIsAttached Offset = 0x6bd0
sceCameraIsValidFrameData Offset = 0x59b0
sceCameraOpen Offset = 0x5430
sceCameraOpenByModuleId Offset = 0x54c0
sceCameraSetAttribute Offset = 0x5a80
sceCameraSetAutoExposureGain Offset = 0x5c50
sceCameraSetAutoWhiteBalance Offset = 0x5db0
sceCameraSetCalibData Offset = 0x6c70
sceCameraSetConfig Offset = 0x5610
sceCameraSetConfigInternal Offset = 0x5690
sceCameraSetContrast Offset = 0x5f10
sceCameraSetDefectivePixelCancellation Offset = 0x6070
sceCameraSetExposureGain Offset = 0x6200
sceCameraSetGamma Offset = 0x63a0
sceCameraSetHue Offset = 0x6510
sceCameraSetLensCorrection Offset = 0x6670
sceCameraSetSaturation Offset = 0x67d0
sceCameraSetSharpness Offset = 0x6930
sceCameraSetWhiteBalance Offset = 0x6ac0
sceCameraStart Offset = 0x5790
sceCameraStartByHandle Offset = 0x5810
sceCameraStop Offset = 0x5890
sceCameraStopByHandle Offset = 0x58f0


there are more but are internals and you can't use it outside the module.


4) Now fun job. Dissasemble each function that you can use from WebKit. You will see that Sony is using the same error Codes than in vita so this will help you to follow better the code. For example function sceCameraStop is at offset 0x5890 you can see its code in the next capture:



Remember:
"The first is placed in rdi, the second in rsi, the third in rdx, and then rcx, r8 and r9. Only the 7th argument and onwards are passed on the stack
For calls that may call functions that use varargs or stdargs (prototype-less
calls or calls to functions containing ellipsis (. . . ) in the declaration)
%al is used as hidden argument to specify the number of vector registers used."

so here we go:

edi contains parameter passed to the function. It is comparing with itself so basically if it is less or equal to 0 go to loc_58c7.

You will see that in loc_58c7 it is using something like:

printf("%s invalid handle:%d\n",__FUNCTION,arg1);

then you will see our old friend 802E0000h aka SCE_CAMERA_ERROR_PARAM well known in psp2sdk. So if you pass an arg1 less or equal than 0 to this function  you will get that.

So now what happen if you pass a valid handle greater than 0. When you open it will give you handle 1. If you are not open previously the camera what happen? Test and error and you will see.

if handle >0 it will call loc_58e3 with 2 parameter first is our handle and second you can see in the code. Result is saved on rsx and if it is not 0 (our old friend SCE_OK) it will return code error. For example try to call close before open and it will return  0x802e0004 aka SCE_CAMERA_ERROR_NOT_OPEN

Easy don't you?

int sceCameraClose(int handle) 0 on success error codes on fail

5) Follow reversing functions. Advice some function are using structures in their parameter so it check if these structures are not NULL and depend of the function check the first 32 bits in these structures it is harcoded on the code so it you can call with a valid chain.data from WebKit and set the correct values on that first 32 bits you can call all the functions described with success.

6) What do you wait to help to open sdk?

sample output from ps4:


The best is yet to come ;) (greets to Kojima san)



Articulo cortesía: Antonio Marquez aka bigboss

Reversing PlayStation VR device (I)

Hola a tod@s

Hoy os traigo un post de mi amigo Antonio el cual me impresiono tanto que me lo lleve a la Sec/Admin y nos maravillo a todos. Sin más dilación os dejo con esta obra de arte de reversing.

First i need to give thanks to:
 The title of this blog article explains very well  about which is the main purpose of this blog entry.
PlayStation VR (before known by Morpheus) is the new device from Sony for Virtual Reality marketplace. As you know there are a few actors right now in this marketplace:
  • Oculus.
  • HTC.
  • Sony.
  • Google.
  • Samsung.
  • Others vendors.
 PlayStation VR need different parts:
  • VR headset.
  • Processor Unit.
  • PlayStation 4
  • PlayStation 4 Camera
  • PlayStation Move and PlayStation dualshock
  • TV with hdmi
Connection schema from Sony:
I have spoken already about PlayStation Move and PlayStation Camera  here in this blog and about its new design in my twitter account:


So now we are going to speak about usb connection between Processor Unit and PlayStation 4 because we want to use PlayStation VR in other platform different than PlayStation 4.
Processor Unit is a black box, if you want to know more about it you will need two things:
  1. Information about hardware. Sony published morpheus_bridge source for 1.50 and 2.0 and it will give you good information about how usb device is build and detailed information about all their 9 interfaces.
  2. An usb dump made with a usb protocol hardware analyzer.
1 was already published and 2 was shared by tokkyo_tw so...

LET THE GAME BEGIN

What happen when you connect usb connector from Processor Unit to a Mac/PC?

Easy you can see a new usb device with these usb descriptors

You can check in morpheus_bridge source code that all information is already there.

Usb dump was done with:

  • Software: USB Protocol Suite 7.35
  • Hardware: USBTrace 2500H
USB Protocol Suite can be downloaded from here you must register your user to dowload it.

We are going to work with files from dump:

  • connect-to-ps4 (psvr off).usb
  • connect-to-ps4 (psvr on in game (rez))-then-vrmode-on.usb
  • connect-to-ps4 (psvr on in game (rez)).usb
  • switch-to-vr-mode (in rez).usb
We will choose  connect-to-ps4 (psvr off).usb file first opening it with USB Protocol Suite.
With PlayStation Camera we got dump from beagle hardware analyzer from totalphase and their tool is multiplatform and easy to use for me.

USB Protocol Suite is for windows only and it is  a little hard to use but task can be done with it.

After opening file, choose in menu View Apply Decoding Scripts and check that you have following interfaces and their usb class applied:


 and in the endpoint option the same:



A problem that i find with this tool is that sometimes it can't put the right type of endponint , class and packet size , so check it with usb descriptors first.(Some weird sometimes identify some endpoint with bulk type when they are interrupt type check with usb descriptor that info is correct)
Choose in menu View Transfer Level and Hide all except Transfers options and  in menu Report Detail, View Data and Decode Field View options.

After that we can go transfer by transfer to make our analysis.

I am not going to tech you how usb protocol works for that you have plenty of information, if you don't know about it stop here.

First transfers are about get device and config ,interaface and endpoint descriptors, basically a dump for all descriptors


For your reference these standard request transfer give you all information about device:
  • Transfer 4 device descriptor
  • Transfer 11 configuration descriptor
  • Transfer 12 all descriptor
  • Transfer 13 status
All these transfer can give you all usb descriptor for this device and you can compare with information in morpheus_bridge  source and lsusb output. It is the same.  Check Decoded Field View Tab to see values from these standard requests transfers.

Transfer 14 set usb configuration to 1
Transfer 15 get size for string at index 3: 30 bytes (14 characters)
Transfer 16 get string at index 3 : PS VR 3D Audio  (name associated to interface 0)
Transfer 17 put alternate setting to 1 in inteface 0
Transfer 18 get size for string at index 4: 24 bytes
Transfer 19 get string at index 4: PS VR Audio (name associated to interface 1)
Transfer 20 21 22  23  25 and 26 are audio claass requests to get min max res from both channels associate to control volume features on interface 1
Transfer 24 is a isoc transfer empty no audio send yet to endpoint 1 OUT
Transfer 27 28 29 set volume to channel 1, channel 2 and again channel 1
Transfer 30 set alternate 1 to interface 3
Transfer 31 set alternate 1 to interface 2
Transfer 32 get size for string at index 7 : 26 bytes (12 caracteres)
Transfer 33 get string at index 7:  PS VR Sensor  (associated to interface 4)
Transfer 34 get report descriptor  from interface 4
/*0x06, 0x01, 0xff, // Usage Page (Vendor-defined 0xFF01)
    0x09, 0x01, // Usage (Vendor-defined 0x0001)
    0xa1, 0x01, // Collection (Application)
    0x09, 0x10, // Usage (Vendor-defined 0x0010)
    0x15, 0x00,       //    Logical minimum (0)
    0x26, 0xff, 0x00, //    Logical maximum (255)
    0x75, 0x08,       //    Report Size (8)
    0x95, 0x40,       //    Report Count (64)
    0x81, 0x02,       //    Input
    0xc0 // End Collection
 */
Transfer 35 get size for string at index 8 : 28 bytes (13 caracteres)
Transfer 36 get string at index 8:  PS VR Control    (associated to interface 5)
Transfer 37 get report descriptor from interface 5
/*
    0x06, 0x00, 0xff, // Usage Page (Vendor-defined 0xFF00)
    0x15, 0x00, // Logical Minimum(0)
    0x26, 0xff, 0x00, // Logical Maximun(255)
    0x09, 0x08, //Usage (Vendor-defined 0x0008)
    0xa1, 0x01, // Collection (Application)
    0x09, 0x80, // Usage (Vendor-defined 0x0080)
    0x85, 0x40, // Report ID (0X40)
    0x75, 0x08, // Report Size(0x8)
    0x95, 0x04, // Report Count(0x4)
    0xb1, 0x02, // Feature
    0xc0
*/
Transfer 38 put alternating setting to 3 to interface 6
Transfer 39 get size for string at index 10 : 26 bytes (12 caracteres)
Transfer 40 get string at index 10: PS VR BulkIn  (associated to interface 7)
Transfer 41 get size for string at index 11: 30 bytes (14 caracteres)
Transfer 42 get string at index 11: PS VR Control2  (associated to interface 8)
Transger 43 get report descriptor from interface 8
/*
    0x06, 0xf0, 0xff, // Usage Page (Vendor-defined 0xFFF0)
    0x15, 0x00, // Logical Minimum(0)
    0x26, 0xff, 0x00, // Logical Maximum(255)
    0x75, 0x08, // Report Size(0x8)
    0x95, 0x3f, // Report Count(0x3F)

    0x09, 0x01, // Usage(Vendor-defined 0x0001)
    0xa1, 0x01, // Collection(Application)
    0x85, 0xd0, // Report ID(0xD0)
    0x09, 0xd0, // Usage(Vendor-defined 0x00d0)
    0xb1, 0x02, // Feature

    0x85, 0xd1, // Report ID(0xD1)
    0x09, 0xd1, // Usage(Vendor-defined 0x00d1)
    0xb1, 0x02, // Feature

    0x85, 0xd2, // Report ID(0xD2)
    0x09, 0xd2, // Usage(Vendor-defined 0x00d2)
    0xb1, 0x02, // Feature

    0x85, 0xd3, // Report ID(0xD3)
    0x09, 0xd3, // Usage(Vendor-defined 0x00d3)
    0xb1, 0x02, // Feature
    0xc0, // End Collection 

    0x09, 0x02, // Usage(Vendor-defined 0x0002)
    0xa1, 0x01, // Collection(Application)
    0x85, 0xe0, // Report ID(0xE0)
    0x09, 0xe0, // Usage(Vendor-defined 0x00e0)
    0xb1, 0x02, // Feature

    0x85, 0xe1, // Report ID(0xE1)
    0x09, 0xe1, // Usage(Vendor-defined 0x00e1)
    0xb1, 0x02, // Feature

    0x85, 0xe2, // Report ID(0xE2)
    0x09, 0xe2, // Usage(Vendor-defined 0x00e2)
    0xb1, 0x02, // Feature

    0x85, 0xe3, // Report ID(0xE3)
    0x09, 0xe3, // Usage(Vendor-defined 0x00e3)
    0xb1, 0x02, // Feature

    0x85, 0xe4, // Report ID(0xE4)
    0x09, 0xe4, // Usage(Vendor-defined 0x00e4)
    0xb1, 0x02, // Feature

    0x85, 0xe5, // Report ID(0xE5)
    0x09, 0xe5, // Usage(Vendor-defined 0x00e5)
    0xb1, 0x02, // Feature

    0x85, 0xe6, // Report ID(0xE6)
    0x09, 0xe6, // Usage(Vendor-defined 0x00e6)
    0xb1, 0x02, // Feature

    0x85, 0xe7, // Report ID(0xE7)
    0x09, 0xe7, // Usage(Vendor-defined 0x00e7)
    0xb1, 0x02, // Feature

    0x85, 0xe8, // Report ID(0xE8)
    0x09, 0xe8, // Usage(Vendor-defined 0x00e8)
    0xb1, 0x02, // Feature

    0x85, 0xe9, // Report ID(0xE9)
    0x09, 0xe9, // Usage(Vendor-defined 0x00e9)
    0xb1, 0x02, // Feature

    0x85, 0xef, // Report ID(0xEF)
    0x09, 0xef, // Usage(Vendor-defined 0x00ef)
    0x95, 0x04, // Report Count(0x4)
    0xb1, 0x02, // Feature
    0xc0, // End Collection 

    0x09, 0x40, // Usage(Vendor-defined 0x0040)
    0xa1, 0x01, // Collection(Application)
    0x85, 0xf0, // Report ID(0xF0)
    0x09, 0x47, // Usage(Vendor-defined 0x0047)
    0x15, 0x00, // Logical Minimum(0)
    0x26, 0xff, 0x00, // Logical Maximum(255)
    0x75, 0x08, // Report Size(0x8)
    0x95, 0x3f, // Report Count(0x3F)
    0xb1, 0x02, // Feature

    0x85, 0xf1, // Report ID(0xF1)
    0x09, 0x48, // Usage(Vendor-defined 0x0048)
    0x95, 0x3f, // Report Count(0x3F)
    0xb1, 0x02, // Feature

    0x85, 0xf2, // Report ID(0xF2)
    0x09, 0x49, // Usage(Vendor-defined 0x0049)
    0x95, 0x0f, // Report Count(0x0F)
    0xb1, 0x02, // Feature

    0x85, 0xf3, // Report ID(0xF3)
    0x0a, 0x01, 0x47, // Usage(Vendor-defined 0x4701)
    0x95, 0x07, // Report Count(0x07)
    0xb1, 0x02, // Feature
    0xc0 // End Collection 
 */
Ttrasfer 44 set idle to interface 8

Translation to c/c++ code with libusb api call is direct with all information from dump. All repoorts are described in morpheus_bridge source code so it's confirm all  is fine.

TO BE CONTINUED
Autor: Antonio Marquez aka bigboss

De 0 a exploiting (VI)

Buenas amigos, como ya sabéis soy Fare9, y vengo con otra entrada de "De 0 a exploiting", aquellos posts que van de eso de buscar vulnerabilidades en software, ya sabéis. Hoy tengo una técnica que más o menos se parece a la vista en el anterior post. Esta técnica se llama "Off-By-One", en la cual en lugar de poder modificar todo el valor de EBP, podemos modificar máximo 1 Byte.

antes de nada, ya sabemos, los preparativos:
###############################################

Desactivar la aleatoriedad en las direcciones de la pila, para ello debeis ejecutar el comando (como root):
echo 0 > /proc/sys/kernel/randomize_va_space

Compilar (hoy si) con:
gcc -g -fno-stack-protector -z execstack codigo.c -o programa

###############################################
(sabéis que Fare9, hace copy-paste siempre con los preparativos del anterior post...)


Bien, vamos a ver un código en C, con el cual intentaremos entender esto:

Como vemos, el código es muy parecido al que vimos en el post anterior, pero esta vez, en el límite en lugar de sumar 4 sumamos 1, y el objetivo es que al comparar "cookie" con 0xdefaced, salga lo mismo.
Bien "off-by-one" es referido a que esta vez, sobreescribimos 1 byte, con lo cual intentaremos que eso juege a nuestro favor.
En este reto es interesante ver como se realiza la comparación de "cookie" con 0xdefaced:
Ejecutamos el programa con cualquier argumento y dentro de nuestro debugger visual edb.
Después de navegar un poco por el código, vemos que la comparación es la siguiente, que se compara "cookie", pero esta variable se referencia como [ebp-28] y resulta que un byte de EBP lo podemos modificar (el último byte) ...

Bien, vamos a volver a ejecutar y veamos el valor de EBP que se metió en la pila a la hora de realizar el stack frame (recordais de anteriores posts, el stack frame), vamos mirando por la pila y lo tenemos antes de un return:

Vemos que ebp ha metido en la pila el valor "bffff168" (tenemos además luego la dirección de retorno y  el argumento que hemos pasado esta vez), pues el 68, lo podremos modificar, a nuestro antojo. Nuestro objetivo será, modificar ese 68, por ejemplo por 'A' o 41 en valor ASCII, y si le restamos 28 ([ebp-28]) tenemos que la dirección que se usará para comparar es:

bfff:f141 - 1Ch (valor 28 en hexadecimal) = bfff:f125

Bien la dirección donde tendrá que estar el 0xdefaced es bfff:f125, ahora veremos donde empieza a copiar nuestros valores, para ello ejecutamos realizamos un par de veces el bucle for, y vemos donde empieza a copiar, no hay más dificultad (guiño guiño):
Como vemos, empezó a copiarse en bfff:f030, y que podemos llegar a escribir hasta bfff:f135 (el lugar donde se realiza el off-by-one), bfff:f125 está entre medias...
Ahora realizamos los siguientes pasos:

  1. Calcular cuanta basura tenemos que meter antes de meter el 0xdefaced:
     bfff:f125 - bfff:f030 = f5h = 245 bytes 
  2. Meter 0xdefaced 
  3. Meter más basura hasta el último byte que meteremos una 'A' (yo meto un montón de 'A's y que se encargue el programa de parar, por tanto nunca falla).
Vamos entonces a montar un programita exploit en python:
 Con el método pack, de struct, pasamos el 0xdefaced a Little-endian, luego como vemos metemos 245 'A' antes del defaced y luego todo 'A' de basura. 
Ejecutemos y veamos que pasa en la pila (podemos establecer un breakpoint en el leave de la función, así el bucle for se ejecuará completo):
 Breakpoint en el leave, para ejecutar el for.
Vemos que al comienzo del buffer se han metido un montón de 'A's
Al final del buffer, hemos modificado el último byte que se metará en EBP, con una 'A', ahora vale bffff141.
Y como vemos, en bfff:f125, se empieza a meter defaced, al contrario (pues estamos en Little-Endian) y con un 0 al final, ya que para tener un total de 8 bytes había que meter eso. Por tanto se ha metido ed, ac, ef, 0d (Recordemos que son números en hexadecimal, no letras).
Sigamos ejecutando y veamos en qué acaba la comparación:
Vemos que, vamos a realizar la comparación y el debugger, ya nos muestra abajo el valor de la dirección de memoria [ebp-28]... Vaya parece que es 0x0defaced (como dijo Nostradamus). Por tanto la comparación sale correcta y tachaaaan, conseguimos una shell.
Bien, para ejecutarlo directamente en shell, vamos a comentar el primer os.system... y descomentar el segundo del código del exploit y ejecutamos:

Como vemos, ya tenemos nuestra rica shell. Para el programador que se le pasó por una:

Hasta aquí el post de "De 0 a exploiting" de hoy, en el siguiente post ya veremos "Return to libc", algo que cuando lo vi por primera vez, me pareció muy muy interesante.

Nos vemos en los próximos post de Fare9
--------------------------------------------------------FIN