<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Diario de un programador</title>
	
	<link>http://blog.cuerty.com</link>
	<description>Historias, pensamientos, ideas y proyectos de un programador viviendo en Buenos Aires, Argentina.</description>
	<lastBuildDate>Wed, 16 Jun 2010 20:38:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/DiarioDeUnProgramador" /><feedburner:info uri="diariodeunprogramador" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Reverse engineer en OSX – Parte I</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/DGumCimOy1M/</link>
		<comments>http://blog.cuerty.com/2010/06/16/181/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 06:18:35 +0000</pubDate>
		<dc:creator>Fz</dc:creator>
				<category><![CDATA[Sin categoria]]></category>
		<category><![CDATA[cracking]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[reverse-engineer]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=181</guid>
		<description><![CDATA[
.entry a { color: blue; }

Como verán, quien escribe no es quién esperan que escriba. Me tomé el atrevimiento de intrometerme en el blog de mi amigo @cuerty y dejarles una serie de posts para los switchers que se compraron una mac.
I. Introducción
Voy a hacer algunas entregas de una introducción a reverse engineer en OSX, [...]]]></description>
			<content:encoded><![CDATA[<style>
.entry a { color: blue; }
</style>
<p>Como verán, quien escribe no es quién esperan que escriba. Me tomé el atrevimiento de intrometerme en el blog de mi amigo @cuerty y dejarles una serie de posts para los switchers que se compraron una mac.</p>
<h2>I. Introducción</h2>
<p>Voy a hacer algunas entregas de una introducción a reverse engineer en OSX, siempre asm x86 32-bit. Mi idea es intentar desviar un poco la atención de la teoría (Que ya fue repetida hasta el hartazgo) y hacer un enfoque mas práctico: Voy a presentar una serie de crackme&#8217;s que bajé de otro sitio y explicar qué puede hacerse.</p>
<h2>II. Requerimientos</h2>
<p>Para mas o menos entender de qué viene el asunto, es necesario:</p>
<ul>
<li>Entender la sintaxis de Objective-C</li>
<li>Conocer mas o menos los comandos básicos de gdb</li>
<li>Estar familiarizado con la sintaxis Intel de asm.</li>
</ul>
<h2>II. b. Herramientas</h2>
<ul>
<li><a href="http://developer.apple.com/technologies/xcode.html">gdb</a></li>
<li><a href="http://otx.osxninja.com/files/otx.dmg">otx</a></li>
<li><a href="http://www.codethecode.com/download/class-dump-3.3.2.dmg">class-dump</a></li>
<li>Dado que OSX usa Mach-O que puede tener muchas arquitecturas, los offsets están corridos. Para solucionar esto pueden usar <a href="http://dl.dropbox.com/u/623010/offset.py">este script que hice</a></li>
</ul>
<h2>III. Lo básico.</h2>
<p>Entender asm es fundamental para poder seguir adelante y a partir de este momento voy a asumir que esto último es un hecho.</p>
<p>Dicho esto, voy a recordar dos cosas: La primera es esta tabla de optcodes muy util (http://ref.x86asm.net/coder32.html) y la segunda la representación de los registros completos y parciales:</p>
<table style="font-family: Arial, sans-serif; font-size: small; margin-top: 2em; margin-right: 0px; margin-bottom: 2em; margin-left: 4em; border-collapse: collapse; background-color: #eee; line-height: normal; padding: 0px; border: 1px solid #000000;" border="0">
<tbody style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<th style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; text-align: center; background-color: #e0e0e0; margin: 0px; border: 1px solid #000000;">Bits 31 &#8211; 24</th>
<th style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; text-align: center; background-color: #e0e0e0; margin: 0px; border: 1px solid #000000;">Bits 23 &#8211; 16</th>
<th style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; text-align: center; background-color: #e0e0e0; margin: 0px; border: 1px solid #000000;">Bits 15 &#8211; 8</th>
<th style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; text-align: center; background-color: #e0e0e0; margin: 0px; border: 1px solid #000000;">Bits 7 &#8211; 0</th>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="4"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">eax</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">ax</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">ah</code></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">al</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="4"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">ebx</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">bx</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">bh</code></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">bl</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="4"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">ecx</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">cx</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">ch</code></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">cl</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="4"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">edx</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">dx</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">dh</code></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">dl</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="4"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">ebp</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">bp</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="4"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">esp</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">sp</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="4"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">esi</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">si</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="4"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">edi</code></td>
</tr>
<tr style="font-family: Arial, sans-serif; font-size: small; padding: 0px; margin: 0px;">
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"></td>
<td style="font-family: Arial, sans-serif; font-size: small; padding-top: 0px; padding-right: 1em; padding-bottom: 0px; padding-left: 1em; vertical-align: top; text-align: center; margin: 0px; border: 1px solid #000000;" colspan="2"><code style="font-family: 'Lucida Console', monospace; font-size: small; padding: 0px; margin: 0px;">di</code></td>
</tr>
</tbody>
</table>
<h2>III b. ¿¡ Objective-Qué !?</h2>
<p>Antes de empezar voy a hacer una brevísima introducción a la sintaxis de Objective-C.</p>
<p>Objective-C es un superset de C que provee programación orientada a objetos y conceptos de Messaging al estilo Smalltalk. Actualmente podemos compilar objective-c usando gcc.</p>
<h3>¿Cómo se vé un hello world en Objective-C?</h3>
<p>Normalmente tiene (Al igual que C) un archivo con los headers (.h) y otro con la implementación (.m), sin embargo no se parecen en nada a la sintaxis de C. Objective-C usa &#8220;interfaces&#8221; que vamos a llamar incorrectamente y para simplificarlo: &#8220;clases&#8221;.</p>
<p>Nuestro HelloWorld.h se vería:</p>
<pre class="prettyprint">@interface HelloWorld : NSObject

- (void)imprimirFrase:(NSString *)frase

@end</pre>
<p>Esto puede traducirse a: La clase HelloWorld hereda de NSObject y tiene un método imprimirFrase que devuelve void y recibe un parámetro NSString.</p>
<p>Nuestro HelloWorld.m sería:</p>
<pre class="prettyprint">#import "HelloWorld.h"

@implementation HelloWorld

- (void)imprimirFrase:(NSString *)frase
{
	NSLog(@"%@", frase);
}

@end</pre>
<p>Si quisiera llamar a esta función debería hacer:</p>
<pre class="prettyprint">HelloWorld *hola = [[HelloWorld alloc] init];
[hola imprimirFrase:@"Hola mundo!"];
[hola release];</pre>
<p>Como dije antes cuando hablamos de Objective-C no hacemos &#8220;llamadas a funciones&#8221; (A menos que sea una llamada a una función de C/C++) sino que &#8220;enviamos mensajes&#8221;. La sintaxis es esta:</p>
<p><strong>[&lt;objeto&gt; &lt;método&gt;:&lt;argumento_1&gt; &lt;nombre_argumento_2&gt;:&lt;argumento_2&gt;....];</strong></p>
<h3>¿Y cómo funciona este envío de mensajes?</h3>
<p>Lo primero que podemos ver es que los binarios están linkeados a libobjc.A.dylib. Por ahora lo único que vamos a ver de esta librería es una función que se llama &#8220;objc_msgSend&#8221;.</p>
<p>objc_msgSend es lo que el superset usa internamente para &#8220;enviar los mensajes&#8221; que vimos anteriormente. Esto es importante porque lo vamos a utilizar todo el tiempo en los análisis.</p>
<p>La función tiene esta declaración:</p>
<pre class="prettyprint">id objc_msgSend(id theReceiver, SEL theSelector, ...)</pre>
<p>Devuelve un id (&#8221;id&#8221; es un puntero a objc_class que a su vez es un struct. Quizás en el siguiente tutorial entre en detalles sobre esto) y recibe como parámetros:</p>
<ol>
<li>El objeto que recibe el mensaje</li>
<li>El método (SEL es un objc_selector, que a su vez es un (char *). SEL se utiliza en Objective-C para llamar a funciones dinámicamente en runtime).</li>
<li>Los siguientes parámetros son los argumentos del método.</li>
</ol>
<h2>IV. A los bifes, #1 Crack me.</h2>
<ul>
<li>El archivo se puede bajár de acá: <a href="http://reverse.put.as/wp-content/uploads/2010/05/SmellsGood.zip">SmellsGood</a></li>
</ul>
<p>Voy a explicar un caso muy intuitivo; que no necesita mucho análisis y parece bastante straight forward, no obstante voy a pasar siempre por los mismos pasos:</p>
<ul>
<li>Recolección de información.</li>
<li>Análisis de la información</li>
<li>Debugging</li>
<li>Cracking</li>
</ul>
<h3>Recolección de información</h3>
<p>En esta primera etapa lo que vamos a hacer es recolectar todo lo necesario para entender qué sucede en la app y qué podemos hacer.</p>
<p>Lo primero que vay a hacer es desensamblarlo[0]. Para eso voy a usar otx, esta aplicación (otool eXtended) es muy similar a otool pero con un output mucho mas prolijo, optcodes, offsets y lo que es mejor: El nombre de los métodos.</p>
<p>Entonces:</p>
<pre>$ otx SmellGood.app &gt; SmellGood.asm</pre>
<p>De esta manera tenemos en SmellGood.asm nuestra aplicación desensamblada. Ahora le toca el turno al class-dump. Lo que vamos a hacer en el siguiente paso es *intentar* hacer un dump de las definiciones de las clases usadas en SmellGood. El output debería ser similar a un .h de Objective-C con las interfaces.</p>
<pre>$ class-dump SmellGood.app &gt; SmellGood.h</pre>
<h3>Análisis de la información</h3>
<p>Lo siguiente que voy a hacer es tratar de entender qué está sucediendo.</p>
<p>En el .h podemos ver qué métodos nos interesan tanto para entender qué sucede como para empezar a poner break-points. Nuestro caso es este:</p>
<pre class="prettyprint">- (void)check:(id)arg1;
- (BOOL)checkCode:(id)arg1 forName:(id)arg2;
- (id)generateCodeForName:(id)arg1;
- (id)digest:(id)arg1;
- (id)shuffle:(id)arg1;</pre>
<p>Sin mucho análisis podemos ver que:</p>
<ul>
<li>El código depende del nombre.</li>
<li>Hay un &#8220;digest&#8221; (¿md5?, ¿sha1?)</li>
<li>Hay un shuffle</li>
</ul>
<p>Ahora hagamos un análisis mas serio desde el assembler. Lo primero que vamos a ver es el método <strong>-(BOOL)[SmellsGood_AppDelegate checkCode:forName:]</strong>:</p>
<pre class="prettyprint"> +30	00002b18	e855250000	calll	0x00005072		-[(%esp,1) componentsSeparatedByString:]
 +35	00002b1d	8b150c400000	movl	0x0000400c,%edx		count
 +41	00002b23	89542404	movl	%edx,0x04(%esp)
 +45	00002b27	890424		movl	%eax,(%esp)
 +48	00002b2a	e843250000	calll	0x00005072		-[(%esp,1) count]
 +53	00002b2f	83f805		cmpl	$0x05,%eax
 +56	00002b32	754c		jne	0x00002b80
 +58	00002b34	a110400000	movl	0x00004010,%eax		uppercaseString
 +63	00002b39	891c24		movl	%ebx,(%esp)
 +66	00002b3c	89442404	movl	%eax,0x04(%esp)
 +70	00002b40	e82d250000	calll	0x00005072		-[(%esp,1) uppercaseString]
 +75	00002b45	89c3		movl	%eax,%ebx
 +77	00002b47	8b4514		movl	0x14(%ebp),%eax
 +80	00002b4a	89442408	movl	%eax,0x08(%esp)
 +84	00002b4e	a114400000	movl	0x00004014,%eax		generateCodeForName:
 +89	00002b53	89442404	movl	%eax,0x04(%esp)
 +93	00002b57	8b4508		movl	0x08(%ebp),%eax
 +96	00002b5a	890424		movl	%eax,(%esp)
 +99	00002b5d	e810250000	calll	0x00005072		-[(%esp,1) generateCodeForName:]
+104	00002b62	891c24		movl	%ebx,(%esp)
+107	00002b65	89442408	movl	%eax,0x08(%esp)
+111	00002b69	a118400000	movl	0x00004018,%eax		isEqualToString:
+116	00002b6e	89442404	movl	%eax,0x04(%esp)
+120	00002b72	e8fb240000	calll	0x00005072		-[(%esp,1) isEqualToString:]
+125	00002b77	ba01000000	movl	$0x00000001,%edx
+130	00002b7c	84c0		testb	%al,%al
+132	00002b7e	7502		jne	0x00002b82
+134	00002b80	31d2		xorl	%edx,%edx
+136	00002b82	83c414		addl	$0x14,%esp
+139	00002b85	89d0		movl	%edx,%eax
+141	00002b87	5b		popl	%ebx
+142	00002b88	c9		leave
+143	00002b89	c3		ret</pre>
<p>Bueno, este es un caso que está clarísimo, incluso sin debuggearlo. No voy a detenerme en esta parte, ya que tiene demasiada meta-data. Lo que voy a hacer es traducir esto que vimos a un código que esté bastante cerca al que suponemos habrá sido el original:</p>
<pre class="prettyprint">-(BOOL)SmellsGood_AppDelegate checkCode:(NSString *)code forName:(NSString *)name
{
	if ([[code componentsSeparatedByString:@"-"] count] != 5) return NO;

	NSString *_code = [self generateCodeForName:[name uppercaseString]];
	if ([_code isEqualToString:code])
		return YES;
	else
		return NO;
}</pre>
<p>¿Bastante facil no?. Lo mismo podemos hacer con generateCodeForName:.</p>
<pre class="prettyprint">-(NSString *)generateCodeForName:(NSString *)name
{
	NSArray *data = [[self digest:[name dataUsingEncoding:4]] componentsSeparatedByString:@" "];
	return [[[self shuffle:data] componentsJoinedByString:@"-"] uppercaseString];
}</pre>
<p>Por cierto, ese &#8220;4&#8243; ahí es del enum NSStringEncoding, en este caso NSUTF8StringEncoding = 4,</p>
<p>Y nuevamente podríamos hacer algo similar con shuffle, pero voy a cambiar de estrategia para que sea mas divertido.</p>
<p>Veamos el asm, separé las partes que nos importan:</p>
<pre class="prettyprint">+17	00002d0e  c744240800000000	movl	$0x00000000,0x08(%esp)
...
+40	00002d25  e848230000		calll	0x00005072			-[(%esp,1) objectAtIndex:]

+48	00002d2d  c744240802000000	movl	$0x00000002,0x08(%esp)
...
+68	00002d41  e82c230000		calll	0x00005072			-[(%esp,1) objectAtIndex:]

+76	00002d49  c744240801000000	movl	$0x00000001,0x08(%esp)
...
+96	00002d5d  e810230000		calll	0x00005072			-[(%esp,1) objectAtIndex:]

+104	00002d65  c744240803000000	movl	$0x00000003,0x08(%esp)
...
+123	00002d78  e8f5220000		calll	0x00005072			-[(%esp,1) objectAtIndex:]

+131	00002d80  c744240804000000	movl	$0x00000004,0x08(%esp)
...
+150	00002d93  e8da220000		calll	0x00005072			-[(%esp,1) objectAtIndex:]</pre>
<p>Bueno, ahí está bastante claro. Si recuerdan lo que dije de objc_msgSend no es dificil entender lo que sucede: Al principio está poniendo en el esp + 0&#215;08 el número 0 (Recordemos que: esp tiene el objeto, +0&#215;04 tiene un (char *) con el método y a partir de ahí los argumentos).</p>
<p>En resumen lo que está pasando acá es:</p>
<pre class="prettyprint">[array objectAtIndex:0];
[array objectAtIndex:2];
[array objectAtIndex:1];
[array objectAtIndex:3];
[array objectAtIndex:4];</pre>
<p>Por otro lado sin mucho análisis uno puede deducir que el digest hace un <strong>sha1</strong> (De nuevo, solo mirando el nombre de los métodos).</p>
<h3>Debugging</h3>
<p>Bueno, a decir verdad ya tenemos tanta información que no necesitamos mucho debugging. Este paso lo vamos a hacer mas en profundidad en otros crackme&#8217;s. Voy a hacer solamente una comprobación. ¿Se acuerdan en el primer código que hay un if que pregunta si el codigo ingresado es el mismo al generateCodeForName: ?. Bueno, vamos a localizarlo, para que se entienda lo que sucede. Según el .asm lo tenemos acá:</p>
<pre class="prettyprint">+130	00002b7c  84c0		testb	%al,%al
+132	00002b7e  7502		jne	0x00002b82</pre>
<p>Corremos el gdb con el filename de nuestra app en el primer argumento.</p>
<pre>$ gdb SmellsGood.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1461) (Wed Dec 23 06:11:18 UTC 2009)
...</pre>
<p>Seteamos un breakpoint en checkCode:forName:</p>
<pre>gdb$ break checkCode:forName:
Breakpoint 1 at 0x2b01</pre>
<p>Corremos el programa.</p>
<pre>gdb$ run</pre>
<p>Ahora tocamos en el botón de &#8220;check&#8221;.</p>
<pre class="prettyprint">Breakpoint 1, 0x00002b01 in -[SmellsGood_AppDelegate checkCode:forName:] ()
gdb$ disas
Dump of assembler code for function -[SmellsGood_AppDelegate checkCode:forName:]:
(...)
0x00002b7c <-[SmellsGood_AppDelegate checkCode:forName:]+130>:	test   al,al
0x00002b7e <-[SmellsGood_AppDelegate checkCode:forName:]+132>:	jne    0x2b82 <-[SmellsGood_AppDelegate checkCode:forName:]+136>
(...)</pre>
<p>Bien, supongamos que queremos saber qué devuelve ese isEqualToString. (Asumamos por un segundo que sabemos que devuelve &#8220;false&#8221;&#8230; nota: Nunca asumir nada), podemos tomar muchos approaches de como encarar el patch, que vamos a analizar en el siguiente punto. Uno de ellos sería hacer que eso devuelva siempre &#8220;true&#8221; (o cambiar ese jne a un je). Veamos lo que devuelve esa función:</p>
<pre class="prettyprint"># Seguimos haciendo stepping hasta llegar a 0x00002b72 (Según lo que vimos en el disas ahí está el test al, al).
gdb$ until *0x00002b72
0x00002ab1 in -[SmellsGood_AppDelegate check:] ()</pre>
<p>¿Qué pasó?. No llegó nunca a la dirección que esperábamos. ¿Por qué?. Si analizamos el asm (O mas facil el código Objective-C que puse arriba) en un momento pasa esto:</p>
<pre class="prettyprint">0x00002b1d <-[SmellsGood_AppDelegate checkCode:forName:]+35>:	mov    edx,DWORD PTR ds:0x400c
0x00002b23 <-[SmellsGood_AppDelegate checkCode:forName:]+41>:	mov    DWORD PTR [esp+0x4],edx
0x00002b27 <-[SmellsGood_AppDelegate checkCode:forName:]+45>:	mov    DWORD PTR [esp],eax
0x00002b2a <-[SmellsGood_AppDelegate checkCode:forName:]+48>:	call   0x5072
0x00002b2f <-[SmellsGood_AppDelegate checkCode:forName:]+53>:	cmp    eax,0x5
0x00002b32 <-[SmellsGood_AppDelegate checkCode:forName:]+56>:	jne    0x2b80 <-[SmellsGood_AppDelegate checkCode:forName:]+134></pre>
<p>Supongamos por un momento que no tenemos el nombre de los métodos. Veamos que pasa acá:</p>
<p>Tocamos de nuevo &#8220;<em>check</em>&#8221; y vamos hasta este primer call que vemos arriba.</p>
<pre class="prettyprint">Breakpoint 1, 0x00002b01 in -[SmellsGood_AppDelegate checkCode:forName:] ()
gdb$ until *0x00002b2a
0x00002b2a in -[SmellsGood_AppDelegate checkCode:forName:] ()</pre>
<p>Veamos a qué función va a llamar:</p>
<pre class="prettyprint"># Primero el objeto
gdb$ po *(void **)($esp)
{NSCFArray 0x241010} (
dasdasd
)</pre>
<pre class="prettyprint"># Ahora el método
gdb$ x/s *(char **)($esp + 0x4)
0x990bea10:	 "count"</pre>
<p>Ok, básicamente lo que hace esto es fijarse si el tamaño de un array es 5. Si vemos mas arriba lo había separado por &#8220;-&#8221;. Algo ya podemos asumir: el código tiene que tener 5 partes separadas por &#8220;-&#8221;. Probemos ahora el código <strong>X-X-X-X-X</strong> y tocamos &#8220;<em>check</em>&#8220;.</p>
<pre class="prettyprint">Breakpoint 1, 0x00002b01 in -[SmellsGood_AppDelegate checkCode:forName:] ()
gdb$ until *0x00002b72
0x00002b72 in -[SmellsGood_AppDelegate checkCode:forName:] ()</pre>
<p>Ahora si llegamos. Veamos ahí a qué llama:</p>
<pre class="prettyprint">gdb$ po *(void **)($esp)
X-X-X-X-X
gdb$ x/s *(char **)($esp + 0x4)
0x991037e8 <__PRETTY_FUNCTION__.202408+3076>:	 "isEqualToString:"
gdb$ po *(void **)($esp + 0x4)
37E77CCE-999C2986-B5AC28E4-34238294-C7A9F84B</pre>
<p>Well, well well.. Parece que ya tenemos el código para ese nombre!. Pero no vamos a parar acá ¿no?. Sigamos:</p>
<pre class="prettyprint">gdb$ nexti
0x00002b77 in -[SmellsGood_AppDelegate checkCode:forName:] ()
gdb$ nexti
0x00002b7c in -[SmellsGood_AppDelegate checkCode:forName:] ()</pre>
<p>Bueno, ahí estamos en el test al, al. Como ya sabemos al es un partial de eax. Veamos que tiene:</p>
<pre class="prettyprint">gdb$ info reg eax
eax            0x0	0x0</pre>
<p>El test hace un AND sin guardar el resultado en ningún lado, solamente setea los flags// pero para qué digo todo esto si ya saben asm. Ya con esto estamos.</p>
<h3>Cracking</h3>
<p>Siempre hay mas de un camino para seguir a la hora de patchear o generar un keygen, acá es donde juega el ingenio de cada uno. Yo voy a encarar las dos opciones.</p>
<h4>Patching (easy way)</h4>
<p>La opción mas sencilla como ya vimos es cambiar el jne por un je. Para esto vamos a usar un editor hexadecimal.</p>
<p>Recordemos, lo que queremos cambiar es:</p>
<pre class="prettyprint">+132	00002b7e  7502					  jne		  0x00002b82</pre>
<p>Como en este caso, la arquitectura x86 está primero en el mach-O no necesitamos calcular el offset. Directamente vamos a ese offset (0&#215;2b7e) en el editor hexadecimal, tiene que haber un &#8220;75&#8243; (optcode de <strong>jne</strong>). Cambiamos por &#8220;74&#8243; (optcode de <strong>je</strong>), corremos el programa, llenamos el codigo con cualquier cosa de la forma <strong>X-X-X-X-X</strong> y vemos que pasa.</p>
<p>Voilá!.</p>
<h4>Keygen</h4>
<p>Ya que nos tomamos el trabajo de hacer todo el análisis y de comprender qué está pasando, deberíamos aprovechar y hacer un keygen que imite la lógica que ya pudimos deducir.</p>
<p>Este es el mio:</p>
<pre class="prettyprint">from hashlib import sha1

name = raw_input("Nombre?: ").strip()
sha1str = sha1(name).hexdigest().upper()
slots = [sha1str[i:i+8] for i in xrange(0, len(sha1str), 8)]
code = "%s-%s-%s-%s-%s" % (slots[4], slots[3], slots[1], slots[2], slots[0])
print code</pre>
<p>[0] Si se me permite el neologismo</p>
<p style="text-align: right;"><a href="http://twitter.com/Reflejo">@Reflejo</a></p>

<p><a href="http://feedads.g.doubleclick.net/~a/qwAuRvu_wMKWiNzdMLGPXD1hMG8/0/da"><img src="http://feedads.g.doubleclick.net/~a/qwAuRvu_wMKWiNzdMLGPXD1hMG8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/qwAuRvu_wMKWiNzdMLGPXD1hMG8/1/da"><img src="http://feedads.g.doubleclick.net/~a/qwAuRvu_wMKWiNzdMLGPXD1hMG8/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/DGumCimOy1M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2010/06/16/181/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2010/06/16/181/</feedburner:origLink></item>
		<item>
		<title>Bases de datos, passwords, seguridad y otras yerbas</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/emU4j8VoB9Q/</link>
		<comments>http://blog.cuerty.com/2010/03/24/bases-de-datos-passwords-seguridad-y-otras-yerbas/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 09:04:32 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[geelbe]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[passwords]]></category>
		<category><![CDATA[sql injection]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=178</guid>
		<description><![CDATA[Hoy por la madrugada paso algo bastante fuerte: hackearon geelbe.com
Para los que no lo saben geelbe es un “club privado de compras”, un modelo distinto a sitios como Mercado Libre o De Remate donde cualquiera puede participar. La idea es lograr tener una red de confianza entre la gente que participa ya que solamente se [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy por la madrugada paso algo bastante fuerte: <a href="http://www.uberbin.net/archivos/seguridad/geelbe-hackeado-y-el-problema-de-las-claves-unicas.php">hackearon</a> <a href="http://www.geelbe.com/">geelbe.com</a></p>
<p>Para los que no lo saben geelbe es un “club privado de compras”, un modelo distinto a sitios como Mercado Libre o De Remate donde cualquiera puede participar. La idea es lograr tener una red de confianza entre la gente que participa ya que solamente se entra por invitación.</p>
<p>Al margen de como funciona el sitio, esta madrugada se publico en Internet una lista de usuarios con su respectivo password. ¿Como es esto posible? Facil, los passwords estaban guardados en la base de datos en texto plano.</p>
<p>Existen varias formas en las que uno puede elegir guardar el password de sus usuarios en la base de datos, a saber: <em>en texto plano, encriptadas, encriptadas con salt</em>. Cada una tiene sus pro y sus contras, y de hecho dependiendo del tipo de aplicación que estemos desarrollando existen leyes al respecto.</p>
<p><strong>Texto plano</strong></p>
<p>Guardar las claves en texto plano es lo mas simple. Uno tiene registro del password de cada usuario y cuando este intenta ingresar al sistema se compara el password que nos provee contra el que tenemos en la base de datos, si es igual, lo dejamos pasar, si no es igual, impedimos que acceda.</p>
<p><strong>Encriptada</strong></p>
<p>Cuando uno encripta passwords utiliza algún tipo de hash, esto es, un algoritmo que da por resultado una cadena de texto que no se puede revertir al dato que se ingreso originalmente (el password).</p>
<p>Ejemplos de estos algoritmos son md5 y sha1, los mas utilizados en las aplicaciones WEB por cierto.</p>
<p><strong>Encriptada con salt</strong></p>
<p>Para entender la encriptacion con salt primero hay que ver una gran falencia en la encriptacion a secas: Si uno asume que su aplicación puede, por alguna falla de seguridad, llegar a dejar expuesta la base de datos, y por consiguiente tener acceso a los passwords encriptados, estos pueden llegar a ser revertidos.</p>
<p>¿Pero como? Si recién dije que se utilizan algoritmos por los cuales no se puede llegar al password partiendo del resultado del algoritmo, bien, existen lo que se conoce como rainbow tables, que son listas de los passwords ya encriptados y su correspondiente password en texto plano. De esta forma cuando uno tiene un password encriptado, puede ir a una rainbow table pre generada con millones de passwords y ver si lo encuentra ahí, de ser así, tiene la versión en texto plano del mismo. Obviamente también existe la “fuerza bruta”, esto es, teniendo el hash empezar a probar encriptar todas las combinaciones de letras, números, etc hasta llegar a algún hash que coincida, y ahí obtenemos el password original (o también se puede utilizar una lista de los passwords mas comunes para probar).</p>
<p>¿Como evitamos que alguien venga y compruebe los passwords guardados en la base de datos contra una rainbow table y obtenga el password original? Bueno, podemos, en lugar de guardar el hash del password, agregarle una pequeña cadena de texto “random” al password original, y después guardarnos el hash resultante de encriptar eso y también guardarnos la cadena. Esta es la practica mas extendida hoy en día y frameworks como Django ya lo hacen desde el vamos, también el cookbook de Ruby on Rails nos recomienda hacerlo. Es mucho menos probable que existan rainbow con el password mas una cadena al azar de que si existen rainbow tables con el password solamente.</p>
<p>Viendo estas tres opciones tenemos que decir que el caso de Geelbe coincida con el primero, ellos no encriptan los passwords guardados en la base de datos lo cual no seria problema si nadie pudiera acceder a la base de datos.</p>
<p>Puedo asumir que como quien tuvo acceso a los passwords los publico en la web, que no accedio al servidor, ya que su intencion era la de hacer algun daño a la imagen de Geelbe y de haber tenido acceso al servidor seguramente hubiera defaceado (ie: cambiado la pagina por algo tipo “hackeado por pepito”) y no solamente publicado los passwords. Seguramente el acceso se dio por algún SQL Injection como <a href="http://www.patriciomolina.com/2010/02/xss-y-sql-injection-en-infobae-com/">el que Patricio descubrió hace unas semanas en Infobae</a>.</p>
<p>Otro detalle a tener en cuenta, y esta practica no esta tan extendida, es la elección del algoritmo para encriptar/hashear los passwords. Si bien las practicas comunes nos dicen que usemos md5 y sha1, lo cierto es que esos algoritmos no fueron diseñados para esa tarea, son efectivos, si, pero tienen un problema: son rápidos.</p>
<p>¿Que tiene de malo que sean rápidos? Cuando uno controla a un usuario que accede a su sitio por lo general guarda una cookie que. Esta cookie guarda solamente un identificador de sesión el cual en el servidor terminamos asociando con el usuario, esto quiere decir que solamente la primer ves que accede el usuario al sitio se comprueba su password. Así que no necesitamos que sea rápido. ¿Donde si es útil la velocidad del algoritmo de hasheo? Cuando uno trata de hacer brute force. Si vos tenes un hash y queres ir probando todas las palabras posibles contra ese hash, y cada intento te toma milésimas de segundo, vas a llegar mucho mas rápido a destino que si te toma 1 segundo cada intento. Es por eso que es recomendable utilizar algún algoritmo como <a href="http://codahale.com/how-to-safely-store-a-password/">bcrypt</a> que si están diseñados para guardar passwords de usuarios (¡Es lento apropósito!).</p>
<p>Si la aplicación por otro lado tiene que manejar datos como tarjetas de crédito y cobros (PayPal, Google checkout, etc), recomiendo leer las guiás de PCI y los blogs de la gente que desarrolla los estándares de seguridad para ese tipo de aplicaciones (por suerte hasta ahora no me toco desarrollar ninguna así de critica).</p>
<p>Una nota al margen del objetivo del post (concientizar del sano storage de passwords): La gente de Geelbe esta haciendo un laburo groso, un SQL Injection no es un bug tan raro y el error grave que tuvieron (tener los passwords en pseudo texto plano) es corregible 100%, no seamos botones y pasemos la lista de usuarios afectados y sus passwords por ahí.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/xheI1B4IzQbOiaAFDstjunXmAj0/0/da"><img src="http://feedads.g.doubleclick.net/~a/xheI1B4IzQbOiaAFDstjunXmAj0/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/xheI1B4IzQbOiaAFDstjunXmAj0/1/da"><img src="http://feedads.g.doubleclick.net/~a/xheI1B4IzQbOiaAFDstjunXmAj0/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/emU4j8VoB9Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2010/03/24/bases-de-datos-passwords-seguridad-y-otras-yerbas/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2010/03/24/bases-de-datos-passwords-seguridad-y-otras-yerbas/</feedburner:origLink></item>
		<item>
		<title>Jugando con el sistema</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/qBEPr1ZHHxc/</link>
		<comments>http://blog.cuerty.com/2009/12/20/jugando-con-el-sistema/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 05:37:10 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[gaming]]></category>
		<category><![CDATA[managing]]></category>
		<category><![CDATA[system]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=175</guid>
		<description><![CDATA[
Hace algunos días leí “Gaming de system”, un articulo del blog Rands in Response, y me impacto la claridad de este párrafo:
Vemos el mundo como un complejo pero conocible diagrama de flujo donde hay una finita cantidad de entradas, lo que causa una similar finita cantidad de salidas. Este imposible diagrama nos da la reconfortante [...]]]></description>
			<content:encoded><![CDATA[<p><img alt="Mi juego favorito" src="http://blog.cuerty.com/wp-includes/images/attachments/teg.jpg" width="360" height="241" /></p>
<p>Hace algunos días leí “<a href="http://www.randsinrepose.com/archives/2009/12/13/gaming_the_system.html">Gaming de system</a>”, un articulo del blog Rands in Response, y me impacto la claridad de este párrafo:</p>
<p>Vemos el mundo como un complejo pero conocible diagrama de flujo donde hay una finita cantidad de entradas, lo que causa una similar finita cantidad de salidas. Este imposible diagrama nos da la reconfortante ilusión de control y entendimiento del caótico mundo, pero su existencia es un efecto secundario de una vida mirando, deduciendo, y construyendo sistemas. Es también porque nos gustan tanto los juegos – ellos son solamente sistemas mas pequeños – y mientras mas entiendas esta fascinacion con los juegos, mejor vas a ser manejándonos.</p>
<p>En espíritu, el <a href="http://www.catb.org/~esr/faqs/hacker-howto.html">hacker how to</a> expresa las mismas ideas:</p>
<blockquote><p>Es muy divertido ser un hacker, pero es la clase de diversión que requiere mucho esfuerzo. El esfuerzo requiere motivación. Los atletas triunfadores obtienen su motivación a partir de un tipo de placer físico que surge de trabajar su cuerpo, al forzarse a sí mismos más allá de sus propios límites físicos. De manera similar, para ser un hacker deberás sentir un estremecimiento de tipo primitivo cuando resuelves problemas, afinas tus habilidades y ejercitas tu inteligencia. </p>
<p><a href="http://biblioweb.sindominio.net/telematica/hacker-como.html#believe1">Cómo convertirse en hacker,  El mundo está lleno de problemas fascinantes que esperan ser resueltos</a>, Eric S. Raymond.</p></blockquote>
<p>Las derivaciones de este principio son muy importantes, con el ambiente necesario, y planteándolo como un juego, nuestro trabajo de desarrollo se convierte en algo que nos atrapa y nos permite estar sin perder concentración o interés durante horas. ¿No nos pasa lo mismo cuando jugamos un MMORPG y estamos en la tarea de matar 1000 bichitos?</p>
<p><a href="http://www.randsinrepose.com/archives/2009/12/13/gaming_the_system.html">Este articulo</a> es una de las lecturas recomendadas de la semana.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/iBS14ak0_bJACySUEIJfCThQSJU/0/da"><img src="http://feedads.g.doubleclick.net/~a/iBS14ak0_bJACySUEIJfCThQSJU/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/iBS14ak0_bJACySUEIJfCThQSJU/1/da"><img src="http://feedads.g.doubleclick.net/~a/iBS14ak0_bJACySUEIJfCThQSJU/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/qBEPr1ZHHxc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2009/12/20/jugando-con-el-sistema/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2009/12/20/jugando-con-el-sistema/</feedburner:origLink></item>
		<item>
		<title>Diagrama de la cultura geek</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/RQOt2sGxovE/</link>
		<comments>http://blog.cuerty.com/2009/12/14/diagrama-de-la-cultura-geek/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 10:11:55 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Links]]></category>
		<category><![CDATA[culture]]></category>
		<category><![CDATA[diagram]]></category>
		<category><![CDATA[geek]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=171</guid>
		<description><![CDATA[Estoy sin mucho tiempo para escribir últimamente, pero cuando encuentro algo entretenido trato de compartirlo acá. Hoy, diagrama de la cultura geek (via I love charts)

]]></description>
			<content:encoded><![CDATA[<p>Estoy sin mucho tiempo para escribir últimamente, pero cuando encuentro algo entretenido trato de compartirlo acá. Hoy, diagrama de la cultura geek (via <a href="http://ilovecharts.tumblr.com">I love charts</a>)</p>
<p><a href="http://ilovecharts.tumblr.com/post/283732161"><img src="http://blog.cuerty.com/wp-includes/images/attachments/geek_map.jpg" alt="Diagrama de la cultura geek" /></a></p>

<p><a href="http://feedads.g.doubleclick.net/~a/oa9sCnzXyCOSBPHKgVDeZEaaoyY/0/da"><img src="http://feedads.g.doubleclick.net/~a/oa9sCnzXyCOSBPHKgVDeZEaaoyY/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/oa9sCnzXyCOSBPHKgVDeZEaaoyY/1/da"><img src="http://feedads.g.doubleclick.net/~a/oa9sCnzXyCOSBPHKgVDeZEaaoyY/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/RQOt2sGxovE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2009/12/14/diagrama-de-la-cultura-geek/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2009/12/14/diagrama-de-la-cultura-geek/</feedburner:origLink></item>
		<item>
		<title>Un día en internet</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/LZCdGspMTk4/</link>
		<comments>http://blog.cuerty.com/2009/12/08/un-dia-en-internet/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 13:39:02 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Sin categoria]]></category>
		<category><![CDATA[infografia]]></category>
		<category><![CDATA[internet]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/2009/12/08/un-dia-en-internet/</guid>
		<description><![CDATA[Interesante infografía del volumen de datos que se mueven en internet por día:
Created by OnlineEducation.net
]]></description>
			<content:encoded><![CDATA[<p>Interesante infografía del volumen de datos que se mueven en internet por día:</p>
<p><a href="http://www.onlineeducation.net/internet/"><img src="http://www.onlineeducation.net/internet/social-media-count_full.jpg" alt="A Day in the Internet" width="500" height="1624" border="0" /></a><br />Created by <a href="http://www.onlineeducation.net">OnlineEducation.net</a></p>

<p><a href="http://feedads.g.doubleclick.net/~a/AlIEk7EYckv_w4Cho8M5zLyxoMw/0/da"><img src="http://feedads.g.doubleclick.net/~a/AlIEk7EYckv_w4Cho8M5zLyxoMw/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/AlIEk7EYckv_w4Cho8M5zLyxoMw/1/da"><img src="http://feedads.g.doubleclick.net/~a/AlIEk7EYckv_w4Cho8M5zLyxoMw/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/LZCdGspMTk4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2009/12/08/un-dia-en-internet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2009/12/08/un-dia-en-internet/</feedburner:origLink></item>
		<item>
		<title>Google Public DNS es rápido</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/Uo5pA_vRjpI/</link>
		<comments>http://blog.cuerty.com/2009/12/06/google-public-dns-es-rapido/#comments</comments>
		<pubDate>Sun, 06 Dec 2009 12:24:29 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[dontbeevil]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=164</guid>
		<description><![CDATA[Como sabrán esta semana Google anuncio que abrió un DNS server publico.

Las ventajas de usar los servicios de Google las conocemos: Son gratis (la mayoría), tienen un uptime decente y lo mas interesante: son rápidos. Pero, como con todo anuncio de una compañía grande, surgieron en internet un por de dudas:

¿Que información guarda Google sobre [...]]]></description>
			<content:encoded><![CDATA[<p>Como sabrán esta semana <a href="http://googlesystem.blogspot.com/2009/12/google-dns.html">Google anuncio que abrió un DNS server publico</a>.</p>
<p><img src="http://code.google.com/intl/es-AR/speed/public-dns/images/adwords_features_v2_l.gif" alt="Google Public DNS" /></p>
<p>Las ventajas de usar los servicios de Google las conocemos: Son gratis (la mayoría), tienen un uptime decente y lo mas interesante: son rápidos. Pero, como con todo anuncio de una compañía grande, <a href="http://thevagary.net/archives/2009/12/why_i_moved_my_home_network_to_googles_public_dns.html">surgieron en internet un por de dudas</a>:</p>
<ul>
<li>¿Que información guarda Google sobre el uso que le de a su servidor de DNS? </li>
<li>¿Porque no ayudaron a un <a href="http://www.opendns.com/">proyecto como OpenDNS</a> en lugar de crear su propio proyecto.</li>
<li>Google tiene control sobre tantas cosas ya (email, búsquedas, publicidad) que empieza a asustar un poco.</li>
</ul>
<p>De hecho en <a href="http://www.cgisecurity.com/2009/12/risks-of-using-googles-free-dns-service.html">sitios como cgisecurity</a> salieron serias criticas, todas relacionadas con la cantidad que de información que le damos a Google, ya que esto les permite hacer un perfil sobre el uso que le damos a internet, aun en sitios que no tengan Google Adsense/Analytics.</p>
<p>La conclusión a la que llegaron algunos bloggers es que a Google le interesa que Internet sea mas rápida, ya que esto les permite imprimir mas banners y ganar mas plata.</p>
<p>Así que me decidí a investigar un poco que tan rápido es Google Public DNS.</p>
<p>Encontré varios artículos criticando la velocidad del servicio, <a href="http://business.swivel.com/charts/8351-how-fast-is-your-dns-">diciendo que no era tan rápido</a>. Pero no me convencían así que decidí hacer mis propias pruebas con nslookup y para mi sorpresa, al menos en mi ISP, Google Public DNS es 5 veces mas rápido que OpenDNS (el cual ya era el doble de mas rápido que mi ISP).</p>
<p>Después de usarlo un par de horas en mi desktop decidí pasar la red de mi casa a este servicio.</p>
<p>En mi caso es fácil, uso un router wifi Linksys WRT54GL que tengo flasheado con <a href="http://www.dd-wrt.com/site/index">DD-WRT</a> (un firmware opensource que me brinda opciones como conectarme a la VPN de la oficina) así que lo único que tuve que hacer fue ir a la opción de Commands, dentro del menú Administration, escribir el siguiente script:</p>
<p><code>echo “nameserver 8.8.8.8” > /tmp/resolv.dnsmasq<br />
echo “nameserver 8.8.4.4” >> /tmp/resolv.dnsmasq<br />
sleep 1<br />
killall -HUP dnsmasq</code></p>
<p>Y clickear sobre “Save Firewall”.</p>
<p>Para no tener que reiniciar el router simplemente corrí esos comandos a traves de la interface SSH del mismo.</p>
<p>Conclusión: La velocidad se nota.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/DfvvTidh-UIJFfcSZXLFsQG3gi4/0/da"><img src="http://feedads.g.doubleclick.net/~a/DfvvTidh-UIJFfcSZXLFsQG3gi4/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/DfvvTidh-UIJFfcSZXLFsQG3gi4/1/da"><img src="http://feedads.g.doubleclick.net/~a/DfvvTidh-UIJFfcSZXLFsQG3gi4/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/Uo5pA_vRjpI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2009/12/06/google-public-dns-es-rapido/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2009/12/06/google-public-dns-es-rapido/</feedburner:origLink></item>
		<item>
		<title>Evita linuxera</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/R21CAc2n4ZQ/</link>
		<comments>http://blog.cuerty.com/2009/12/03/evita-linuxera/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 02:46:35 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Links]]></category>
		<category><![CDATA[evita]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[peter capusotto]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=161</guid>
		<description><![CDATA[Hace pocos días descubrí el blog de “Si Evita estuviera viva seria Linuxera”.
Es un blog sobre Linux y peronismo (?) que lleva varias explicaciones de distintos temas con algo de humor, parafraseando a un compañero de trabajo: Es como ver “Peter Capusotto y sus Videos” pero hablando de vim.
Hoy justo Evita esta presentando Python, acá [...]]]></description>
			<content:encoded><![CDATA[<p>Hace pocos días descubrí el blog de “<a href="http://evitalinuxera.blogspot.com/">Si Evita estuviera viva seria Linuxera</a>”.</p>
<p>Es un blog sobre Linux y peronismo (?) que lleva varias explicaciones de distintos temas con algo de humor, parafraseando a un compañero de trabajo: Es como ver “<a href="http://http://www.youtube.com/results?search_query=peter%20capusotto%20y%20sus%20videos&#038;search_type=&#038;aq=f&#038;oq=">Peter Capusotto y sus Videos</a>” pero hablando de vim.</p>
<p>Hoy justo <a href="http://evitalinuxera.blogspot.com/2009/12/construyendo-la-patria-peronista.html">Evita esta presentando Python</a>, acá un fragmento:</p>
<blockquote><p>Es por eso que hoy les traemos la noticia que cambiará la manera de trabajar, el desarrollo está golpeando las puertas de la Patria y es tarea del movimiento  obrero, abrir esa puerta para convertirlo en una realidad nacional. A partir de hoy, queridos compañeros, desde este mismo lugar, tendremos un curso de Python, el lenguaje de programación Justicialista, el que ejerce la tercera posición entre  Java y  .net, los dos males de estos tiempos.</p></blockquote>
<p>Espero que les guste el blog. Yo me estoy divirtiendo leyendolo.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/u9wV1TPNUQRzyMjShSCJeK9NZLE/0/da"><img src="http://feedads.g.doubleclick.net/~a/u9wV1TPNUQRzyMjShSCJeK9NZLE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/u9wV1TPNUQRzyMjShSCJeK9NZLE/1/da"><img src="http://feedads.g.doubleclick.net/~a/u9wV1TPNUQRzyMjShSCJeK9NZLE/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/R21CAc2n4ZQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2009/12/03/evita-linuxera/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2009/12/03/evita-linuxera/</feedburner:origLink></item>
		<item>
		<title>¿NetBSD rapido?</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/9Z2I02Xs-zc/</link>
		<comments>http://blog.cuerty.com/2009/12/03/%c2%bfnetbsd-rapido/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 02:37:08 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=156</guid>
		<description><![CDATA[Yo tengo la costumbre de pensar así:

Desktop: Linux (Gentoo, Fedora, Ubuntu o Arch)
Server: Linux (Gentoo o Debian) o FreeBSD.

Pero este benchmark me lleno de sorpresas:

¿NetBSD con SMP mas rápido que el resto? Voy a tener que hacer algunas pruebas&#8230;
]]></description>
			<content:encoded><![CDATA[<p>Yo tengo la costumbre de pensar así:</p>
<ul>
<li>Desktop: Linux (Gentoo, Fedora, Ubuntu o Arch)</li>
<li>Server: Linux (Gentoo o Debian) o FreeBSD.</li>
</ul>
<p>Pero <a href="http://mauthesis.com/sysbench.html">este benchmark</a> me lleno de sorpresas:</p>
<p><a href="http://blog.cuerty.com/wp-includes/images/attachments/sysbench.png"><img src="http://blog.cuerty.com/wp-includes/images/attachments/sysbench.png" alt="Benchmark de MySQL sobre el mismo hardware en distintos OS con SMP." /></a></p>
<p>¿NetBSD con SMP mas rápido que el resto? Voy a tener que hacer algunas pruebas&#8230;</p>

<p><a href="http://feedads.g.doubleclick.net/~a/W-PiWh2SgV2ujkXzMI3Uf-RDoUM/0/da"><img src="http://feedads.g.doubleclick.net/~a/W-PiWh2SgV2ujkXzMI3Uf-RDoUM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/W-PiWh2SgV2ujkXzMI3Uf-RDoUM/1/da"><img src="http://feedads.g.doubleclick.net/~a/W-PiWh2SgV2ujkXzMI3Uf-RDoUM/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/9Z2I02Xs-zc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2009/12/03/%c2%bfnetbsd-rapido/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2009/12/03/%c2%bfnetbsd-rapido/</feedburner:origLink></item>
		<item>
		<title>Namespaces</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/JAWnJLCGfIY/</link>
		<comments>http://blog.cuerty.com/2009/12/02/namespaces/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 14:49:25 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[namespaces]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=151</guid>
		<description><![CDATA[Hoy en el blog de Christopher Lenz salio un interesante esbozo de articulo sobre los namespaces y como la mayoría de los lenguajes de programación manejan mal ese concepto.
El ejemplo en C# es clarisimo:
using System;
using System.IO;
public class HelloWorld {
   public static void Main(string[] args) {
      Console.WriteLine("Hello, World!");
  [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy en el blog de Christopher Lenz salio un interesante <a href="http://www.cmlenz.net/archives/2009/12/namespaces">esbozo de articulo sobre los namespaces</a> y como la mayoría de los lenguajes de programación manejan mal ese concepto.</p>
<p>El ejemplo en C# es clarisimo:</p>
<p><code>using System;<br />
using System.IO;</p>
<p>public class HelloWorld {<br />
   public static void Main(string[] args) {<br />
      Console.WriteLine("Hello, World!");<br />
   }<br />
}<br />
</code></p>
<p>¿De donde sale Console? Y no queda en C#, hoy por hoy estoy trabajando mucho en C++:</p>
<p><code>#include &lt;iostream&gt;</p>
<p>int main()<br />
{<br />
  std::cout << "Hola mundo!" << std::endl;<br />
}<br />
</code></p>
<p>¿De donde sale std? Y lo que es peor, muchos include te pueden llenar a std de distintas cosas.</p>
<p>La parte que mas me gusto es del articulo es esta:</p>
<blockquote><p>Resulta que los lenguajes en los que estoy actualmente interesado entienden esto (mas o menos) bien: Python, Erlang, Go, y (aunque no es un lenguaje) node.js.</p></blockquote>
<p>+1 Python otra ves.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/XwRgDFFO7OYkP7_PprsyhLOI2tM/0/da"><img src="http://feedads.g.doubleclick.net/~a/XwRgDFFO7OYkP7_PprsyhLOI2tM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/XwRgDFFO7OYkP7_PprsyhLOI2tM/1/da"><img src="http://feedads.g.doubleclick.net/~a/XwRgDFFO7OYkP7_PprsyhLOI2tM/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/JAWnJLCGfIY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2009/12/02/namespaces/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2009/12/02/namespaces/</feedburner:origLink></item>
		<item>
		<title>Como obtener el Window Handle (HWND) de una ventana en Windows y 4 momentos epicos de MSDN</title>
		<link>http://feedproxy.google.com/~r/DiarioDeUnProgramador/~3/JJQSE3nadzU/</link>
		<comments>http://blog.cuerty.com/2009/11/27/como-obtener-el-window-handle-hwnd-de-una-ventana-en-windows-y-4-momentos-epicos-de-msdn/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 06:57:01 +0000</pubDate>
		<dc:creator>qwerty</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[lol]]></category>
		<category><![CDATA[rant]]></category>

		<guid isPermaLink="false">http://blog.cuerty.com/?p=143</guid>
		<description><![CDATA[La documentación de Microsoft para desarrolladores es mala. Esta es la conclusión a la que llegue después de ver que en MSDN no sabían unicode.
Pero lo que mas gracia me causa de MSDN es cuando documentan pequeños workarounds para las limitaciones de sus productos. Este es un ejemplo: How To Obtain a Console Window Handle [...]]]></description>
			<content:encoded><![CDATA[<p>La documentación de Microsoft para desarrolladores es mala. Esta es la conclusión a la que llegue después de ver que <a href="http://blog.cuerty.com/2009/04/05/microsoft-no-sabe-unicode/">en MSDN no sabían unicode</a>.</p>
<p>Pero lo que mas gracia me causa de MSDN es cuando documentan pequeños workarounds para las limitaciones de sus productos. Este es un ejemplo: <a href="http://support.microsoft.com/kb/124103">How To Obtain a Console Window Handle (HWND)</a>.</p>
<p>Un HWND se utiliza para acceder a propiedades de la ventana, el problema es que en viejas versiones de la API de Windows no había un método para listar las ventanas de una aplicación que retornara el HWND de estas, así que Microsoft surgió con este hack:</p>
<ul>
<li>Llame a GetConsoleTitle() para guardar el título de ventana de consola actual. </li>
<li>Llame a SetConsoleTitle() para cambiar el título de la consola a un título único. </li>
<li>Se actualizó Sleep(40) de llamada para garantizar el título de la ventana. </li>
<li>Llamada a FindWindow (NULL, uniquetitle) para obtener el objeto HWND esta llamada devuelve el HWND&#8211;o NULL si no se pudo realizar la operación. </li>
<li>Llamada SetConsoleTitle() con el valor se recupera del paso 1, para restaurar el título de ventana original. </ul>
</li>
<p><img alt="Plop!" src="http://blog.cuerty.com/wp-includes/images/attachments/plop.jpg" title="Plop!" width="400" height="300" /></p>
<p>¿Soy al único que le parece un hack horrible?</p>
<p>Otros momentos épicos de MSDN:</p>
<ul>
<li><a href="http://social.msdn.microsoft.com/forums/en-US/winformssetup/thread/ae06a513-4655-4c92-9cfe-459529dc66ce/">Notepad tiene mas funcionalidades que vim</a>.</li>
<li><a href="http://msdn.microsoft.com/en-us/library/wz42302f%28loband%29.aspx">Buscar por *.* puede ser un tanto confuso (lean la aclaración al pie)</a>.</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms441219.aspx">Esconder el almanaque de Taiwan en China</a>.</li>
<li>Uno de mis preferidos: “<a href="http://support.microsoft.com/kb/168702">Si Oracle te devuelve este mensaje de error, lo que tenes que hacer es no dejar de mover el mouse mientras ejecutas la consulta</a>”.</li>
</ul>

<p><a href="http://feedads.g.doubleclick.net/~a/TRw5L4gD6mjfY4oKmT-Bd7AYsvE/0/da"><img src="http://feedads.g.doubleclick.net/~a/TRw5L4gD6mjfY4oKmT-Bd7AYsvE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/TRw5L4gD6mjfY4oKmT-Bd7AYsvE/1/da"><img src="http://feedads.g.doubleclick.net/~a/TRw5L4gD6mjfY4oKmT-Bd7AYsvE/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DiarioDeUnProgramador/~4/JJQSE3nadzU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.cuerty.com/2009/11/27/como-obtener-el-window-handle-hwnd-de-una-ventana-en-windows-y-4-momentos-epicos-de-msdn/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.cuerty.com/2009/11/27/como-obtener-el-window-handle-hwnd-de-una-ventana-en-windows-y-4-momentos-epicos-de-msdn/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.658 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-08-30 04:56:27 -->
