¿FAES?
Un reto: crackear mi plugin
¿Cómo se consigue eso? Pues muy sencillo. El plugin genera para cáda página un código JavaScript aleatorio que el browser tiene que interpretar para conseguir un resultado. El browser entonces tiene que devolver el resultado de ejecutar el javascript como un campo más del formulario de comentario. Por ejemplo, un código al azar generado es el siguiente:
function go_anti_spam()
{
eElement = document.getElementById("chk");
if(!eElement){ return false; }
else
{
v0=1368;v1=1581;v2=927;v3=802;v4=1280;v5=968;v6=1745;v7=1147;v8=661;v9=1376;v10=2086;v11=1539;v12=165;v13=1380;v14=1407;v15=114;if ( v15 > 2059)
{ v7 = v15; }if ( v15 > 1735)
{ v10 = v12; }if ( v11 > 1503)
{ v12 = v8; }v10=(v13-v5)%2514;v4=Math.abs(v4);
v4%=26; while (v4--) {
v0++; }v0=(v8+v12)%2514;eElement.value = (v0+v1+v2+v3+v4+v5+v6+v7+v8+v9+v10+v11+v12+v13+v14+v15)%2514;
return true;
}
}
El gran problema que les plantea esto a los spammers es que tendrían que hacer que sus programas de envío de comentarios automáticos supieran interpretar JavaScript... Hasta este punto de sofisticación no llegan. Sin embargo, aquí viene el reto:
Pensando se me han ocurrido al menos tres formas de saltarse el plugin de una forma más o menos sencilla (o al menos, en teoría). Una de ellas ya os la he dicho: Que los spammers tengan un programa que interprete también el javascript de la página (harto improbable).
¿Cuáles son las otras dos formas? Grandes premios para los acertantes. :D
Anoche lloré con un libro
Ahora: "Imprimatur" de Monaldi & Sorti. Ya hablaré sobre ella.
Mis coqueteos con AMD64
processor : 0
vendor_id : AuthenticAMD
cpu family : 15
model : 12
model name : AMD Athlon(tm) 64 Processor 3400+
stepping : 0
cpu MHz : 2412.160
cache size : 512 KB
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 pni syscall nx mmxext lm 3dnowext 3dnow
bogomips : 4751.36
TLB size : 1024 4K pages
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management: ts fid vid ttp
Como últimamente me he dado cuenta de que dentro de las distribuciones basadas en Debian (sin duda la mejor distribución) Ubuntu es una de las más cuidadas en todos los aspectos, me decidí a ponerle la última versión, a saber, la Hoary 5.04. Sin embargo, esa distribución, al menos en la versión para AMD64 tiene un problema al instalar el núcleo. O bien mi ISO estaba mal, o la grabación, pero el caso es que el paquete del núcleo que llevaba no se instalaba bien. Tuve que bajarlo de la red e instalarlo a mano, lo cual no fue muy fácil.
Sin embargo, el sistema no funcionaba muy bien. Se colgaba cuando entraba en modo multiusuario. Después de muchas vueltas, me di cuenta de qué programa era el que fallaba: powernowd, o lo que es lo mismo, el sistema fallaba al intentar cambiar la velocidad del procesador (los nuevos procesadores son una maravilla de la técnica y permiten cambiar la velocidad del procesador conforme haga más o menos trabajo). Así que lo eliminé. Aún así, el problema persistió.
Busqué ayuda por otro sitio y vi que debian tenía una iniciativa de debian para AMD64. Pensé en instalar ese núcleo a ver si los problemas se iban. Y efectivamente, con ese núcleo todo ha ido bien (eso sí, sin powernowd ni ningún otro programa que cambie la velocidad del procesador, al menos de momento). Por ahora el núcleo que tengo es este:
Linux version 2.6.11-9-amd64-k8 (root@athlon.lowpingbastards.de) (gcc version 3.4.4 20050314 (prerelease) (Debian 3.4.3-12)) #1 Sun Mar 27 12:58:31 CEST 2005
(específico para K8) y va bastante bien. Sólo tiene un problema: que hay muchas cosas compiladas para i386 y derivados que no se pueden instalar directamente (la arquitectura no es la misma) y aunque este procesador puede ejecutar aplicaciones para i386, hay que hacer ciertos hacks por ahora.
Así que lo verdaderamente interesante es este tutorial de instalación de Debian en AMD64. Por ahora lo estoy haciendo. La idea es tener un sistema con chroot en el que se pueden instalar los paquetes i386. Así se pueden ejecutar todos los programas que todavía no estén disponibles para AMD64.
El ordenador va muy rápido, sobre todo en el modo nativo de 64 bits, pero no se me ocurre ningúna prueba que sirva para ver cuán rápido va. Digamos que Firefox 1.0.2 de Ubuntu Horary tarda, en la primera ejecución, unos dos segundos en salir en la pantalla.
Intenté instalarle Windows XP, pero no hubo suerte: no soporta la controladora/discos Serial ATA y tengo que ver cómo obtengo los drivers para ponérselos al XP en la instalación. Hasta ahora no he tenido suerte. Menos mal que utilizo sistemas operativos que se pueden llamar así :)
Optimizando código
for (i=0; i < npalabras; ++i)
{
strcat(cadena, palabras[i]);
if (i != npalabras - 1)
strcat(cadena, " ");
}
Este código es perfectamente normal, y de hecho lo he utilizado de formas parecidas yo mismo anteriormente. Sin embago, estudiándolo un poco tenemos varias cuestiones:
1. En cada bucle se hacen dos comparaciones. Una para el bucle y otra para el if. Esto es muy costoso, sobre todo porque se hace una comparación en cada paso del bucle cuando sabemos que sólo se cumple en la última iteración. Los saltos por lo general rompen la estructura de ejecución interna de los procesadores. Sí, ya sé que llevan predictores de saltos, pero hay ocasiones como esta en las que podemos optimizar el código de una forma elegante.
2. Se hace una resta cada iteración para la comparación (npalabras - 1).
Alguien puede decir que el tiempo del strcat comparado con lo otro es ridículo. Y tiene razón, pero en este caso. Aquí estamos viendo la idea general, la optimización. Así que manos a la obra. La siguiente versión:
for (i=0; i < npalabras - 1; ++i)
{
strcat(cadena, palabras[i]);
strcat(cadena, " ");
}
strcat(cadena, palabras[i]);
Ahora, gracias a repetir el código del último bucle podemos optimizarlo. Nótese que después del bucle, la variable "i" tiene el valor correcto para el último strcat. Sin embargo, todavía no me gusta. Tiene un detalle que no me gusta: la comparación se hace en cada bucle y se tiene que calcular en cada bucle la expresión "npalabras - 1". Para mí la mejor solución sería entonces:
register size_t np = npalabras - 1;
for (i=0; i < np; ++i)
{
strcat(cadena, palabras[i]);
strcat(cadena, " ");
}
strcat(cadena, palabras[i]);
Y así colorín colorado hemos optimizado un bucle. Quizá este ejemplo no sea el mejor del mundo, pero ejemplifica que programar no es sólo hacer funcionar un programa. Me encanta la programación y la optimización de código. Iré mostrando más cosas conforme pase el tiempo.
¡Por fin! ¡Fotos de los tambores de este año!



Si nadie va a tomar cerveza, yo tampoco
Algo en qué pensar...
Planet Murcia Reloaded
¡¡Gracias, Juanjo!!
Continuando con el planeta, la generación del mismo se encuentra con problemas con varias bitácoras. Desde hace tiempo quiero dedicar un post a este problema y no he tenido tiempo. El caso es que el feed de algunas de las bitácoras da error y no sale listado en el planet. Esto estoy seguro de que lo habrán solucionado de alguna manera en otros planets, por lo que voy a investigar un poco. Después cuando tenga tiempo pondré otra entrada comentando el problema concreto a ver si a alguien se le ocurre una solución.
XSH: XML Editing Shell
------------------------------------------------------------
xsh - XML Editing Shell version 2.0.2/0.12 (Revision: 2.2)
------------------------------------------------------------
Copyright (c) 2002 Petr Pajas.
Esta noche es la gran noche
Ahora mismo estoy en Madrid, pero raudo cogeré el coche para llegar a tiempo. Así que para los que leáis esto, lo más probable es que me pilléis de camino.
No obstante, os invito a todos a ir esta noche. A partir de las 11 todo el mundo se concentra en la plaza del ayuntamiento y a las 12 es la gran explosión, que dura hasta el día siguiente. Un espectáculo digno de ver si nunca habéis ido, y que pilla a un paso de toda la región (ya que Mula está en el centro, y bien comunicada por autovía desde Murcia y desde Caravaca).
En esta otra web podeis ver el mapa de cómo llegar, y también otra página sobre los tambores, mucho más apasionada.
Os espero esta noche. Por mi parte, yo voy a disfrutar como un niño, y qué ilusión me hace que mi novia me acompañe.
Más Planet Murcia
New version of the CCM tutorial
Espein is Espein!
- ¿Quién?
- ¿Está Perico?
- ¿Quién eres? --Ojo a esto.
- Soy un amigo suyo... er... lo buscaba para ver si estudiábamos un rato.
- Pues es que se ha ido.
- Ah, vale.
Así somos en España. Ojo a la pregunta tipo "¿Quién eres?" o "¿De parte de quién?" ODIO eso. Además, me parece una falta de respeto. O sea, que la madre del susodicho Perico sabe que su hijo se ha ido pero pregunta para enterarse quién lo busca, haciendo gala de esa curiosidad morbosa que tenemos los españoles. Pero es más... uno malicioso podría pensar que la mujer ha _modificado la respuesta en función de quién era_. No quiera el altísimo...
WP-Morph en Blgging-Pro
* En qué se diferencia de WP-HashCash (ahí lo explico).
* ¿Qué pasa con los usuarios que tienen JavaScript deshabilitado? No pueden enviar comentarios, básicamente...
A ver qué aceptación tiene. Veré si lo envío al repositorio de plugins de WordPress.
Código fuente de WP-Morph
<?php // -*- mode: php -*- vim: expandtab ts=8 sw=8
/*
Plugin Name: WP-Morph
Plugin URI: http://wordpress.org/#
Description: Fool spammers by creating a complicated javascript program to be executed by a real browser.
Author: Diego Sevilla Ruiz
Version: 1.0
Author URI: http://neuromancer.inf.um.es/blog
Id: $Id: wp-morph.php 500 2005-03-15 20:39:58Z dsevilla $
*/
/// Put some random value here!!!
// Greater than 0, and less than 1000000
$rnd_val = xxx;
/// Put some random value here!!!
// Check the result through the MD5 sum.
function morph_check_md5($comment) {
global $rnd_val;
// Check the fast check :)
if ('spammers_go_home' == trim(strip_tags($_POST['checkpoint'])) )
{
// Check that md5 of check is the same than produced
$v = $_POST['calc_value'];
// This value cannot be known by spammers
$v += $rnd_val;
$v = md5($v);
if ($v == $_POST['result_md5'])
{
return $comment;
}
}
die( "Spammer, go home" );
}
add_filter('post_comment_text', 'morph_check_md5');
// Output form actions
function morph_output_form_items($page) {
global $rnd_val;
// We have three arrays of random size. Complicated calculus can
// be made here.
// 6 to 20 variables
$nvars = rand(6,20);
$maxval = rand(1000,10000);
$vvv = array();
for ($i = 0 ; $i < $nvars; $i++)
{
$v = rand(1,$maxval - 1);
$js_str .= 'v' . $i . '=' . $v . ';';
$vvv[$i] = $v;
}
$nops = rand(3,20);
for ($i = 0; $i < $nops; $i++)
{
// Operator
$op = rand(0,5);
// Select two variables and result, random
$v1 = rand(0, $nvars - 1);
$v2 = rand(0, $nvars - 1);
$v3 = rand(0, $nvars - 1);
switch($op)
{
// +
case '0':
$vvv[$v3] = ($vvv[$v1] + $vvv[$v2]) % $maxval;
$js_str .= 'v'.$v3.'=(v'.$v1
. '+v'.$v2.')%'. $maxval .';';
break;
// -
case '1':
$vvv[$v3] = ($vvv[$v1] - $vvv[$v2]) % $maxval;
$js_str .= 'v'.$v3.'=(v'.$v1
. '-v'.$v2.')%'. $maxval .';';
break;
// *
case '2':
$vvv[$v3] = ($vvv[$v1] * $vvv[$v2]) % $maxval;
$js_str .= 'v'.$v3.'=(v'.$v1
. '*v'.$v2.')%'. $maxval .';';
break;
// if, >
case '3':
$v4 = rand (1, $maxval - 1);
$js_str .= 'if ( v' . $v1 . ' > '. $v4 . ')
{ v' . $v2 . ' = v' . $v3 . '; }';
if ($vvv[$v1] > $v4)
{
$vvv[$v2] = $vvv[$v3];
}
break;
// if, <
case '4':
$v4 = rand (1, $maxval - 1);
$js_str .= 'if ( v' . $v1 . ' < '. $v4 . ')
{ v' . $v2 . ' = v' . $v3 . '; }';
if ($vvv[$v1] < $v4)
{
$vvv[$v2] = $vvv[$v3];
}
break;
// while
case '5':
$v4 = rand (1, 100);
// Quick and dirty check
if ($v1 == $v2)
break;
$js_str .= 'v'. $v1 .'=Math.abs(v'.$v1.');
v'. $v1 .'%='. $v4 .'; while (v'.$v1.'--) {
v'. $v2.'++; }';
// Calc the final value
$vvv[$v1] = abs ($vvv[$v1]);
$vvv[$v2] += $vvv[$v1] % $v4;
$vvv[$v1] = -1;
break;
}
}
$final_val = 0;
$js_str .= "eElement.value = (";
for ($i = 0 ; $i < $nvars; $i++)
{
if ($i != 0)
{
$js_str .= '+';
}
$js_str .= 'v' . $i;
$final_val += $vvv[$i];
}
$js_str .= ')%'. $maxval.';';
$final_val %= $maxval;
//$js_str .= '// '.$final_val;
// Add the secret quantity
$final_val += $rnd_val;
// Calc the md5 of the value
$md5_value = md5($final_val);
// Write in hidden field
$page = str_replace('<input type="hidden" name="comment_post_ID"',
'<input type="hidden" name="checkpoint" value="spammers_go_home" />
<input type="hidden" name="result_md5" value="'
. $md5_value . '" />
<input type="hidden" id="chk" name="calc_value" value="" />
<input type="hidden" name="comment_post_ID"', $page);
// The form action
$page = str_replace('<form',
'<form onsubmit="go_anti_spam();" ',
$page);
// The jscript
$page = str_replace('</head>', '<script type="text/javascript">
function go_anti_spam()
{
eElement = document.getElementById("chk");
if(!eElement){ return false; }
else
{
'.$js_str.'
return true;
}
}</script></head>', $page);
return $page;
}
function morph_call_output_items() {
ob_start('morph_output_form_items');
}
// Now we set that function up to execute when the wp_head action is called
add_action('wp_head', 'morph_call_output_items');
?>
WP-Morph 1.0
*New version 1.1 here.*
(English version below)
WP-Morph es un plugin anti-spam para WordPress. Características:
* No requiere de ningún "capcha". El usuario no tiene que introducir ningún código extraño ni se entera de nada del proceso
* Se requiere JavaScript en el browser.
* Los Spammers tendrían que interpretar el código JavaScript de la página para poder enviar comentarios. Hasta ahroa no conozco a ningún programa spammer que haya sido capaz de interpretar también el código JavaScript de la página.
Instalación
-----------
* Descarga el fichero ZIP wp-morph.zip y descomprímelo.
* Edita las líneas siguientes de
wp-morph.php
y pon un número al azar. Es importante que ese número sea diferente, ya que será el secreto de tu sitio web que los spammers no sabrán:
/// Put some random value here!!!
// Greater than 0, and less than 1000000
$rnd_val = xxx;
/// Put some random value here!!!
* Copia
wp-morph.php
en el directorio de plugins de WordPress (normalmente WP-ROOT/wp-content/plugins/
).* Ve al menú "Plugins" de la administración de WordPress.
* Activa el plugin "WP-Morph".
¡¡Y ya está!! ¡¡Adios spam!!
Si tienes alguna pregunta/comentario/cuestión, no dudes en contactar conmigo.
English version:
WP-Morph is an anti-spam plugin for WordPress. Features:
* No capcha. The user don't have to enter any additional code.
* JavaScript support required in the browser.
* Spammers would have to interpret the JavaScript in the page to be able to submit comments. As far as I know, no one spammer in the world process a page including the JavaScript.
Installation
------------
* Download and decompress the ZIP file wp-morph.zip.
* Edit the following lines (in wp-morph.php) to put a random value of your own:
/// Put some random value here!!!
// Greater than 0, and less than 1000000
$rnd_val = xxx;
/// Put some random value here!!!
* Copy
wp-morph.php
in the WordPress plugin directory (normally WP-ROOT/wp-content/plugins/
).* Go to the "Plugins" menu of the WordPress Admin console.
* Activate the "WP-Morph" plugin.
That's it!! Bye, bye, spam!!
If you have questions/comments, please contact me.
Ahora sí, el Anti-Spam definitivo para WordPress: WP-Morph
Hoy es muy tarde. Ya mañana explicaré qué he hecho y cómo permite eliminar los spammers. He utilizado como ejemplo el plugin "WP-Hashcash", aunque este, os lo aseguro, es mucho más simple y no hace falta modificar nada de Wordpress: sólo instalar el plugin en el directorio de plugins y activarlo.
Spam: El método ya no es suficiente
La cuestión es que ahora los programas hacen algo que es muy sencillo de hacer: leen la página del post, la analizan, ven los valores de los campos del form, y los rellenan. Así la solución que di de un campo oculto no vale.
Os mantendré informados. A ver si programo algo ahora.
Xorg y Debian
Planet Murcia: ¡¡Primicia mundial!!
Varias otras cosas...

Su Weblog, que ya lo tengo enlazado en los enlaces, digamos que hay que verlo :). Sin duda la noticia que más me impactó fue esta :).
¡¡Ánimo, Monty, gran Weblog!!
Literatura y música

Después, he ido a un concierto de piano a cuatro manos con un programa excelente (sale en la foto). Jeje, obsérvese la metedura de pata del programa: "Piano a dos manos" :) En fin, el caso es que es a cuatro manos :) También aparece en la foto la carpetita del curso de creación literaria.

Por cierto, que se me olvidó añadir que aunque todas las obras fueron muy buenas, sin duda las que más me llegaron fueron las de Falla. Es curioso cómo un espíritu (el español) se puede transmitir también a través de la música. Una cultura, una herencia, un sentir común que nos hace sentir las cosas de forma parecida. Ya lo decía Alex Grijelmo en su "Defensa apasionada del idioma español".
Memoria de España
Me gustaría decirles a todos esos que dicen "la derecha no tiene que ver con Franco". Está claro que todos tenemos una historia y una herencia. Hay gente que pretende obviar esa cuestión. España tiene una historia y una herencia. ¿Cuál es la historia y la herencia de la derecha? Para mí que la gente que apoyó al régimen son la historia y la herencia de la derecha.
Mi abuelo fue republicano. Luchó por la determinación del pueblo y sufrió la persecución y las codenas a muerte. La desidia de una España gobernada por la gente de peor moral del país, apoyada por la Iglesia, que para mí, si cabe es lo más fuerte. ¿Quiere que le tenga respeto a una institución que apoyó a un régimen venido por las armas y después de la guerra?
Patentes de Software
Nedstat, vaya una mierda

¿Bloqueado? ¿Y a cuento de qué? He visto además ya otros contadores a los que le ha pasado lo mismo. Por favor, decidme alternativas a esta patraña.
Actualización: Gracias a náufrago, estoy ahora utilizando Site Meter y va genial.
Cuentos
Ahora estamos estudiando el cuento, y nos mostró uno de Cortázar que me pareció genial. Lo cito aquí junto con la URL de donde lo saqué. Disfrutad...
Continuidad de los parques
Había empezado a leer la novela unos días antes. La abandonó por negocios urgentes, volvió a abrirla cuando regresaba en tren a la finca; se dejaba interesar lentamente por la trama, por el dibujo de los personajes. Esa tarde, después de escribir una carta a su apoderado y discutir con el mayordomo una cuestión de aparcerías volvió al libro en la tranquilidad del estudio que miraba hacia el parque de los robles. Arrellanado en su sillón favorito de espaldas a la puerta que lo hubiera molestado como una irritante posibilidad de intrusiones, dejó que su mano izquierda acariciara una y otra vez el terciopelo verde y se puso a leer los últimos capítulos. Su memoria retenía sin esfuerzo los nombres y las imágenes de los protagonistas; la ilusión novelesca lo ganó casi en seguida. Gozaba del placer casi perverso de irse desgajando línea a línea de lo que lo rodeaba, y sentir a la vez que su cabeza descansaba cómodamente en el terciopelo del alto respaldo, que los cigarrillos seguían al alcance de la mano, que más allá de los ventanales danzaba el aire del atardecer bajo los robles. Palabra a palabra, absorbido por la sórdida disyuntiva de los héroes, dejándose ir hacia las imágenes que se concertaban y adquirían color y movimiento, fue testigo del último encuentro en la cabaña del monte. Primero entraba la mujer, recelosa; ahora llegaba el amante, lastimada la cara por el chicotazo de una rama. Admirablemente restallaba ella la sangre con sus besos, pero él rechazaba las caricias, no había venido para repetir las ceremonias de una pasión secreta, protegida por un mundo de hojas secas y senderos furtivos. El puñal se entibiaba contra su pecho, y debajo latía la libertad agazapada. Un diálogo anhelante corría por las páginas como un arroyo de serpientes, y se sentía que todo estaba decidido desde siempre. Hasta esas caricias que enredaban el cuerpo del amante como queriendo retenerlo y disuadirlo, dibujaban abominablemente la figura de otro cuerpo que era necesario destruir. Nada había sido olvidado: coartadas, azares, posibles errores. A partir de esa hora cada instante tenía su empleo minuciosamente atribuido. El doble repaso despiadado se interrumpía apenas para que una mano acariciara una mejilla. Empezaba a anochecer.
Sin mirarse ya, atados rígidamente a la tarea que los esperaba, se separaron en la puerta de la cabaña. Ella debía seguir por la senda que iba al norte. Desde la senda opuesta él se volvió un instante para verla correr con el pelo suelto. Corrió a su vez, parapetándose en los árboles y los setos, hasta distinguir en la bruma malva del crepúsculo la alameda que llevaba a la casa. Los perros no debían ladrar, y no ladraron. El mayordomo no estaría a esa hora, y no estaba. Subió los tres peldaños del porche y entró. Desde la sangre galopando en sus oídos le llegaban las palabras de la mujer: primero una sala azul, después una galería, una escalera alfombrada. En lo alto, dos puertas. Nadie en la primera habitación, nadie en la segunda. La puerta del salón, y entonces el puñal en la mano. la luz de los ventanales, el alto respaldo de un sillón de terciopelo verde, la cabeza del hombre en el sillón leyendo una novela.
Más spam (qué raro)

De esta figura se pueden sacar varias cosas:
1. Es un bot. (no hay más que ver el número de accesos)
2. Utiliza varios hilos, como se puede comprobar en que unas peticiones de una página y de su post de comentarios llegan desordenadas.
3. Lee completamente las páginas y luego busca en la página el form de enviar comentarios e intenta por todos los medios emular una pulsación de botón humana (esto se ve en que luego vuelve a cargar la página sobre la que envió comentarios).
4. Es un programa que se autoproclama "ai", como el _User Agent_ establece (AIRF, luego buscaré esto en Google, estoy seguro de que a otros muchos le habrán hecho este tipo de scan).
¿Qué hacer? Bueno, en principio tengo que ver si este tipo de ataques se producen más a menudo o si ha sido una cosa al azar. Si es así, tendré que pensar en mejorar el esquema de anti-spam para los comentarios. Puedo pensar también que de alguna manera han visto la fórmula anti-spam que propongo y la han atacado a saco.
Como siempre se me ocurrirá algo :) Además, así tengo algo en qué ocuparme, un puzzle que resolver. No, si al final hasta voy a tener que agradecer a estas caparras de los recursos ajenos :)
¡Qué risa!
The following is a message to all dogs who read The Sneeze: First, sit. Sit! Good boy. Now listen to me. Beggin' Strips do NOT, I repeat, DO NOT TASTE LIKE BACON. You are all being played for chumps! Alright, now give me your paw. Okay, roll over! Good boy! Now go take a steamy dump in your master's shoe. Go on! Get!