<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>48Bits Blog &#187; Malware Analysis</title>
	<atom:link href="http://blog.48bits.com/category/malware-analysis/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.48bits.com</link>
	<description>48Bits ... The one and a half architecture land.</description>
	<lastBuildDate>Thu, 19 Jan 2012 11:31:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Comparación de binarios por grafo</title>
		<link>http://blog.48bits.com/2011/01/23/comparacion-de-binarios-por-grafo/</link>
		<comments>http://blog.48bits.com/2011/01/23/comparacion-de-binarios-por-grafo/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 18:33:44 +0000</pubDate>
		<dc:creator>matalaz</dc:creator>
				<category><![CDATA[48Bits Projects]]></category>
		<category><![CDATA[Malware Analysis]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=1694</guid>
		<description><![CDATA[Hace ya bastante tiempo me puse a mirar como buscar similitudes entre programas basándose exclusivamente en grafos y estadísticas de los mismos, procurando huir siempre que fuera posible del código ensamblador, con la ayuda de muchas ideas de la gente de 48bits, especialmente. La idea es poder buscar similitudes entre múltiples binarios para agruparlos (por [...]]]></description>
			<content:encoded><![CDATA[<p>Hace ya bastante tiempo me puse a mirar como buscar similitudes entre programas basándose exclusivamente en grafos y estadísticas de los mismos, procurando huir siempre que fuera posible del código ensamblador, con la ayuda de muchas ideas de la gente de 48bits, especialmente. La idea es poder buscar similitudes entre múltiples binarios para agruparlos (por ejemplo, para crear subgrupos de baterías de malware similares a partir de una batería más grande) o comparar 2 binarios y extraer sus similitudes (útil para buscar vulnerabilidades corregidas en parches, aunque este post no va de eso). El resultado de todo esto es una serie de algoritmos &#8220;WorksForMe&#8221; (TM) qué he implementado utilizando <a href="http://pyew.googlecode.com" target="_blank">Pyew</a> (inicialmente la idea era utilizar IDA pero, a pesar de que funcione mejor, me gusta más utilizar software libre y a poder ser mío, manías).<br />
<span id="more-1694"></span></p>
<p><strong>¿Qué coño es eso de Pyew?</strong></p>
<p>Para quienes no lo conozcan, <a href="http://pyew.googlecode.com" target="_blank">Pyew</a> es un proyecto Open Source muy similar a <a href="http://radare.org">radare</a> o hiew, escrito en Python y principalmente orientado a la automatización de análisis de malware. Pyew tiene soporte para muchos formatos de archivo (PDF, OLE2, &#8230;) pero los que nos importan ahora son PEs y ELF (aunque el soporte de ELF no es muy bueno que se diga).</p>
<p><strong>Análisis de código</strong></p>
<p>Cuando abrimos un archivo de este tipo (PE o ELF) Pyew realiza análisis de código para encontrar las funciones que se encuentren en este binario. Utiliza un algoritmo muy similar al de IDA: Analiza, instrucción por instrucción, todos los puntos de entrada del binario y va buscando llamadas a funciones, poniéndolas en una cola para posterior análisis, hasta agotar todos los elementos de dicha cola (podéis leer más del algoritmo utilizado en Pyew <a href="http://code.google.com/p/pyew/wiki/CodeAnalysis" target="_blank">aquí</a>). Después de este paso, opcionalmente, se pondrá a buscar funciones buscando los prólogos de función más típicos de x86 y x86_64.</p>
<p>Una vez que el análisis ha finalizado, se realizan unos cálculos estadísticos, y se obtienen muchos datos interesantes para la agrupación o búsqueda de similitudes, siendo los más importantes los siguientes:</p>
<ul>
<li>Funciones.</li>
<li><a href="http://en.wikipedia.org/wiki/Basic_block" target="_blank">Bloques básicos</a>.</li>
<li>Datos estadísticos de cada función (<a href="http://es.wikipedia.org/wiki/V%C3%A9rtice_%28teor%C3%ADa_de_grafos%29#V.C3.A9rtices_y_grados" target="_blank">grado</a> de entrada, de salida y <a href="http://es.wikipedia.org/wiki/Complejidad_ciclom%C3%A1tica" target="_blank">complejidad ciclomática</a>).</li>
<li>Datos estadísticos del programa (media, máxima y mínima del número de <a href="http://es.wikipedia.org/wiki/V%C3%A9rtice_%28teor%C3%ADa_de_grafos%29" target="_blank">nodos</a>, <a href="http://es.wikipedia.org/wiki/Arista_%28teor%C3%ADa_de_grafos%29" target="_blank">aristas</a> y valores de complejidad ciclomática).</li>
</ul>
<p>Explicado lo básico, vamos a ver los algoritmos que he implementado.</p>
<p><strong>Algoritmo 1: Sistema experto</strong></p>
<p>Esta fue una de las primeras ideas que tuve: Teniendo los datos de complejidad ciclomática media, máxima, mínima así como el número de funciones de un binario, esto se podría utilizar como un hash para comparar, rápidamente, 2 o varios binarios. Si todos los datos son iguales, los binarios son clasificados como &#8220;100% similares&#8221; (que no iguales). Si no lo son, entonces se calcula la distancia de estos valores y se le asigna un porcentaje a cada valor sacado:</p>
<ul>
<li>Media de la complejidad ciclomática: 50% de la diferencia.</li>
<li>Máxima de la complejidad ciclomática: 30% de la diferencia.</li>
<li>Mínima de la complejidad ciclomática: 10% de la diferencia.</li>
<li>Total de funciones: 10% de la diferencia.</li>
</ul>
<p>El siguiente es el código de ejemplo utilizado:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="co1"># This code is under the GPLv2</span><br />
<span class="kw1">import</span> <span class="kw3">os</span>, <span class="kw3">sys</span></p>
<p><span class="kw1">from</span> hashlib <span class="kw1">import</span> sha256<br />
<span class="kw1">from</span> pyew_core <span class="kw1">import</span> CPyew</p>
<p><span class="kw1">class</span> CExpertCluster<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, data<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">data</span> = data</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> compareTwoSets<span class="br0">&#40;</span><span class="kw2">self</span>, set1, set2<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Get the ciclomatic complexity statistical data of the 2 samples</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ccs1 = set1.<span class="me1">values</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">program_stats</span><span class="br0">&#91;</span><span class="st0">&quot;ccs&quot;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ccs2 = set2.<span class="me1">values</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">program_stats</span><span class="br0">&#91;</span><span class="st0">&quot;ccs&quot;</span><span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; avg_cc_distance = <span class="kw2">abs</span><span class="br0">&#40;</span>ccs1<span class="br0">&#91;</span><span class="st0">&quot;avg&quot;</span><span class="br0">&#93;</span> &#8211; ccs2<span class="br0">&#91;</span><span class="st0">&quot;avg&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; max_cc_distance = <span class="kw2">abs</span><span class="br0">&#40;</span>ccs1<span class="br0">&#91;</span><span class="st0">&quot;max&quot;</span><span class="br0">&#93;</span> &#8211; ccs2<span class="br0">&#91;</span><span class="st0">&quot;max&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; min_cc_distance = <span class="kw2">abs</span><span class="br0">&#40;</span>ccs1<span class="br0">&#91;</span><span class="st0">&quot;min&quot;</span><span class="br0">&#93;</span> &#8211; ccs2<span class="br0">&#91;</span><span class="st0">&quot;min&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; total_functions = <span class="kw2">abs</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>set1.<span class="me1">values</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">functions</span><span class="br0">&#41;</span> &#8211; <span class="kw2">len</span><span class="br0">&#40;</span>set2.<span class="me1">values</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">functions</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; difference = avg_cc_distance*<span class="nu0">0.5</span> + \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;max_cc_distance*<span class="nu0">0.3</span> + \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;min_cc_distance*<span class="nu0">0.1</span> + \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;total_functions*<span class="nu0">0.1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> difference</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> cluster<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; set1 = <span class="kw2">self</span>.<span class="me1">data</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; set2 = <span class="kw2">self</span>.<span class="me1">data</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">compareTwoSets</span><span class="br0">&#40;</span>set1, set2<span class="br0">&#41;</span></p>
<p><span class="kw1">class</span> CGraphCluster<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">deep</span> = <span class="kw2">False</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">timeout</span> = <span class="nu0">0</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> addFile<span class="br0">&#40;</span><span class="kw2">self</span>, filename<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">files</span>.<span class="me1">append</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> clear<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">files</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">results</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">data</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> processFile<span class="br0">&#40;</span><span class="kw2">self</span>, filename<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;[+] Analyzing file %s&quot;</span> % filename<br />
&nbsp; &nbsp; &nbsp; &nbsp; pyew = CPyew<span class="br0">&#40;</span>batch=<span class="kw2">True</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; pyew.<span class="me1">deepcodeanalysis</span> = <span class="kw2">self</span>.<span class="me1">deep</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; pyew.<span class="me1">analysis_timeout</span> = <span class="nu0">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; pyew.<span class="me1">loadFile</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> pyew.<span class="me1">format</span> <span class="kw1">in</span> <span class="br0">&#91;</span><span class="st0">&quot;PE&quot;</span>, <span class="st0">&quot;ELF&quot;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">hash</span> = sha256<span class="br0">&#40;</span>pyew.<span class="me1">getBuffer</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">hexdigest</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">data</span>.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#123;</span><span class="kw2">hash</span>:pyew<span class="br0">&#125;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Not a PE/ELF file&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> compareExpert<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; cluster = CExpertCluster<span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">data</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; val = cluster.<span class="me1">cluster</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> val == <span class="nu0">0</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Expert system: Programs are 100% equals&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Expert system: Programs differs in %f%s&quot;</span> % <span class="br0">&#40;</span><span class="kw2">round</span><span class="br0">&#40;</span>val, <span class="nu0">1</span><span class="br0">&#41;</span>, <span class="st0">&quot;%&quot;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> val</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> processFiles<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> f <span class="kw1">in</span> <span class="kw2">self</span>.<span class="me1">files</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">processFile</span><span class="br0">&#40;</span>f<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> main<span class="br0">&#40;</span>prog1, prog2<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; cluster = CGraphCluster<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">addFile</span><span class="br0">&#40;</span>prog1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">addFile</span><span class="br0">&#40;</span>prog2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">processFiles</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">compareExpert</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> usage<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Usage:&quot;</span>, <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, <span class="st0">&quot;file1 file2&quot;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span> != <span class="nu0">3</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; usage<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; main<span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>, <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Y ahora explico un poco el código. Hay 2 clases:</p>
<ol>
<li>CGraphCluster: Es la clase principal, encargada de analizar los archivos pasados con pyew y guardar sus datos en miembros de la clase.</li>
<li>CExpertCluster: Esta es la clase que se encarga realmente de comparar los 2 binarios, con el algoritmo comentado, a partir de los datos sacados con pyew.</li>
</ol>
<p><strong>Prueba</strong></p>
<p>Para hacer las pruebas voy a coger primero unos cuantos programas de ejemplo muy simples, y compilarlos con Mingw en PEs: <a href="http://pastebin.com/6wCfzEFG" target="_blank">clean.c</a>,<a href="http://pastebin.com/tMHmXr7X" target="_blank"> test.c</a>, <a href="http://pastebin.com/7wfkawMr" target="_blank">test2.c</a>, <a href="http://pastebin.com/gPDJCpha" target="_blank">test3.c</a>,<a href="http://pastebin.com/Vinc0jz0" target="_blank"> test4.c</a> y <a href="http://pastebin.com/qDAhxPhs" target="_blank">test5.c</a>. Y ahora vamos a ver que tal se porta este sistema de comparaciones:</p>
<pre>$ graph_test1.py clean.exe test.exe
[+] Analyzing file clean.exe
[+] Analyzing file test.exe
Expert system: Programs differs in 0.100000%
$ graph_test1.py clean.exe test2.exe
[+] Analyzing file clean.exe
[+] Analyzing file test2.exe
Expert system: Programs differs in 0.900000%
$ graph_test1.py clean.exe test3.exe
[+] Analyzing file clean.exe
[+] Analyzing file test3.exe
Expert system: Programs differs in 0.900000%
$ graph_test1.py clean.exe test4.exe
[+] Analyzing file clean.exe
[+] Analyzing file test4.exe
Expert system: Programs differs in 1.000000%
$ graph_test1.py clean.exe test5.exe
[+] Analyzing file clean.exe
[+] Analyzing file test5.exe
Expert system: Programs differs in 1.000000%
</pre>
<p>Como se puede ver, parece que el sistema funciona medianamente bien con los programas de ejemplo. El siguiente paso es probarlo con malware. Para ese ejemplo he probado con los archivos siguientes:</p>
<pre>e1acaf0572d7430106bd813df6640c2e  HGWC.ex_
73be87d0dbcc5ee9863143022ea62f51  BypassXtrap.ex_
</pre>
<p>Si probamos a comparar esto archivos con, por ejemplo, ssdeep, veremos que nos dice que no se parecen ni en el ano:</p>
<pre>$ ssdeep -b HGWC.ex_ BypassXtrap.ex_
ssdeep,1.0--blocksize:hash:hash,filename
12288:faWzgMg7v3qnCiMErQohh0F4CCJ8lnyC8rm2NY:CaHMv6CorjqnyC8rm2NY,"HGWC.ex_"
49152:C1vqjdC8rRDMIEQAePhBi70tIZDMIEQAevrv5GZS/ZoE71LGc2eC6JI/Cfnc:C1vqj9fAxYmlfACr5GZAVETeDI/Cvc,"BypassXtrap.ex_"
</pre>
<p>Sin embargo, si hacemos la prueba con este script:</p>
<pre>$ graph_test1.py HGWC.ex_ BypassXtrap.ex_
[+] Analyzing file HGWC.ex_
[+] Analyzing file BypassXtrap.ex_
Expert system: Programs are 100% equals
</pre>
<p>Un análisis un poco más en profundidad de los bitxos y tal muestra que ambos están empacados con AutoIt.</p>
<p><strong>Problemas de este algoritmo</strong></p>
<p>Uno de los problemas más claros de este algoritmo es que agrupando por grafo estaríamos agrupando por el packer, si los archivos no están desempacados, como está claro. Sin embargo, a veces, también interesa agrupar por packers (por ejemplo, por packers de malware).</p>
<p>Otro de los problemas es que es relativamente fácil crear colisiones: se podrían hacer binarios que generasen el mismo hash que, por ejemplo, el notepad de Windows, de un modo no demasiado complicado (poniendo funciones que no hagan nada más que cambiar los datos estadísticos).</p>
<p>Además, hay que tener en cuenta otro problema más: Solo vale para comparar 2 archivos, no para comparar grupos de archivos. Aunque siempre se podrían utilizar los datos en que se basa este algoritmo para realizar la agrupación (como se verá en la herramienta ya finalizada).</p>
<p><strong>Algoritmo 2: Comparación con números primos y firma de funciones<br />
</strong></p>
<p>En este caso lo que se hace es coger para cada función los datos de grado de entrada, grado de salida y complejidad ciclomática (una lista [indegree, outdegree, complexity]) y considerar estos 3 datos como la firma de la función (es decir, una función con firma [1, 2, 3] en un binario se considera que es igual a otra función con esa misma firma en otro binario).</p>
<p>Además de obtenerse este conjunto para cada binario, con la complejidad ciclomática de cada función, se obtiene un número primo asociado a su valor y se multiplican todos los valores encontrados excluyendo repetidos. Es decir, si una función tiene complejidad 5, se coge el 5º primo, si la siguiente función tiene complejidad 19, se coge el 19º primo y, suponiendo que un binario solo tuviera estas 2 funciones, el hash rápido generado basado en números primos será la multiplicación del 5º primo * 19º primo. De esta multiplicación, se excluyen aquellas funciones cuya complejidad ciclomática sea 1.</p>
<p>Una vez que se tienen calculados ambos datos (los grupos de firmas de función de cada binario y el hash hecho con números primos) se compara primero el hash, si este es igual, se considera que el binario es &#8220;100% similar&#8221; (repito, que no igual) y ya no es necesario continuar haciendo nada más. En caso de que no coincida el hash, se obtiene el total de elementos de la intersección de ambos conjuntos (estamos suponiendo la comparación de 2 binarios), el total de elementos de la diferencia de conjuntos y el número máximo de elementos de conjuntos (es decir, el mayor del total de elementos del conjunto 1 y conjunto 2). Y, finalmente, con estos datos se procede al cálculo de la diferencia entre ambos binarios.</p>
<p><strong>Menuda mierda de explicación</strong></p>
<p>Ya, no se entiende una oxtia, intentaré explicarme mejor respondiendo a las preguntas típicas acerca de este algoritmo:</p>
<ol>
<li>¿Para qué generas un valor con números primos si luego, en caso de que no coincidan, realizas unas operaciones donde nada tienen que ver los números primos? El valor obtenido multiplicando los números primos se utiliza para hacer una comprobación rápida de 2 o más archivos, es decir, si estoy comparando 100 archivos a la vez, mirar si el valor obtenido es igual es más rápido que comprobar la intersección y diferencia de conjuntos.</li>
<li>¿Cómo se aplica esto para varios archivos? Hoy por hoy, lo hago comparando cada archivo con todos los demás. Es decir, si tengo 100 archivos, haré 100*100 comparaciones.</li>
</ol>
<p><strong>Prueba</strong></p>
<p>Para probar este algoritmo, agregamos el siguiente código al archivo graph_test1.py anterior:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">def</span> primes<span class="br0">&#40;</span>n<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">if</span> n==<span class="nu0">2</span>: <span class="kw1">return</span> <span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; <span class="kw1">elif</span> n&lt;<span class="nu0">2</span>: <span class="kw1">return</span> <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; s=<span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">3</span>,n<span class="nu0">+1</span>,<span class="nu0">2</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; mroot = n ** <span class="nu0">0.5</span><br />
&nbsp; &nbsp; half=<span class="br0">&#40;</span>n<span class="nu0">+1</span><span class="br0">&#41;</span>/<span class="nu0">2</span><span class="nu0">-1</span><br />
&nbsp; &nbsp; i=<span class="nu0">0</span><br />
&nbsp; &nbsp; m=<span class="nu0">3</span><br />
&nbsp; &nbsp; <span class="kw1">while</span> m &lt;= mroot:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> s<span class="br0">&#91;</span>i<span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j=<span class="br0">&#40;</span>m*m<span class="nu0">-3</span><span class="br0">&#41;</span>/<span class="nu0">2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s<span class="br0">&#91;</span>j<span class="br0">&#93;</span>=<span class="nu0">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> j&lt;half:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s<span class="br0">&#91;</span>j<span class="br0">&#93;</span>=<span class="nu0">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j+=m<br />
&nbsp; &nbsp; &nbsp; &nbsp; i=i<span class="nu0">+1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m=<span class="nu0">2</span>*i<span class="nu0">+3</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>+<span class="br0">&#91;</span>x <span class="kw1">for</span> x <span class="kw1">in</span> s <span class="kw1">if</span> x<span class="br0">&#93;</span></p>
<p><span class="kw1">class</span> CPrimesCluster<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, data<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">primes</span> = primes<span class="br0">&#40;</span><span class="nu0">1024</span>*<span class="nu0">1024</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">data</span> = data</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> generateHash<span class="br0">&#40;</span><span class="kw2">self</span>, pyew<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; val = <span class="nu0">1</span>.<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="me1">dones</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; primes_done = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> f <span class="kw1">in</span> pyew.<span class="me1">functions</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nodes, edges, cc = pyew.<span class="me1">function_stats</span><span class="br0">&#91;</span>f<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> cc &gt; <span class="nu0">1</span> <span class="kw1">and</span> <span class="br0">&#40;</span>nodes, edges, cc<span class="br0">&#41;</span> <span class="kw1">not</span> <span class="kw1">in</span> dones:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = <span class="kw2">self</span>.<span class="me1">primes</span><span class="br0">&#91;</span>cc<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> p <span class="kw1">not</span> <span class="kw1">in</span> primes_done:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val *= p<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; primes_done.<span class="me1">append</span><span class="br0">&#40;</span>p<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dones.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#40;</span>nodes, edges, cc<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> val, dones</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> compareManySets<span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw3">sets</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; files = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; primes = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; values = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;File1;File2;Difference&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> s <span class="kw1">in</span> <span class="kw3">sets</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pyew = s.<span class="me1">values</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val, prime = <span class="kw2">self</span>.<span class="me1">generateHash</span><span class="br0">&#40;</span>pyew<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">hash</span> = sha256<span class="br0">&#40;</span>pyew.<span class="me1">getBuffer</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">hexdigest</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; primes<span class="br0">&#91;</span><span class="kw2">hash</span><span class="br0">&#93;</span> = prime<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; values<span class="br0">&#91;</span><span class="kw2">hash</span><span class="br0">&#93;</span> = val<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; files<span class="br0">&#91;</span><span class="kw2">hash</span><span class="br0">&#93;</span> = pyew.<span class="me1">filename</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">del</span> pyew</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; dones = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; size = <span class="kw2">len</span><span class="br0">&#40;</span>primes<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> h1 <span class="kw1">in</span> values:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> h2 <span class="kw1">in</span> values:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> h1 == h2 <span class="kw1">or</span> <span class="br0">&#40;</span>h1, h2<span class="br0">&#41;</span> <span class="kw1">in</span> dones <span class="kw1">or</span> <span class="br0">&#40;</span>h2, h1<span class="br0">&#41;</span> <span class="kw1">in</span> dones:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">continue</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> values<span class="br0">&#91;</span>h1<span class="br0">&#93;</span> == values<span class="br0">&#91;</span>h2<span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;%s;%s;0&quot;</span> % <span class="br0">&#40;</span>files<span class="br0">&#91;</span>h1<span class="br0">&#93;</span>, files<span class="br0">&#91;</span>h2<span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dones.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#40;</span>h1, h2<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dones.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#40;</span>h2, h1<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dones.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#40;</span>h1, h2<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dones.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#40;</span>h2, h1<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s1 = <span class="kw2">set</span><span class="br0">&#40;</span>primes<span class="br0">&#91;</span>h1<span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s2 = <span class="kw2">set</span><span class="br0">&#40;</span>primes<span class="br0">&#91;</span>h2<span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; diff = <span class="kw2">self</span>.<span class="me1">getSimilarity</span><span class="br0">&#40;</span>s1, s2<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;%s;%s;%f&quot;</span> % <span class="br0">&#40;</span>files<span class="br0">&#91;</span>h1<span class="br0">&#93;</span>, files<span class="br0">&#91;</span>h2<span class="br0">&#93;</span>, diff<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> getSimilarity<span class="br0">&#40;</span><span class="kw2">self</span>, s1, s2<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; m = <span class="kw2">max</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>s1<span class="br0">&#41;</span>, <span class="kw2">len</span><span class="br0">&#40;</span>s2<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; diff1 = <span class="kw2">len</span><span class="br0">&#40;</span>s1.<span class="me1">difference</span><span class="br0">&#40;</span>s2<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; diff2 = <span class="kw2">len</span><span class="br0">&#40;</span>s2.<span class="me1">difference</span><span class="br0">&#40;</span>s1<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; diff = <span class="br0">&#40;</span>diff1 + diff2<span class="br0">&#41;</span>*<span class="nu0">100</span>./m</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; simil1 = <span class="kw2">len</span><span class="br0">&#40;</span>s1.<span class="me1">intersection</span><span class="br0">&#40;</span>s2<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; simil = simil1*<span class="nu0">100</span>. / m</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; metric = simil + diff<br />
&nbsp; &nbsp; &nbsp; &nbsp; diff = diff * <span class="nu0">100</span>. / metric</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> diff</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> compareTwoSets<span class="br0">&#40;</span><span class="kw2">self</span>, set1, set2<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; pyew1 = set1.<span class="me1">values</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; val1, primes1 = <span class="kw2">self</span>.<span class="me1">generateHash</span><span class="br0">&#40;</span>pyew1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; pyew2 = set2.<span class="me1">values</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; val2, primes2 = <span class="kw2">self</span>.<span class="me1">generateHash</span><span class="br0">&#40;</span>pyew2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; s1 = <span class="kw2">set</span><span class="br0">&#40;</span>primes1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; s2 = <span class="kw2">set</span><span class="br0">&#40;</span>primes2<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> val1 == val2:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; diff = <span class="kw2">self</span>.<span class="me1">getSimilarity</span><span class="br0">&#40;</span>s1, s2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> diff</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> cluster<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">data</span><span class="br0">&#41;</span> == <span class="nu0">2</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set1 = <span class="kw2">self</span>.<span class="me1">data</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set2 = <span class="kw2">self</span>.<span class="me1">data</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">compareTwoSets</span><span class="br0">&#40;</span>set1, set2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">compareManySets</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">data</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Luego en la clase CGraphCluster agregamos el siguiente método:</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp; &nbsp;<span class="kw1">def</span> comparePrimes<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; cluster = CPrimesCluster<span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">data</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; val = cluster.<span class="me1">cluster</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> val == <span class="nu0">0</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Primes system: Programs are 100% equals&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Primes system: Programs differs in&quot;</span>, val, <span class="st0">&quot;% percent&quot;</span><br />
&nbsp;</div>
<p>Y, finalmente, cambiamos la función main para que quede como sigue:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">def</span> main<span class="br0">&#40;</span>prog1, prog2<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; cluster = CGraphCluster<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">addFile</span><span class="br0">&#40;</span>prog1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">addFile</span><span class="br0">&#40;</span>prog2<span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">processFiles</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">compareExpert</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; cluster.<span class="me1">comparePrimes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Una vez hechos los cambios empezamos a probar el algoritmo con los mismos ejemplos anteriores (los programitas tontos de antes y los 2 ejemplos de malware). Los resultados son los siguientes:</p>
<pre>$ graph_test1.py clean.exe test.exe
[+] Analyzing file clean.exe
[+] Analyzing file test.exe
Expert system: Programs differs in 0.100000%
Primes system: Programs differs in 14.2857142857 % percent
$ graph_test1.py clean.exe test2.exe
[+] Analyzing file clean.exe
[+] Analyzing file test2.exe
Expert system: Programs differs in 0.900000%
Primes system: Programs differs in 25.0 % percent
$ graph_test1.py clean.exe test3.exe
[+] Analyzing file clean.exe
[+] Analyzing file test3.exe
Expert system: Programs differs in 0.900000%
Primes system: Programs differs in 25.0 % percent
$ graph_test1.py clean.exe test4.exe
[+] Analyzing file clean.exe
[+] Analyzing file test4.exe
Expert system: Programs differs in 1.000000%
Primes system: Programs differs in 37.5 % percent
$ graph_test1.py clean.exe test5.exe
[+] Analyzing file clean.exe
[+] Analyzing file test5.exe
Expert system: Programs differs in 1.000000%
Primes system: Programs differs in 25.0 % percent
$ graph_test1.py HGWC.ex_ BypassXtrap.ex_
[+] Analyzing file HGWC.ex_
[+] Analyzing file BypassXtrap.ex_
Expert system: Programs are 100% equals
Prime: Programs are 100% equals
</pre>
<p>Como se puede ver este sistema &#8216;funciona&#8217;, aunque da porcentajes muy diferentes con los ejemplos de prueba anteriores. Con los 2 bitxos empacados con AutoIt, sin embargo, nos sigue diciendo que son exactamente iguales.</p>
<p><strong>Problemas</strong></p>
<p>Los problemas de este algoritmo son exactamente los mismos que en el caso anterior: Agrupa por packer y se podría (aunque con este algoritmo se hace más complicado) hacer un programa que tuviera la misma firma que un notepad y diferente comportamiento (un malware, por ejemplo).</p>
<p><strong>Herramienta final<br />
</strong></p>
<p>El script ya finalizado con algunas cositas más lo podéis descargar <a href="http://code.google.com/p/pyew/source/browse/gcluster.py" target="_blank">aquí</a> (requiere Pyew, acordaros). Las modificaciones que tiene este script son para utilizarlo con baterías de archivos. Puede recibir 2 parámetros, siendo 2 programas (ELF o PE) a comparar o un directorio. En caso de ser un directorio, se analizan todos los archivos de ese directorio y sus subdirectorios y se imprime, con formato CSV, la lista de archivos, hashes y todos los datos obtenidos de las funciones.</p>
<p><strong>Uso de la herramienta con baterías</strong></p>
<p>El archivo CSV generado se puede utilizar con GNumeric, LibreOffice/OpenOffice o MS Office para ver que grupos existen (o importarlo a una base de datos). Voy a mostrar una prueba con una batería de 28 malwares (detectados por varios AVs como TDSS.Z, aunque realmente hay un poco de todo). Los siguientes son los resultados con la herramienta ssdeep:</p>
<p><a href="http://blog.48bits.com/wp-content/uploads/2011/01/ssdeep.png"><img class="aligncenter size-medium wp-image-1727" title="ssdeep" src="http://blog.48bits.com/wp-content/uploads/2011/01/ssdeep-300x121.png" alt="" width="300" height="121" /></a></p>
<p>En esta imagen se puede ver que la herramienta, por fuzzy hashing, solo encuentra 2 archivos similares. En la siguiente imagen se muestran los resultados con <a href="http://deeptoad.googlecode.com" target="_blank">deeptoad</a>:</p>
<p><a href="http://blog.48bits.com/wp-content/uploads/2011/01/deeptoad.png"><img class="aligncenter size-medium wp-image-1730" title="deeptoad" src="http://blog.48bits.com/wp-content/uploads/2011/01/deeptoad-300x109.png" alt="" width="300" height="109" /></a></p>
<p>Vemos que esta herramienta consigue encontrar alguna similitud más agrupando 4 archivos. Ahora hagamos la prueba con los datos que genera la herramienta de comparación por grafos:</p>
<p><a href="http://blog.48bits.com/wp-content/uploads/2011/01/gcluster.png"><img class="aligncenter size-medium wp-image-1731" title="gcluster" src="http://blog.48bits.com/wp-content/uploads/2011/01/gcluster-300x118.png" alt="" width="300" height="118" /></a></p>
<p>Y en este caso vemos que se crea un grupo más grande. Si comparamos los 10 archivos que ha agrupado veremos que en la mayoría de casos nos dirá que son 100% similares y, en otros, que las diferencias entre ellos son mínimas, como por ejemplo con los 2 primeros archivos que se ven en la imagen:</p>
<pre>$ gcluster.py d8e8001a175e777ff4d56a6a7b9d32f37178cc24010d4e4d0e8e4027ac69c54d 28a847f4010f95fd3302816559b8cc4be433445aad26b04ff3d688e42ae5b0a1
Expert system: Programs differs in 0.100000%
Primes system: Programs differs in 16.8421052632 % percent
</pre>
<p><strong>Notas finales</strong></p>
<p>De momento lo dejo aquí porque el post ya es bastante grande. Seguramente vuelva a postear algo más acerca de grafos en el futuro pero, de momento, aquí se acaba. Espero que os haya gustado este totxazo de post y que os pueda valer para algo.</p>
<p>Muchas gracias a toda la peña de 48bits por su ayuda y especialmente a Marconi por haberme ayudado con correcciones a los algoritmos y con el post.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2011/01/23/comparacion-de-binarios-por-grafo/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Jugando con Samepage Merging</title>
		<link>http://blog.48bits.com/2010/03/17/jugando-con-samepage-merging/</link>
		<comments>http://blog.48bits.com/2010/03/17/jugando-con-samepage-merging/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 22:47:44 +0000</pubDate>
		<dc:creator>erg0t</dc:creator>
				<category><![CDATA[Ingeniería inversa]]></category>
		<category><![CDATA[Malware Analysis]]></category>
		<category><![CDATA[Noticias]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=1250</guid>
		<description><![CDATA[ACTUALIZACIÓN: 1/5/2010 Incluyo un pequeño cambio en el codigo del PoC que había hecho el cual mejora muchisimo los resultados, lamentablemente no tengo tiempo de rehacer las graficas y las conclusiones. Pruebenlo que ahora los resultados son mucho mas notables Hola audiencia de 48bits, hoy les voy a contar un poco sobre una cualidad que [...]]]></description>
			<content:encoded><![CDATA[<p style="padding-left: 30px; text-align: center;"><span style="color: #ff0000;"><em><strong>ACTUALIZACIÓN:</strong> 1/5/2010 Incluyo un pequeño cambio en el codigo del PoC que había hecho el cual mejora muchisimo los resultados, lamentablemente no tengo tiempo de rehacer las graficas y las conclusiones. Pruebenlo que ahora los resultados son mucho mas notables <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </em></span></p>
<p>Hola audiencia de 48bits, hoy les voy a contar un poco sobre una cualidad que tienen ciertos entornos de virtualizacion, la cual podemos aprovechar para detectar los mismos.</p>
<p>El método que propongo esta basado en timing analysis, pero no sobre el tiempo de ejecución de determinadas instrucciones, sino que sobre los tiempos de acceso a memoria. Se han utilizado técnicas similares para detectar VMMs (incluyendo VT). Un método conocido es medir el tiempo de acceso a memoria con cache on/off, por lo general el VMM no permite desactivar el cache, entonces si ambas mediciones dan resultados similares significa que estamos dentro de un entorno virtual.</p>
<p>A diferencia de esa técnica, la manera que he encontrado no requiere ring0 y además es bastante sencilla. Claro que tiene ciertas limitaciones, no sirve para detectar cualquier VM, solo aquellas que implementen samepage merging (hasta ahora solo hice pruebas con KVM-KSM y VMware).<br />
<span id="more-1250"></span><br />
Supongo que tendré que explicar un poco en que consiste esto del samepage merging (desde ahora SM porque soy vago). El SM esta muy relacionado con el CoW (Copy on Write). Básicamente se trata de un thread que periódicamente recorre la memoria y une todas las páginas cuyo contenido es exactamente el mismo. Una vez unidas las páginas, el resto del proceso es exactamente un CoW, se comparte la misma page frame y se marca la página como read-only, cuando se intenta realizar una escritura, el manejador de excepciones se encarga de asignar una nueva página.</p>
<p>Este tipo de estrategia es bastante costosa por lo que no se suele utilizar sobre toda la memoria del sistema operativo. Sin embargo es muy tentador utilizarla en entornos  virtualizados ya que se ahorran cantidades considerables de ram, el beneficio es máximo cuando se corren varios guests simultanea-mente.</p>
<p>En linux disponemos de KSM (Kernel Samepage Merging), este se puede activar y desactivar en el vuelo. Cualquier versión reciente de KVM saca provecho de KSM si se encuentra activado. La idea original sobre este tipo de tecnologías parece pertenecer a <a href="http://www.google.com/patents?vid=USPAT6789156">VMware</a> y al parecer hubo ciertos problemas de patentes con KSM, lo importante a destacar es que si podemos aprovecharnos de KSM seguramente también podemos hacerlo de VMware.</p>
<p>Ya con todo esto un poco explicado, algunos deben estarse preguntando que pasaría si medimos los tiempos de acceso a memoria antes y después de que el KSM (o VMware) actue sobre la memoria del guest. Es justamente lo que vamos a averiguar <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><span style="text-decoration: line-through;">Para logralo he escrito un PoC bastante cutre pero útil a nuestros propósitos. A continuación, el código (que no es muy bonito que digamos), y le sigue su descripción.</span></p>
<p><strong><span style="color: #ff0000;">Nuevo PoC!</span></strong></p>
<div class="dean_ch" style="white-space: wrap;"><span class="coMULTI">/*<br />
&nbsp;* smdetect.cpp<br />
&nbsp;*<br />
&nbsp;* Created by Daniel Fernandez (<span class="mh-email">soyf<a href='http://www.google.com/recaptcha/mailhide/d?k=018C3PkzWHAYgYz895QBbhcA==&amp;c=lFF3h9zRWUVhNd5kW--LV7y-IWS6WL2Q1P5cpE_Q4Gw=' onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k=018C3PkzWHAYgYz895QBbhcA==&amp;c=lFF3h9zRWUVhNd5kW--LV7y-IWS6WL2Q1P5cpE_Q4Gw=', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;" title="Reveal this e-mail address">...</a>@48bits.com</span>) on 19/03/2010<br />
&nbsp;*<br />
&nbsp;* Copyright (c) 2010 &nbsp;48BITS<br />
&nbsp;* All rights reserved.<br />
&nbsp;*<br />
&nbsp;* Redistribution and use in source and binary forms, with or without<br />
&nbsp;* modification, are permitted provided that the following conditions<br />
&nbsp;* are met:<br />
&nbsp;*<br />
&nbsp;* Redistributions of source code must retain the above copyright notice,<br />
&nbsp;* this list of conditions and the following disclaimer.<br />
&nbsp;*<br />
&nbsp;* Redistributions in binary form must reproduce the above copyright<br />
&nbsp;* notice, this list of conditions and the following disclaimer in the<br />
&nbsp;* documentation and/or other materials provided with the distribution.<br />
&nbsp;*<br />
&nbsp;* Neither the name of the project&#8217;s author nor the names of its<br />
&nbsp;* contributors may be used to endorse or promote products derived from<br />
&nbsp;* this software without specific prior written permission.<br />
&nbsp;*<br />
&nbsp;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS<br />
&nbsp;* &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT<br />
&nbsp;* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS<br />
&nbsp;* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT<br />
&nbsp;* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,<br />
&nbsp;* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED<br />
&nbsp;* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR<br />
&nbsp;* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF<br />
&nbsp;* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING<br />
&nbsp;* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS<br />
&nbsp;* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<br />
&nbsp;*<br />
&nbsp;*/</span></p>
<p><span class="co2">#include &lt;iostream&gt;</span><br />
<span class="co2">#include &lt;cstdlib&gt;</span><br />
<span class="co2">#include &lt;sys/time.h&gt;</span><br />
<span class="co2">#include &lt;unistd.h&gt;</span></p>
<p><span class="co2">#ifdef _WIN32</span><br />
<span class="co2">#include &lt;windows.h&gt;</span><br />
<span class="co2">#else</span><br />
<span class="co2">#include &lt;sys/mman.h&gt;</span><br />
<span class="co2">#endif</span></p>
<p>class Buffer<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> *buffer;<br />
&nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">int</span> size;</p>
<p>&nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">long</span> gettime<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">struct</span> timeval tv;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; gettimeofday<span class="br0">&#40;</span>&amp;tv, <span class="kw2">NULL</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">long</span><span class="br0">&#41;</span> tv.<span class="me1">tv_sec</span><span class="br0">&#41;</span> * 1000000ULL +<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">long</span><span class="br0">&#41;</span> tv.<span class="me1">tv_usec</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>public:</p>
<p>&nbsp; &nbsp; <span class="kw2">enum</span> Exceptions<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ALLOC_FAILED,<br />
&nbsp; &nbsp; &nbsp; &nbsp; LOCK_FAILED,<br />
&nbsp; &nbsp; <span class="br0">&#125;</span>;</p>
<p>&nbsp; &nbsp; Buffer<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> sz, bool locking, <span class="kw4">unsigned</span> <span class="kw4">int</span> seconds<span class="br0">&#41;</span> : size<span class="br0">&#40;</span>sz<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
<span class="co2">#ifdef _WIN32</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; HANDLE hProcess<span class="br0">&#40;</span>GetCurrentProcess<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SIZE_T minws, maxws;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; buffer = <span class="br0">&#40;</span><span class="kw4">int</span> *<span class="br0">&#41;</span> VirtualAlloc<span class="br0">&#40;</span><span class="kw2">NULL</span>, size, MEM_COMMIT, PAGE_READWRITE<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>buffer == <span class="kw2">NULL</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw ALLOC_FAILED;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>locking == <span class="kw2">true</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GetProcessWorkingSetSize<span class="br0">&#40;</span>hProcess, &amp;minws, &amp;maxws<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetProcessWorkingSetSize<span class="br0">&#40;</span>hProcess, minws + size, maxws + size<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>VirtualLock<span class="br0">&#40;</span>buffer, size<span class="br0">&#41;</span> == <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw LOCK_FAILED;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="co2">#else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; buffer = <span class="br0">&#40;</span><span class="kw4">int</span> *<span class="br0">&#41;</span> mmap<span class="br0">&#40;</span><span class="kw2">NULL</span>, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MAP_ANONYMOUS, <span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>buffer == MAP_FAILED<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw ALLOC_FAILED;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>locking == <span class="kw2">true</span> &amp;&amp; mlock<span class="br0">&#40;</span>buffer, size<span class="br0">&#41;</span> == <span class="nu0">-1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw LOCK_FAILED;<br />
<span class="co2">#endif</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> x<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>; x != size/<span class="kw4">sizeof</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>; ++x<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buffer<span class="br0">&#91;</span>x<span class="br0">&#93;</span> = 0x443d3d38;<br />
<span class="co2">#ifdef _WIN32</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Sleep<span class="br0">&#40;</span>seconds * <span class="nu0">1000</span><span class="br0">&#41;</span>;<br />
<span class="co2">#else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sleep<span class="br0">&#40;</span>seconds<span class="br0">&#41;</span>;<br />
<span class="co2">#endif</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; ~Buffer<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
<span class="co2">#ifdef _WIN32</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; VirtualUnlock<span class="br0">&#40;</span>buffer, size<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; VirtualFree<span class="br0">&#40;</span>buffer, <span class="nu0">0</span>, MEM_RELEASE<span class="br0">&#41;</span>;<br />
<span class="co2">#else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; munmap<span class="br0">&#40;</span>buffer, size<span class="br0">&#41;</span>;<br />
<span class="co2">#endif</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">long</span> measureWrite<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">long</span> start<span class="br0">&#40;</span>gettime<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> x<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>; x != size/<span class="kw4">sizeof</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>; x += <span class="nu0">4096</span>/<span class="kw4">sizeof</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buffer<span class="br0">&#91;</span>x<span class="br0">&#93;</span> = x;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> gettime<span class="br0">&#40;</span><span class="br0">&#41;</span> &#8211; start;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">long</span> getTime<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> bsize, bool locking,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw4">unsigned</span> <span class="kw4">int</span> sleep_seconds = <span class="nu0">0</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Buffer buf<span class="br0">&#40;</span>bsize, locking, sleep_seconds<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">return</span> buf.<span class="me1">measureWrite</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> main<span class="br0">&#40;</span><span class="kw4">int</span> argc, <span class="kw4">char</span> *argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">int</span> buffer_size<span class="br0">&#40;</span><span class="nu0">15</span>*<span class="nu0">1024</span>*<span class="nu0">4096</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">int</span> sleep_time<span class="br0">&#40;</span><span class="nu0">60</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">int</span> threshold<span class="br0">&#40;</span><span class="nu0">500</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; bool locking<span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">char</span> c;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>c = getopt<span class="br0">&#40;</span>argc, argv, <span class="st0">&quot;pm:s:t:&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> != <span class="nu0">-1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;p&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locking = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;m&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buffer_size = <span class="br0">&#40;</span>atoi<span class="br0">&#40;</span>optarg<span class="br0">&#41;</span> * <span class="nu0">1024</span> * <span class="nu0">1024</span><span class="br0">&#41;</span> &amp; ~<span class="nu0">4095</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;s&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sleep_time = atoi<span class="br0">&#40;</span>optarg<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;t&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; threshold = atoi<span class="br0">&#40;</span>optarg<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;?&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::<a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span class="kw3">cout</span></a> &lt;&lt; <span class="st0">&quot;<span class="es0">\n</span>Options:<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; <span class="st0">&quot;-m size<span class="es0">\t</span> buffer size in Mb (default 60mb)<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; <span class="st0">&quot;-s time<span class="es0">\t</span> sleep time in second (default 60secs)<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; <span class="st0">&quot;-t num<span class="es0">\t</span> threshold (default 98)<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; <span class="st0">&quot;-p<span class="es0">\t</span> disable locking (default enabled)&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">-1</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; try<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">long</span> t1<span class="br0">&#40;</span>getTime<span class="br0">&#40;</span>buffer_size, locking<span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">long</span> t2<span class="br0">&#40;</span>getTime<span class="br0">&#40;</span>buffer_size, locking, sleep_time<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// avoid division by zero</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>t1 == <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1 = <span class="nu0">1</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> variation<span class="br0">&#40;</span><span class="br0">&#40;</span>std::<span class="me2">abs</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">long</span> <span class="kw4">long</span><span class="br0">&#41;</span><span class="br0">&#40;</span>t2 &#8211; t1<span class="br0">&#41;</span><span class="br0">&#41;</span>*<span class="nu0">100</span><span class="br0">&#41;</span>/t1<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; std::<a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span class="kw3">cout</span></a> &lt;&lt; <span class="st0">&quot;First write: &nbsp;&quot;</span> &lt;&lt; t1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; <span class="st0">&quot;<span class="es0">\n</span>Second write: &quot;</span> &lt;&lt; t2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; <span class="st0">&quot;<span class="es0">\n</span>Variation: &nbsp; &nbsp;&quot;</span> &lt;&lt; variation &lt;&lt; <span class="st0">&quot;%<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; <span class="br0">&#40;</span>variation &gt;= threshold ? <span class="st0">&quot;VMM detected!&quot;</span> : <span class="st0">&quot;no VMM detected&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; catch <span class="br0">&#40;</span>Buffer::<span class="me2">Exceptions</span> e<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e == Buffer::<span class="me2">ALLOC_FAILED</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::<a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span class="kw3">cout</span></a> &lt;&lt; <span class="st0">&quot;Can&#8217;t alloc buffer, try with a smaller size (-m)<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Or check your capabilities&quot;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e == Buffer::<span class="me2">LOCK_FAILED</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::<a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span class="kw3">cout</span></a> &lt;&lt; <span class="st0">&quot;Can&#8217;t lock buffer, check your capabilities<span class="es0">\n</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Or use -p flag&quot;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p><span style="text-decoration: line-through;">El código puede ser compilado con visual studio, y lo ideal es compilarlo para release.</span><br />
<strong> </strong></p>
<p><em>Ahora se compila con: <strong>g++ -O3 smdetect.cpp -o smdetect<br />
</strong>Funciona tanto en linux como en windows (mingw).</em></p>
<p>Ahora unas gráficas con los resultados en distintos entornos:</p>
<p><a href="http://blog.48bits.com/wp-content/uploads/2010/03/smdetect.png"><img src="http://blog.48bits.com/wp-content/uploads/2010/03/smdetect.png" alt="" title="smdetect" width="490" height="340" class="aligncenter size-full wp-image-1265" /></a></p>
<p>Las gráficas corresponden a 10 ejecuciones de smdetect por cada entorno. Si todo fuera perfecto deberían ser lineas horizontales, pero factores externos como la carga del sistema hacen variar bastante los resultados.</p>
<p>Se puede apreciar una diferencia notable entre los casos donde no hay VMM y en los que la hay. Un caso curioso se da con OSX, donde la diferencia es apenas un 100% estando más cerca de los resultados donde no hay VMM. Incluso en una prueba llego a dar ~30% lo cual lo hace un target muy dificil de detectar.</p>
<p>Mirando las gráficas y sin considerar OSX, podriamos establecer un umbral de 150% para la detección. Incluyendo los datos de OSX he decidido utilizar un 98%, aún asi pueden darse falsos negativos en OSX y un umbral tan bajo podría llegar a dar falsos positivos si se dan ciertas condiciones.</p>
<p>Conclushion!</p>
<p>Tenemos un nuevo método, que si bien no es 100% confiable, puede ser utilizado de forma práctica y es posible refinarlo mucho más. Una posibilidad es la utilización de heurísticas para ajustar el umbral en función a información sobre la carga del sistema. Otro tema pendiente es la enorme espera que hay que realizar entre mediciones, pero esto no creo que sea un impedimento para muchos autores de malware&#8230;</p>
<p>Aqui se acaba <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>PD: lo siento Javi y Marconi por meter otro post en tan poco tiempo (parece ser que siempre ocurre lo mismo, pueden pasar meses sin movimiento y luego abalancha de posts).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2010/03/17/jugando-con-samepage-merging/feed/</wfw:commentRss>
		<slash:comments>84</slash:comments>
		</item>
		<item>
		<title>El caso del patch-downloader</title>
		<link>http://blog.48bits.com/2006/07/08/el-caso-del-patch-downloader/</link>
		<comments>http://blog.48bits.com/2006/07/08/el-caso-del-patch-downloader/#comments</comments>
		<pubDate>Sat, 08 Jul 2006 19:27:30 +0000</pubDate>
		<dc:creator>Mario Ballano</dc:creator>
				<category><![CDATA[Malware Analysis]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=44</guid>
		<description><![CDATA[En los tiempos que corren desgraciadamente no es muy dificil toparse con algun que otro esperpento creado especialmente para llenar tu pc de publicidad, casinos, robarte tus claves del messenger o vigilar tus movimientos bancarios y es que realmente hay bastante dinero en juego cuando hablamos de este tipo de malware. Con este post inauguramos [...]]]></description>
			<content:encoded><![CDATA[<p>En los tiempos que corren desgraciadamente no es muy dificil toparse con algun que otro esperpento creado especialmente para llenar tu pc de publicidad, casinos, robarte tus claves del messenger o vigilar tus movimientos bancarios y es que realmente<img align="left" alt="bender.jpg" id="image49" title="bender.jpg" src="http://blog.48bits.com/wp-content/uploads/2006/07/bender.jpg" /> hay bastante dinero en juego cuando hablamos de este tipo de malware.</p>
<p>Con este post inauguramos una nueva categoría en 48Bits dedicada al análisis de las técnicas usadas actualmente por malware, si tienes alguna &#8220;muestra&#8221; que te gustaría analizar o quieres comentar algun caso/código curioso, puedes ponerte en contacto con nosotros a través de correo electrónico, ah y si nos envias muestras que sea en un comprimido con clave <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p>El bicho que nos ocupa hoy nos llegó por correo electrónico, parece que alguien pudo &#8220;spamearlo&#8221; o vete a saber &#8230;<br />
<span id="more-44"></span></p>
<p>Se trata de un ejecutable de unos 21 KB, lo primero que llama la atención de este es que solamente importa dos funciones de librerías del sistema, se trata de GetProcAddress y LoadLibrary, normalmente esto es común en los ficheros empaquetados con algún packer, pero no es este el caso. Lo segundo que llama la atención es que no se aprecia ninguna cadena de texto en el fichero, ¿Como cargará entonces las funciones que necesite?, existen maneras de localizar las funciones recorriendo las exports de las dlls en memoria sin tener que tener estos nombres (usando hashes de ellos por ejemplo), también podría ser que tuviera todos estos nombres encriptados, lo cual es una técnica comunmente usada también, bueno despues de estas suposiciones empezamos a mirar un poco el desensamblado&#8230;<br />
<img align="middle" title="IDA1" id="image45" alt="IDA1" src="http://blog.48bits.com/wp-content/uploads/2006/07/ida1.PNG" /></p>
<p>Como podemos observar aquí (y en el resto del programa) parece que el ejecutable tiene código basura por todos los lados, esto probablemente esté como medida para evitar una detección genérica y como no para dificultar su análisis también, desconozco cómo se ha generado este tipo de junk code, de cualquier manera tampoco es que sea una &#8220;maravilla&#8221; <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Veamos un poco más como queda este &#8220;junk code&#8221; en lo que parece ser una implementación de &#8220;memzero&#8221; aunque la verdad es un poco guarra <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> &#8230;</p>
<p><img align="middle" title="IDA3" id="image47" alt="IDA3" src="http://blog.48bits.com/wp-content/uploads/2006/07/ida3.PNG" /></p>
<p>Seguimos con otro trozo de desensamblado que pertenece a la función &#8220;FunnyNames&#8221;.<br />
<img align="middle" title="IDA2" id="image46" alt="IDA2" src="http://blog.48bits.com/wp-content/uploads/2006/07/ida2.PNG" /></p>
<p>Bueno, creo que aquí queda desvelado el misterio de la no existencia de cadenas&#8230; el que ha programado esto reconstruye las cadenas de manera desordenada y byte a byte!, curioso&#8230; las cadenas están codificadas en instrucciones del propio procesador. En el ejemplo de arriba carga la librería &#8220;kernel32.dll&#8221;, cosa que por otro lado no hace falta porque ya está importando funciones de ahí <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p>Si seguimos mirando el resto del programa vemos que todas las cadenas y los nombres de las funciones que necesita usar están codificados de esta manera. Ahora bien, para enterarnos un poco mejor, con ayuda de algunos breakpoints y demás, dado que esta reconstruccion se hace en la pila del programa en tiempo de ejecución, dumpeando la memoria de la pila a disco obtenemos algo con lo que trabajar &#8230; <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><img align="middle" alt="hiew1.PNG" id="image48" title="hiew1.PNG" src="http://blog.48bits.com/wp-content/uploads/2006/07/hiew1.PNG" /></p>
<p>Bueno con un poco de paciencia y siguiendo el análisis me di cuenta de que lo que hacía este &#8220;bicho&#8221; es acceder a la siguiente URL:</p>
<p>http://207.226.177.108/BN/QgaHo26bYG</p>
<p>Si os descargaís este fichero (no teneís peligro alguno porque no es un ejecutable), observareís una maraña de datos que parecen estar comprimidos/encriptados &#8230; esto realmente es código realocalizable que el bicho inyectará en el contexto del internet explorer, para ello utiliza VirtualAllocEx y CreateRemoteThread además de establecer los privilegios necesarios para poder hacerlo, de esta manera evita firewalls que bloqueen el acceso a internet a determinados procesos, ya que internet explorer suele ser uno de los programas &#8220;permitidos&#8221;.</p>
<p>Lo interesante de todo esto es que este &#8220;parche&#8221; se actualiza cada cierto tiempo, supongo que será una nueva generación del mismo, empaquetado de manera diferente, no he analizado este componente porque ya no tenía ganas XD, de cualquier manera podrían cambiar el parche que hay ahí y actualizarlo con una versión nueva o lo que sea en cualquier momento, lo que si que he hecho ha sido sacar un dumpeado de este código una vez ejecutado en el contexto de internet explorer. Y menuda sorpresita&#8230; porque hay cosas bastante interesantes&#8230; como las siguientes URLs</p>
<pre>0000BAD0   0000BAD0      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERE180Sol.UNIQCNTR.html
0000BB56   0000BB56      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERE180sol.UNIQCNTR.html
0000BBDC   0000BBDC      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREADWARE.UNIQCNTR.html
0000BC62   0000BC62      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREAVG.UNIQCNTR.html
0000BCE2   0000BCE2      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREAdware.UNIQCNTR.html
0000BD68   0000BD68      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREAntivir.UNIQCNTR.html
0000BDF0   0000BDF0      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREBDSM.UNIQCNTR.html
0000BE72   0000BE72      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREBlackjack.UNIQCNTR.html
0000BEFE   0000BEFE      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREBlowjob.UNIQCNTR.html
0000BF86   0000BF86      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERECASINO.UNIQCNTR.html
0000C00C   0000C00C      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERECLEAN.UNIQCNTR.html
0000C090   0000C090      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERECasino.UNIQCNTR.html
0000C116   0000C116      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREClaria.UNIQCNTR.html
0000C19C   0000C19C      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREClean.UNIQCNTR.html
0000C220   0000C220      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERECumshot.UNIQCNTR.html
0000C2A8   0000C2A8      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREE-gold.UNIQCNTR.html
0000C32E   0000C32E      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREERROR.UNIQCNTR.html
0000C3B2   0000C3B2      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREEgold.UNIQCNTR.html
0000C436   0000C436      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREError.UNIQCNTR.html
0000C4BA   0000C4BA      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREGATOR.UNIQCNTR.html
0000C53E   0000C53E      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREGator.UNIQCNTR.html
0000C5C2   0000C5C2      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREHYIP.UNIQCNTR.html
0000C644   0000C644      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREHyip.UNIQCNTR.html
0000C6C6   0000C6C6      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREINVESTMENT.UNIQCNTR.html
0000C754   0000C754      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREInvestment.UNIQCNTR.html
0000C7E2   0000C7E2      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREMcAfee.UNIQCNTR.html
0000C868   0000C868      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERENAV.UNIQCNTR.html
0000C8E8   0000C8E8      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERENude.UNIQCNTR.html
0000C96A   0000C96A      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREPORN.UNIQCNTR.html
0000C9EC   0000C9EC      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREPRIVACY.UNIQCNTR.html
0000CA74   0000CA74      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREPissing.UNIQCNTR.html
0000CAFC   0000CAFC      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREPoker.UNIQCNTR.html
0000CB80   0000CB80      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREPorn.UNIQCNTR.html
0000CC02   0000CC02      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHEREPrivacy.UNIQCNTR.html
0000CC8A   0000CC8A      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERERecover.UNIQCNTR.html
0000CD12   0000CD12      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERERoulette.UNIQCNTR.html
0000CD9C   0000CD9C      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERESPYWARE.UNIQCNTR.html
0000CE24   0000CE24      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERESlots.UNIQCNTR.html
0000CEA8   0000CEA8      0   http://207.226.177.108/G0/WEBMIDHERECOMPIDHERESpybot.UNIQCNTR.html</pre>
<p>En esas URLs hay un repositorio de programas maliciosos bastante grande&#8230; cuidado con lo que ejecutaís/descargaís de ahí, he publicado estas direcciones porque este tipo de cosas deberían ser denunciadas publicamente.</p>
<p>Un saludo y hasta la próxima!</p>
<pre style="margin: 6px" class="code"></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2006/07/08/el-caso-del-patch-downloader/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>

