De 0 a exploiting (VII)

 Hola amigos soy Fare9, y después de un largo periodo en el que he estado liado con exámenes, vuelvo con el cursillo de exploiting, hoy veremos una técnica muy interesante llamada "Return to Libc", pero antes aquí una cabecera que he hecho con el paint:

Aquí dejo los enlaces a los anteriores "de 0 a exploiting" para quien no nos haya seguido:

1. De 0 a exploiting I
2. De 0 a exploiting II
3. De 0 a exploiting III
4. De 0 a exploiting IV
5. De 0 a exploiting V
6. De 0 a exploiting VI

Además, sabéis que podéis seguirme en twitter: Fare9 twitter
Cualquier duda intentaré responder lo antes posible por aquí.


Pero como siempre, aquí los preparativos:

 

Hoy, NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. La técnica que veremos hoy, nos va a quitar que tengamos que desactivar una de las medidas de seguridad así que hoy sólo nos quedaremos con una parte:

###############################################

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

###### ACTUALIZACIÓN
Recompilando los ejecutables en la última versión de Ubuntu, me activa el stack protector por defecto (conocido como canary value), por tanto para compilar, podéis quitar las opciones de -g -z execstack.

Podéis utilizar esto para compilar:
gcc -fno-stack-protector codigo.c -o programa
 ###############################################


La teoría de por qué hoy no compilaremos raroraroraro

Una medida de protección contra los ataques de stack overflow, es el marcado de páginas de memoria como no "ejecutables", en caso de meter un payload en la pila e intentar ejecutarla cuando tenemos esta protección resulta inutil. Esto se hace con un bit conocido como NX, este bit es dependiente del hardware, y Linux es capaz de emularlo con PaX, ya que las arquitecturas ARM y IA32 no lo implementan de por sí. 


Return to Libc

esta es una técnica útil cuando se nos da este problema, que llegamos a un sistema y no podemos meter un payload en la pila. De momento vamos a decir que lo que veremos hoy será una explotación en local y por eso aplicaremos varias técnicas hoy.

Antes de nada necesitamos ver que código vulnerable usaremos:

En return to libc lo que haremos será ejecutar directamente un método de la librería Libc (a que no os lo esperabais), para ello sobreescribiremos la dirección de EIP que es guardada cuando se ejecuta una función. La función que ejecutaremos será una del estilo system(), execve(), execvp()... Tendremos que ver entonces como conseguir hacerlo.
A la hora de montar nuestro exploit tendremos que ver bien como funciona la pila y sobre todo las llamadas a las funciones, volvamos a recordar un dibujo:
https://1.bp.blogspot.com/-_1OiQtXo_z8/WFVSKJ1Bv_I/AAAAAAAAAJY/I98uYsiDryMh1bchi0MN9JMzH5FahAtZQCLcB/s1600/exploit2.PNG
A la hora de llamar a una función, se pasaban los argumentos, se guardaba el valor de EIP y finalmente se montaba toda la función, con esta técnica haremos algo parecido, pondremos el puntero a la función a ejecutar, el valor de su propio EIP (luego veremos que usaremos) y los argumentos, en este caso un puntero a una cadena /bin/sh.
Aún tendremos que desactivar ASLR para tener en cada ejecución las direcciones en el mismo sitio y también necesitamos saber cuantos bytes podemos escribir antes de sobreescribir EIP.

Esta técnica nos servirá para ver que algunas medidas de seguridad, no son tan seguras:


Primero ejecutaremos el programa con unos argumentos más o menos normales, para ver su ejecución:

Como se puede ver, nada malo ha pasado, se ha ejecutado el programa sin ninguna dificultad.
Ahora vamos a intentar petar el programa, para ello tiraremos de una cadena enorme en python:

Ahora si, hemos metido 1024 Aes, y qué ha pasado?
En el siguiente video en el segundo mostrado tendréis la respuesta: https://youtu.be/k7xCUbgzT9o?t=7
(Más tecnicamente es debido a un abuso de frame pointer en la función strcpy)

Necesitamos entonces saber en que momento pasó lo que dice el video, para ello calcularemos el número de bytes metidos antes de petar el programa

Obtención del número de bytes hasta sobreescribir EIP

para esta tarea, usaremos a nuestro gran amigo edb debugger, con el cual necesitamos ver el lugar donde nuestro programa copia el argumento con strcpy, y luego el sitio donde se guarda el EIP de retorno.
Ejecutamos entonces edb debugger con una cadena reconocible como el segundo argumento:


Tenemos que en memoria se copiará la cadena Fare9 (ajam, ajam, egocéntrico, ajam, ajam), a la hora de abrir edb, para ir a la función principal pulsaremos F9 (ajam, ajam que coincidencia).


Tendremos algo así, ahora iremos ejecutando con F7 (ya que queremos meternos en la función que sabemos tiene la vulnerabilidad).

Llegamos a algo así, vemos abajo a la derecha (el stack),  los argumentos pasados a la función, y en cuanto pulsemos F7 de nuevo entraremos a la función:

La función es algo así, además si miramos abajo a la derecha, vemos donde se guarda el valor de EIP, esta es la dirección bfff:f3fc. Necesitamos llegar a la dirección donde se guarda la cadena (el buffer), vamos ejecutando hasta casi llegar a strcpy (sin ejecutarlo):


Aquí tenemos los argumentos pasados a strcpy, el primer argumento es el buffer donde se guardará la cadena, bfff:f1f0.

Ahora podemos calcular la distancia entre el buffer que usa strcpy y el sitio donde se guarda EIP, para saber el máximo número de bytes que tenemos antes de sobreescribir ese valor:

bfff:f3fc - bfff:f1f0 = (nos cargamos bfff ya que queda a 0, las otras f más de lo mismo y nos queda) 20c = 254 en decimal

Por tanto tenemos ya un dato.

Número de bytes antes de sobreescribir EIP = 254.

Ahora calcularemos el puntero a system, además como dijimos después de system meteremos un valor que será el EIP de system, en el cual meteremos por ejemplo una función "exit", así evitaremos que el programa al volver de la ejecución system(/bin/sh) pete y deje logs que nos descubran, para buscar los punteros a las dos funciones sigamos:


Puntero a las funciones system y exit
Esto será facilito y para toda la familia, además de rápido e indoloro (de momento). Usaremos el debugger gdb, y ejecutaremos el programa, una vez ejecutado buscaremos los punteros, que como ASLR lo hemos desactivado, pues siempre serán los mismos:

 
Tenemos ya los dos punteros, a uno le llamaremos en un alarde de originalidad &system y al otro &exit (recordando nuestras clases de C, & era la dirección de memoria de algo, un puntero).

&system = 0xb7e38b30
&exit = 0xb7e2c7e0

Ahora finalmente necesitamos un puntero a una cadena /bin/sh, para eso como dije estamos en local, y lo que podemos hacer es crear una variable de shell y obtener su dirección, igual esto será algo fácil e iremos paso por paso.

Puntero a cadena /bin/sh

Lo primero que haremos será crear la variable de shell, esta debe ser global por tanto usaremos export:
es sencillo, simplemente establecemos el nombre de la variable y un igual seguido de la cadena, con un echo podemos ver que todo ha salido bien. Como aprendí con uno de los videos de exploiting de Adastra, las variables de la shell se pasan todas a los programas al principio de su ejecución a la pila, por tanto con edb debugger, podemos arrancar nuestro programa y sin ejecutar nada obtener del stack una de las direcciones:

Aquí tenemos una dirección bffff651 el principio de la cadena SHELL2=/bin/sh, pero necesitamos avanzar hasta un byte menos que la cadena que buscamos (en este caso el '='), vamos contando bffff651 apunta a S, ...52 a H, ....53 a E,........57 a =, bien entonces nos quedaremos con bfff:f657 ya que luego vendrá nuestra rica y preciada cadena:

&/bin/sh = 0xbffff657

ACTUALIZACIÓN###################################
para los que no quieran contar, o les pueda dar fallos, le voy a dejar el código de un código en C, que al compilar debemos ejecutarlo indicando la variable SHELL2 y el nombre del programa (en mi caso ret_to_libc), así obtendremos la dirección directamente: (Código Linux Exploiting capítulo 4)


Con este programa conseguis directamente la dirección exactamente sin contar.

Finalmente queda la explotación de la vulnerabilidad




Recopilación de datos y explotación de la vulnerabilidad


Número de bytes para llegar a EIP = 254
&system = 0xb7e38b30
&exit = 0xb7e2c7e0
&/bin/sh = 0xbffff657

"En 2017 cuatro de los números usados para la explotación de un programa, fueron borrados de memoria por una explotación que no cometieron. No tardaron en encontrar otra forma de ejecución en memoria. Hoy, buscados todavía por políticas de ejecución seguras, sobreviven como payloads de fortuna. Si tiene usted algún zero day, y se los encuentra, quizá pueda utilizarlos...", Fare9 ,desvarío mental.

Bien usaremos a nuestro gran python para montar una cadena, como ya dije tenemos que reemplazaremos la dirección de vuelta EIP por el puntero a system, este tendrá su propio EIP en memoria que le sigue, el cual se usará cuando se salga de system, este dijimos que era exit, y siguiendo a exit tendremos los argumentos, usaremos un dibujo para entenderlo mejor:
Gracias a tí Fare9, mi vida es más fácil =)...

Bueno el dibujo lo deja más o menos claro, rellenamos el buffer con un montón de Aes, y al llegar a eip metemos el puntero a system, seguido tenemos un puntero de retorno, en este caso decidimos exit y finalmente los argumentos, en este caso puntero a /bin/sh, podríamos poner por ejemplo un puntero a ls, cp, cat /etc/shadow ....

Creemos con la ayuda de nuestro quiero python, la explotación:
Vamos a ver que ha pasado, en la ejecución:

EXPLOTADOOOOOOOOOOOOOOOOOOOOOOOOOOOOO:

Veamos que pasa si en lugar de poner un puntero a exit, no ponemos algo razonable, algo como..."\xe2\xc7\xe2\xb7" (4 bytes). Sólo hemos modificado el último byte en lugar de e0, e2:
Como dije, violación de segmento, esto crea logs, alerta a todo el mundo...




Hoy hemos aprendido que aunque no nos permitan ejecutar código en la pila, nosotros podemos seguir ejecutando código, bypasseando la medida de seguridad que marca la memoria de pila como no ejecutable, para ello hemos redirigido el código a una zona de memoria ejecutable como son las librerías.

--------------------------------------------------------FIN

Para el próximo post veremos como encadenar funciones con una técnica llamada ROP, la cual igual veremos más adelante de forma más avanzada, así que será una introducción para que nuestra mente se vaya haciendo a ello:


Pues hasta el próximo de 0 a exploiting.

Reversing PlayStation 4 Camera

I have been working with PlayStation 4 Camera since 2013. So i want to share with you all things learned since then.


First of all, if device has not a public/free driver , you need to make reverse engineering  and you need to look for information about its chipset and make a research about it. So you need to open the device and look for information about its different chips. After making some research we can show the next high level design diagram:

PlayStation 4 Camera is using a propietary connector called AUX, however it is a USB 3 cable so our first goal was to cut off the AUX connector and connect it to  an USB3 male connector, after this we can connect directly to Mac/PC with USB3 female ports.  Next step was to get an USB sniffer capture from PlayStation 4 with a beagle device in the middle, without this we could not have learnt about how to initialize the device and their different options.

Chips description:

  • OV580. It is an asic from Omnivision a typical custom USB bridge solution to manage all other chip. No information or datasheet about it without signing a NDA with Omnivision. Other companies using it are Mantis Vision and LeapMotion. I have worked with others Omnivision USB bridge solutions included in PlayStation EyeToy(OV519) and PlayStation Eye(OV534) so basically it is the same work i made with other drivers for Omnivision.

  • OV9713.  Two cmos sensors well documented with full datasheet available in google.

  • AK5703. An analogical to digital converter connected with an microphone array (4). Datasheet is available.  The datasheet was very helpfull to get audio properly from PlayStation 4 Camera.

  • 4g51A. An eeprom chip. It contains the initial configuration for PlayStation 4 Camera.

When you connect device to a Mac/PC  with  USB3 it  is in boot mode waiting for loading firmware. Analizing sniffer capture we got the firmware and steps needed  to load it  to device. So after loading firmware you have and special UVC Camera device and you can learn about their different streaming modes.

Interface 1 alt setting 0 describe all video modes with these possible options:

  •     mode 0 fps 60(default), 30, 15, 8 video left and video right frames 1280x800

  •     mode 1 fps 120(default), 60, 30, 15, 8 video left and video right frames 640x400

  •     mode 2 fps 240(default), 120, 60, 30 video left and video right frames 320x192

OV580 is delivering in each mode:

  •     mode 0 3448x2x808 bytes frame each row with:
        header 32 bytes
        audio 64 bytes
        video left 1280x2 bytes
        video right 1280x2 bytes
        video interleave 840x2 bytes

  •     mode 1 1748x2x408 bytes frame each row with:
        header 32 bytes
        audio 64 bytes
        video left 640x2 bytes
        video right 640x2 bytes
        video interleave 420x2 bytes
  •     mode 2 898x2x200 bytes frame each row with
        header 32 bytes
        audio 64 bytes
        video left 320x2 bytes
        video right 320x2 bytes
        video interleave 210x2 bytes

Part of Header is showed in the next screenshot:


Part of Audio is showed in the next screenshot:


Audio has 4 channel i use Audicity tool loading a 10 second capture a reproducing 4 audio channels with success.  AK5703 datasheet was very helpfull. An screenshot from audicity tool:


Videl Left and Right can be converted to RGB with CV_YUV2RGB_YUY2 conversion:

cv::Mat yuv(size_y,size_x,CV_8UC2 ,in);
cv::Mat rgb(size_y,size_x,CV_8UC3, out);
 cv::cvtColor(yuv, rgb, CV_YUV2RGB_YUY2);

Video interleave it is also the same video format but it is making a mix of two sensor

A sample application made using basic PS4EYECam driver showing a 640x400 mode for two PlayStation Cameras at the same time:


Low level usb stuff is implemented and available in my repository. EyeLab  is a  poc of multi camera   application using PS4EYECam driver and it is not in the repository,  you don't need to make changes  in the driver to support multi cameras you need to do it at application level.

So after this i can say that PlayStation 4 Camera is full documented and it can be supported on other platforms. All information needed is here and in my repository.

PlayStation 4 receives frames with format explained here. I suppose that secondary processor makes all the job to parse frames(video and audio) and connect with image/audio libraries from sdk(if someone want to share it with me you can contact with me :P).  PlayStation 4 only has 1 AUX port so a multicam solution would be hard to implement like i am doing now in Osx.

Autor: Antonio Marquez aka bigboss

Bitcoin 101: Fundamentos técnicos

Seguramente hayas oído hablar de Bitcoin, la moneda criptográfica de moda, y quieras profundizar un poco en el tema. Pues bien, el objetivo de esta serie de post es precisamente ese, profundizar en Bitcoin, viendo primero los fundamentos de esta tecnología, para posteriormente ir avanzando en su uso y configuración.

Bitcoin es una criptomoneda que empezó a funcionar en 2009. Una criptomoneda es, por así decirlo, un método de intercambio de información, pero que en este caso representa una moneda digital.
Esta divisa está completamente descentralizada, y no está gestionada por ningún organismo central  (esta es una de las mayores confusiones para las personas no iniciadas en Bitcoin). Entonces, ¿Quién la controla? Pues la respuesta es que nadie, pero todos los que la usan la sustentan, aunque no se puede decir que la controlen.

Para entender este concepto hay que conocer el concepto de blockchain, también muy de moda últimamente. Una blockchain, o cadena de bloques, es una base de datos distribuida que permite almacenar información en diferentes nodos repartidos en diferentes partes del mundo. Una de las características de blockchain es que, una vez se publica una información, no puede ser modificada. En la blockchain de Bitcoin se almacenan las transacciones, que son públicas e irreversibles. Por definición de protocolo, no puede existir más de 21 millones de bitcoins (la minería se basa en una serie matemática telescópica).

Gracias a todo esto, Bitcoin ofrece las siguientes características:

  • Moneda descentralizada
  • Pagos irreversibles
  • Transparencia en las transacciones (son públicas)
  • Cantidad finita de moneda
  • Posibilidad de pagos anónimos. ¡ojo con esto, que no es tan simple!

El protocolo Bitcoin

El protocolo de Bitcoin se compone de tres elementos principales:
  • Las carteras, o wallets
  • Las direcciones
  • Las transacciones

Una cartera de Bitcoin se puede generar de forma completamente offline, y contiene un conjunto de claves criptográficas que se utilizarán, entre otras cosas, para generar direcciones, que son las emisoras/receptoras de las transacciones.


Una dirección de Bitcoin es una secuencia alfanumérica de 33 caracteres, codificada en base 58, para evitar errores de lectura de algunos caracteres, en determinados tipos de letra. 

Una cartera, o wallet, puede generar varias direcciones Bitcoin. De hecho, es recomendable utilizar una dirección para una transacción únicamente, y no repetirla más. El saldo pertenece a la cartera, y no a una dirección.

Una transacción es una operación de cambio de propiedad. Es lógico en pensar en una transferencia que envíe una cantidad de algo, en este caso bitcoins, a otra persona. En realidad el concepto de transacción, aunque a alto nivel sí que es un envío, sería el equivalente a decirle a todo el mundo (los nodos), que cierta cantidad de bitcoins, ya no son tuyos y que se los “transfieres” a otra persona. Cuando este mensaje llegue a todo los nodos, y lo hayan validado, esos bitcoins ya no te pertenecen, porque todo el mundo  sabe que son de la persona a las que se lo transferiste.


Por lo que si Alice quiere transferir 1 Bitcoin (BTC) de su cartera a Bob, lo que hará es generar un paquete que contenga la dirección de Bob y la cantidad de BTC a transferir, añadiendo la clave pública de Bob, y firmando con su clave privada (de Alice). De esta forma, se garantiza que la operación ha sido realizada por Alice.

Este paquete se envía a los nodos de la red, que tras realizar las operaciones matemáticas para comprobar la autenticidad de la transacción, lo retrasmiten a otros nodos, de forma indefinida, hasta llegar a toda la red. 

Es posible que te preguntes que clase de operaciones matemáticas son esas, o simplemente quieras conocer el protocolo a más bajo nivel. En el siguiente apartado se muestra el formato de los bloques, y qué significa cada campo dentro de los mismos.

La Blockchain


En este punto se tiene una idea más aproximada de qué es Bitcoin y cómo funciona el protocolo, pero todo el tema de la cadena de bloques aún debe sonar algo extraño. Para explicar cómo funciona la cadena de bloques, parece lógico explicar primero qué es un bloque.

Un bloque es un conjunto de datos estructurado que contiene una determinada cantidad de transacciones. Estos bloques se pueden extraer, transmitir y confirmar. La blockchain es una cadena de todos estos bloques. Se puede pensar en la blockchain como en un gran libro de contabilidad, en la que aparecen todas las transacciones, y se puede dar seguimiento a cada una de ellas.

Ya se conoce el concepto de bloque, pero aún queda por conocer cómo se estructura la información dentro del bloque. En la representación en disco, un bloque es un fichero binario que utiliza el software de Bitcoin. Dicho fichero tiene una cabecera, como es habitual en los ficheros binarios, con el siguiente formato:


Cabe mencionar que la información se representa en LittleEndian dentro del fichero. Los campos que contiene la cabecera son:
  • Magic Number: Contiene el valor 0xD9B4BEF9
  • Tamaño del bloque: Su propio nombre lo indica
  • Versión: version de Bitcoin utilizada
  • Hash anterior: Se trata del hash de la cabecera del bloque anterior.
  • Hash del contenido: Se trata del hash del contenido del bloque actual. (No puede contener el hash de la cabecera porque se incluiría a si mismo)
  • Timestamp: Fecha y hora, en formato timestamp
  • Límite (dificultad): Este campo ya es más complejo. Contiene una representación del límite del hash, que modela la dificultad. No debe confundirse con el propio límite. (se explica a continuación)
  • Nonce: Una serie de bytes modificables para hacer cumplir los criterios de dificultad.

La dificultad

El campo dificultad, por ponerle un nombre, es una representación de 4 bytes de un número de 32 bytes. ¿Cómo se hace eso? Pues a través de una mantisa y un exponente. El funcionamiento, que se puede ver en la siguiente imagen, es el siguiente:








El byte más significativo representa el exponente (de una base 256), y el resto la mantisa. Realizando la operación de la imagen, se obtendrá el verdadero límite del hash. Otra forma sencilla de calcular este valor es restar 3 al valor del exponente, y añadir esa cantidad de ceros a la derecha de la mantisa.




Esto proporciona como resultado el valor numérico límite del hash del bloque. Es decir, modificando el campo Nonce de la cabecera, y realizando el hash SHA-256 del bloque, su representación numérica tiene que ser inferior al límite obtenido en esta operación. Obviamente esto no se consigue a la  primera, y hay que ir probando diferentes combinaciones del nonce y realizar hashes del bloque. Este es la dificultad, computacionalmente hablando.

El cuerpo del bloque


Justo después de la cabecera del bloque, se almacena el número de transacciones que contiene y seguidamente, todas las transacciones, una detrás de otra.

El contador de transacciones no tiene una longitud fija. En realidad es de un tipo entero “compacto”, que es un tipo de dato utilizado por Bitcoin, y que tiene una longitud de bytes variable. Para poder obtenerlo se lee el primer byte, si es 0xFD, entonces tendrá 3 bytes de longitud; si es 0xFE tendrá 5 bytes de longitud; si es 0xFF tendrá 9 bytes de longitud, y si no es ninguno de esos valores, ocupará un solo byte, con el valor correspondiente.
 

 

Después de este valor se almacenan las transacciones, una después de otra. El formato de transacción es el siguiente:
  • Versión: Entero de 4 bytes
  • Total de inputs de esta transacción: Entero compacto, tal y como se ha visto anteriormente
  • Lista de inputs: Cada input tiene el formato TxIn, explicado más adelante
  • Total de outputs: Entero compacto, tal y como se ha visto anteriormente
  • Lista de outputs: Cada output tiene el formato TxOut, explicado más adelante.
El formato TxIn, tiene el siguiente formato:
  • Outpoint anterior: Ocupa 36 bytes (32 del identificador de transacción TxID, y 4 del índice del output)
  • Bytes del script: Entero compacto que representa el número de bytes del siguiente campo (signature script)
  • Signature script: Firma de la transacción. Se utiliza para comprobar la autenticidad de la misma
  • Número de secuencia: Entero de 4 bytes
El formato TxOut, tiene el siguiente formato:
  • Número de Satoshis: Entero de 8 bytes. Representa el número de Satoshis de la transacción. Un Satoshi es 0,00000001 BTC.
  • Bytes del script: Entero compacto que representa el número de bytes del siguiente campo (pk_script)
  • Pk_script: Datos que contienen las condiciones que deben ser satisfechas  para poder gastar esos satoshis. Se utiliza para verificar la autenticidad.

Después de este rollazo técnico ya tenemos una visión global de Bitcoin y conocemos con el suficiente nivel de detalle el protocolo de Bitcoin; Además, ya sabemos qué significa cada byte de un fichero de bloques.

¿Quién establece el precio del Bitcoin?

Llegados a este punto, es probable que te hayas preguntado cómo se establece el precio del Bitcoin. En este post  voy a intentar de explicar muy brevemente cómo se establece el precio del Bitcoin.

El precio de Bitcoin no lo establece ninguna entidad, sino que son sus usuarios los que hacen que su valor fluctúe; en base al uso que le dan, condicionado, entre otras cosas, por la confianza que se tiene en la moneda. En resumen, se basa en la ley de oferta y demanda.

No se puede comprar un Bitcoin si no hay nadie dispuesto a vender, y viceversa. Gracias a las plataforma de compra-venta de Bitcoins, este hecho es transparente para el usuario. Simplemente uno elige cuantos BTC quiere comprar o vender, y automáticamente da la orden. Sin embargo, internamente tiene que haber  una solicitud de transacción que encaje con la del usuario para que se pueda realizar. Debido a que no hay una plataforma única de compra-venta, el precio del Bitcoin no es único, y puede haber discrepancias entre plataformas. No obstante, se van equiparando.

Por otro lado, existen las plataformas de trading de Bitcoins, que permiten comerciar con Bitcoins directamente entre interesados, sin que el precio lo establezca un intermediario.

Cabe mencionar que una plataforma de trading no es una plataforma de compra-venta. Mientras que en una aplicación de compra-venta hay un precio establecido (el de mercado en este caso), en una plataforma de trading hay ofertas para comprar-vender Bitcoins, o lo que sea, con un precio específico por operación. Son estas operaciones en las plataformas de trading las que influyen en el precio de mercado de Bitcoin.







Bueno, con esto doy por concluido el primer  post de fundamentos de Bitcoins. Próximamente más post de esta serie: