Usando la API de Virustotal

Índice:
1.-Analizando un archivo
2.-Realizando comentarios
3.-Analizando una URL

Introducción

Quien no conoce Virustotal, el servicio online en el que podemos subir un archivo y nos lo escanea con hasta 42 antivirus para tener varios resultados.

Hace ya tiempo, los que se dedicaban al desarrollo de Malware usaban el KIMS (que recuerdos me trae), que era un software que se descargaba varios antivirus (creo que hasta 20) y los analizaba localmente en tu propio ordenador. Ahora con el avance de los tiempos, tenemos servicios online como este del que voy a hablar hoy, o de NoVirusThanks, el cual tuvo su auge en cuanto los desarrolladores supieron que la plataforma Virustotal distribuia lo que subian (o eso se dijo), por lo que si subian virus que estaban desarrollando, no les traia cuenta que estos ficheros fueran dados a las marcas de Antivirus para que los analizasen y detectasen posteriormente.

Una de las razones que me ha llevado a interesarme por esta API, es su increible simpleza y flexibilidad, como podremos ver a continuación en un script. Antes de nada, decir que este script, y todo lo que pondré a continuación está sacado de aquí. La razón por la cual quiera hacer un post de esto, es para dar a conocer más esta API y que todos vean lo simple que es.

Antes de dar paso al uso de la API, quisiera agradecer a Julio Canto y Emiliano Martínez (del staff de VirusTotal) por su total ayuda (incluso en un domingo =P) a través de twitter y por correo electrónico. Sin ellos no podría haber terminado este post, ya que tuve dudas importantes con el uso de la API analizando webs.

A continuación, vamos a hacer lo más simple, y es analizar un fichero y obtener el reporte de los antivirus. Para ello lo primero que tenemos que hacer, es registrarnos en Virustotal.com, y obtener la API Key, que se halla en My Account -> Inbox -> Public API.

1.-Analizando un archivo

Ahora os dejo con el código, comentado y explicado, de cómo analizar un fichero virus.exe y obtener el resultado:

0: fecha (-2 horas española)
--->1: Array
------>Nombre del antivirus: Resultado
------| Si no detecta nada, el resultado está vacio
------| Hay 42 antivirus
*/

echo "
"; if($retrieve){ foreach($retrieve['report'][1] as $clave => $valor) echo $clave . ": " . $valor . "
"; //Esto nos devuelve todos los antivirus, seguido del resultado que nos dan echo "
"; } function virustotal_scanfile($filepath, $key){ //Editada y comentada por lipman // Author: Peter Bailey // Website: Bailey-Projects.com $post = array('key' => $key, 'file' => '@'.$filepath); //preparamos lo que vamos a pasar por POST $ch = curl_init(); //Iniciamos CURL curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); curl_setopt($ch, CURLOPT_URL, 'http://www.virustotal.com/api/scan_file.json'); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($ch); curl_close($ch); //Cerramos CURL } function virustotal_getreport($resource, $key){ $url = 'https://www.virustotal.com/api/get_file_report.json'; $fields = array('resource'=>$resource, 'key'=>$key); foreach($fields as $key=>$value) $fields_string .= $key.'='.$value.'&'; $fields_string = rtrim($fields_string,'&'); //Preparamos la variable que enviaremos por el método POST $ch = curl_init(); //Iniciamos CURL curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_POST,count($fields)); curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($ch); curl_close($ch); //Cerramos CURL $result = json_decode($result, true); //Decodeamos usando la función de json el resultado if(isset($result['report'][0])) return $result; //Si todo sale bien, lo devolvemos a la función else return false; } ?>

Resultado (seguro que podeis adiviniar que virus testeé):

2.-Realizando comentarios

En los reportes que se generan online tras el analizado de un fichero, se pueden realizar comentarios, incluso puntuar si estos son buenos o malos. Para realizar comentarios también disponemos de una función que he explicado en los comentarios del script:

$key,'comment'=>$comment);
	 if(preg_match('/^https?:\/\/.*/',$fileorurl)){
	    $fields['url']=$fileorurl;
	 } else {
	    $fields['file']=$fileorurl;
	 }
	 //Esto detecta si lo que pasamos es la URL o el hash del archivo, pero como
	 //dije anteriormente, a mi pasando la URL no me funciona, asi que podriamos
	 //deshacer este if-else
	
    $fields_string='';
	foreach($fields as $key=>$value)
	   $fields_string .= $key.'='.$value.'&';
	
	$fields_string=rtrim($fields_string,'&');
	//Creamos lo que vamos a pasar por POST-JSON
	
        $ch = curl_init();
	//Iniciamos CURL
	curl_setopt($ch,CURLOPT_URL,$url);
	curl_setopt($ch,CURLOPT_POST,count($fields));
	curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

	$result = curl_exec($ch);

	curl_close($ch);
	//Cerramos CURL
	$result = json_decode($result, true);
	//Decodeamos el resultado para saber si ha sido exitoso o no el proceso

	 if($result['result']=="1"){
	 	return true;
	 } else {
	 	return false;
	 }
}

Analizando una URL

Virustotal también nos permite analizar una URL. A priori, al analizar una URL, los motores de análisis tales como Google Safebrowsing y el de Firefox, nos indican la maliciosidad de la web (devuelto en un array, al igual que los resultados de cuando analizábamos un archivo). Pero además de esto, si la URL que indicábamos corresponde a un archivo, también nos devuelve un identificador que posteriormente podemos usar para ver si ese archivo es detectado o no.

Aquí el código, explicado:

$key = 'API_KEY';
//Api que se obtiene en el perfil
$file = "http://i476.photobucket.com/albums/rr125/lipmandj/asd.jpg";
//URL a analizar

$identificador = virustotal_scanurl($file,$key);

$retrieve = virustotal_geturlreport($key,$identificador);


if($retrieve){
	print_r($retrieve); // Array que contiene el reporte
}

function virustotal_scanurl($url, $key){

	// Esta función envia la URL

	
    // Author: Kenny Lyons aka ih8censorship
	// Website: http://pasture.sourceforge.net
    // Editado por lipman
	
    //URL a la que enviaremos los datos
    $url = 'http://www.virustotal.com/api/scan_url.json';
    //Preparamos los campos de lo que vamos a enviar
	$fields = array('url'=>$url, 'key'=>$key);
    $fields_string='';
	foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
	$fields_string=rtrim($fields_string,'&');

    //Procedemos a enviarlo mediante cURL
    $ch = curl_init();

	curl_setopt($ch,CURLOPT_URL,$url);
	curl_setopt($process, CURLOPT_HTTPHEADER, array("Content-Type: text/xml","SOAPAction: \"/soap/action/query\"", "Content-length: ".strlen($fields_string))); 
	curl_setopt($ch,CURLOPT_POST,count($fields));
	curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	
	$result = curl_exec($ch);

	curl_close($ch);
	//Tras enviarlo, cerramos la conexión y decodeamos el resultado devuelto
	$result = json_decode($result, true);
	
	
	if($result['result']=="1"){ //Si todo va bien, devolvemos la ID del scan
		return $result['scan_id'];
	} else {
		return false;
	}
	
}

function virustotal_geturlreport($key,$resource,$scan=false){

	// Nos devuelve el reporte
	
    // Author: Kenny Lyons aka ih8censorship
	// Website: http://pasture.sourceforge.net
    //Editado por lipman	

    //URL a donde enviaremos los datos
    $url = 'http://www.virustotal.com/api/get_url_report.json';
    //Preparamos los campos
	$fields = array('resource'=>$resource, 'key'=>$key,'scan'=>$scan);
    $fields_string='';
	foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
	$fields_string=rtrim($fields_string,'&');
    //Finalmente, usamos cURL para enviarlo y recoger el resultado
    $ch = curl_init();

	curl_setopt($ch,CURLOPT_URL,$url);
	curl_setopt($ch,CURLOPT_POST,count($fields));
	curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	
	$result = curl_exec($ch);

	curl_close($ch);
	
	$result = json_decode($result, true);
	
	 if($scan && $result['result']=="0"){
	 	return $result['scan_id'];
	 } else {
	 	return $result;
	 }
	
}

Saludos, lipman