Ir para conteúdo
  • Cadastre-se

Pesquisar na Comunidade

Mostrando resultados para as tags ''linux''.



Mais opções de pesquisa

  • Pesquisar por Tags

    Digite tags separadas por vírgulas
  • Pesquisar por Autor

Tipo de Conteúdo


Fóruns

  • Conteúdo Mente Binária
    • Núcleo
    • Projeto Bumerangue
    • Fale com a gente!
  • Comunidade
    • Engenharia Reversa
    • Programação
    • Redes
    • Análise de malware
    • Teste de intrusão
    • Sistemas operacionais
    • Certificações
    • Oportunidades
    • Outros

Categorias

  • Crackmes
  • Documentação
  • Debuggers
  • Ferramentas para PE
  • Utilitários
  • Unpackers

Encontrar resultados em...

Encontrar resultados que...


Data de Criação

  • Início

    FIM


Data de Atualização

  • Início

    FIM


Filtrar pelo número de...

Data de Registro

  • Início

    FIM


Grupo


Website


Github


LinkedIn

Encontrado 6 registros

  1. Fernando Mercês

    Como criar um pacote deb “na unha”

    Aproveitando que farei uma apresentação sobre pacotes deb na comemoração do 18º aniversário do Debian GNU/Linux, decidi escrever este artigo, para mostrar o que é um pacote deb e como ele pode ser gerado de forma quase artesanal. O objetivo deste artigo é mostrar o que é um pacote deb e como ele se comporta. Mostrarei como olhar o conteúdo de um pacote deb a fim de copiar sua estrutura para gerar um novo, coisa que fiz quando comecei a me interessar pelo assunto. Este artigo faz parte de um objetivo maior, que é atrair colaboradores para a comunidade Debian. Um pacote “caseiro” não será aceito nos repositórios oficiais, mas iniciará o leitor no mundo do empacotamento e, quem sabe, despertará o Debian Maintainer que há em você. 1. Introdução Imagine um mundo sem pacotes deb. Todos os softwares livres seriam distribuídos em código-fonte. Você seria obrigado a baixar, compilar e instalar. Fácil? Nem sempre. Os programas possuem dependências de bibliotecas que o desenvolvedor usou. Na máquina dele essas bibliotecas estão instaladas, na sua provavelmente não. Então seria preciso instalá-las antes de compilar o programa que você quer. Claro que os jargões utilizados aqui só fazem sentido para usuários avançados. O Linux não teria conquistado a popularidade que tem hoje se os usuários leigos tivessem que compilar o Firefox para navegar na internet. Os pacotes supriram esta necessidade e hoje um software inteiro com suas dezenas de dependências pode ser instalado graficamente ou com uma curta e simples linha de comando. Cabe aqui um viva ao software livre. o/ Este artigo não é para leigos, mas para quem gostaria de entender como o pacote deb funciona. 2. Pacote “caseiro” x pacote oficial Para fazer um pacote e submetê-lo ao repositório oficial, você precisa ler, compreender e seguir rígidas regras de qualidade, que podem ser encontradas nos documentos oficiais [1]. No entanto, creio que o modo mais fácil é começar por um pacote “caseiro”, que não segue a política, para entender o funcionamento e então partir para o estudo dos documentos. Foi assim que deu certo comigo e hoje mantenho o pacote do pev [2] no repositório oficial (testing). A comunidade Debian oferece uma série de ferramentas para criação de pacotes, sempre com foco nos pacotes oficiais. Neste artigo evitarei usar tais ferramentas, mas vou comentar, para que o leitor já se ambiente. 3. Do que é feito o pacote deb Se você der uma olhada em no diretório /var/cache/apt/archives provavelmente vai encontrar vários pacotes deb. Eles estão lá porque foram baixados por você seja via Synaptic, apt-get, aptitude ou outro gerenciador de pacotes que use o dpkg. Antes de usar o dpkg (a ferramenta oficial) para analisar um pacote deb, vamos ver do que um pacote deb é feito. Escolhi como exemplo o pacote do wget. $ ls -lh wget* -rw-r–r– 1 fernando fernando 717K Aug 17 00:26 wget_1.12-5_amd64.deb Vamos copiar o pacote para o /tmp, para manter o cache intacto: $ cp wget_1.12-5_amd64.deb /tmp No diretório /tmp, podemos usar o comando file para ver o tipo de arquivo do pacote deb: $ cd /tmp $ file wget_1.12-5_amd64.deb wget_1.12-5_amd64.deb: Debian binary package (format 2.0) A libmagic (usada pelo file) reconhece o pacote corretamente. Mas será que os desenvolvedores criaram realmente um tipo de arquivo completamente novo para armazenar o conteúdo de um programa? Sabemos que dentro de um pacote deb há os arquivos executáveis do programa, documentação, ícones etc. Não seria viávei utilizar um agrupador de arquivos com compressão ou coisa do tipo? Eric Raymond, um dos hackers mais respeitados do mundo detém a seguinte crença, escrita em seu documento “How to become a hacker” [3]: “No problem should ever have to be solved twice” (Nenhum problema deve ser resolvido duas vezes). Ou seja, não é preciso “reinventar a roda”, como dizemos popularmente. Com base nesta inteligente frase, os desenvolvedores do dpkg e do formato deb usaram sim o que já exitia para atingir seus objetivos, o que foi brilhante. Na página de manual do formato deb(5), podemos ler: “The file is an ar archive with a magic value of !<arch>.” Para conferir, comande: $ man deb Então estamos falando de um arquivo ar [4]. Conforme você pode ver na referência, ar é um utilitário do conjunto binutils, do projeto GNU, para criar, modificar e extrair arquivos. É um agrupador, assim como o tar. Vamos conferir o magic value como disse o man? $ hd -n 64 wget* 00000000 21 3c 61 72 63 68 3e 0a 64 65 62 69 61 6e 2d 62 |!<arch>.debian-b| 00000010 69 6e 61 72 79 20 20 20 31 33 31 31 34 35 31 34 |inary 13114514| 00000020 35 31 20 20 30 20 20 20 20 20 30 20 20 20 20 20 |51 0 0 | 00000030 31 30 30 36 34 34 20 20 34 20 20 20 20 20 20 20 |100644 4 | Certinho. O tal “!<arch>” esta no início do arquivo, o que sugere ser o seu magic number. Vamos listar o conteúdo deste arquivo com a ferramenta ar então: $ ar tv wget* rw-r–r– 0/0 4 Jul 23 17:04 2011 debian-binary rw-r–r– 0/0 2432 Jul 23 17:04 2011 control.tar.gz rw-r–r– 0/0 731281 Jul 23 17:04 2011 data.tar.gz Então temos um arquivo ar com três arquivos. E se criarmos um ar com um arquivo qualquer, o que será que o file retorna? $ echo “meu texto” > texto.txt $ ar r teste.deb texto.txt ar: creating teste.deb O comando acima criou um arquivo ar chamado teste.deb (lembre-se que o Linux despreza extensões) e adicionou o arquivo texto.txt nele. $ file teste.deb teste.deb: current ar archive O file retorna que é um arquivo ar, corretamente. Mas por que o file reconhece como pacote do wget corretamente como binário do debian? A resposta está no código-fonte do file [5], que identifica um pacote binário se depois do magic number do ar, o arquivo contiver a string “debian-binary”. De fato, o formato ar define o magic e o nome do primeiro arquivo agrupado em seguida. Então bastaria que criássemos um arquivo ar com um arquivo debian-binary qualquer para o “enganar” o file. $ echo 2011 > debian-binary $ ar r fake.deb debian-binary ar: creating fake.deb $ file fake.deb fake.deb: Debian binary package (format 2011) Agora sim. O file não faz nenhuma verificação adicional (e nem deveria). Mas a intenção aqui não é hackear o file (até porque estamos falando de um formato livre, com extensa documentação), e sim criar um deb “na mão”. Perceba que o formato apareceu como “2011”. Claro que é um pacote inválido e se você tentar instalar o dpkg vai gerar um erro. Nem perca seu tempo. 4. Extraindo um pacote deb Voltando ao que interessa, vamos extrair o conteúdo do pacote deb do wget para conferir o que há de interessante: $ mkdir wget $ cd wget $ ar xv ../wget* x – debian-binary x – control.tar.gz x – data.tar.gz $ cat debian-binary 2.0 Exatamente o que o file informou. Versão 2.0 do formato deb. Beleza. $ tar tvzf control.tar.gz drwxr-xr-x root/root 0 2011-07-23 17:04 ./ -rw-r–r– root/root 3832 2011-07-23 17:04 ./md5sums -rw-r–r– root/root 12 2011-07-23 17:04 ./conffiles -rw-r–r– root/root 1327 2011-07-23 17:04 ./control Acima vemos alguns arquivos de controle do pacote. O interesse maior é no arquivo “control”, necessário para um pacote funcionar. O md5sums também é legal de se ter. $ tar tvzf data.tar.gz <saída suprimida=””> -rw-r–r– root/root 651 2009-09-21 23:52 ./usr/share/doc/wget/ChangeLog.README drwxr-xr-x root/root 0 2011-07-23 17:04 ./usr/bin/ -rwxr-xr-x root/root 353824 2011-07-23 17:04 ./usr/bin/wget Já o data.tar.gz contém os dados do pacote em si, incluindo binários executáveis e documentação, todos numa estrutura bem definida. Aliás, é esta estrutura que o pacote cria ao ser instalado. Estou mais interessado no control.tar.gz. Vamos extraí-lo: $ tar xvzf control.tar.gz ./ ./md5sums ./conffiles ./control $ head -5 md5sums 1b2acae8540b64a3170dc4ce0200809e usr/bin/wget d62b0aafbbacf1d54031ded4d1a5f232 usr/share/doc/wget/AUTHORS 2f58d6d92cabcf358718a564d3e132d4 usr/share/doc/wget/ChangeLog.README 2b95a82f1c7499025d67ff86af2d7ecd usr/share/doc/wget/MAILING-LIST 9e83cee67a496f5eb62aecf283e14367 usr/share/doc/wget/NEWS.gz Certo, vemos no arquivo md5sums, o hash MD5 de cada arquivo incluso no data.tar.gz (no entanto só imprimi 5 linhas com o head). Não seria difícil gerar isso para o nosso pacote “artesenal”. $ cat control Package: wget Version: 1.12-5 Architecture: amd64 Maintainer: Noël Köthe Installed-Size: 2344 Depends: libc6 (>= 2.3), libidn11 (>= 1.13), libssl1.0.0 (>= 1.0.0), dpkg (>= 1.15.4) | install-info Conflicts: wget-ssl Section: web Priority: important Multi-Arch: foreign Homepage: http://www.gnu.org/software/wget/ Description: retrieves files from the web Wget is a network utility to retrieve files from the web using HTTP(S) and FTP, the two most widely used internet protocols. It works non-interactively, so it will work in the background, after having logged off. The program supports recursive retrieval of web-authoring pages as well as ftp sites — you can use wget to make mirrors of archives and home pages or to travel the web like a WWW robot. . Wget works particularly well with slow or unstable connections by continuing to retrieve a document until the document is fully downloaded. Re-getting files from where it left off works on servers (both HTTP and FTP) that support it. Both HTTP and FTP retrievals can be time stamped, so wget can see if the remote file has changed since the last retrieval and automatically retrieve the new version if it has. . Wget supports proxy servers; this can lighten the network load, speed up retrieval, and provide access behind firewalls. Este é o arquivo que descreve o pacote. A referência deste arquivo é tratada na Debian Policy [6], mas os campos mais comumente usados para pacotes simples são: Package – Nome do pacote Version – Versão do programa-versão do pacote Architecture– Arquitetura para qual o programa foi compilado. Pode ser i386, amd64, dentre outras. Pode ser “all” para scripts, por exemplo. Maintainer – Aqui vai o seu nome e e-mail. O criador do pacote (não do programa a ser empacotado). Installed-Size – O espaço estimado, em bytes, requerido para instalar o pacote. Depends – Os pacotes dos quais seu pacote depende. Se for um programa em Python, vai depender do interpretador python, por exemplo. Homepage – O site do programa empacotado Description-A descrição do pacote. Uma linha para a descrição curta e demais para descrição longa, onde todas devem começar com um espaço e as linhas em branco devem possuir um ponto (.), que não vai aparecer no final das contas. Agora que já explicamos a estrutura de um pacote deb básico, vamos ver como criar um. 5. Criando um pacote “artesanal” Precisamos ter o que empcotar. Então vamos criar um software de teste. $ mkdir /tmp/nada-1.0 $ cd /tmp/nada-1.0 $ echo -e “#include <stdio.h>nnint main()n{ntputs(“nada…”);ntreturn 0;n}” > nada.c Os comandos acima devem criar um arquivo nada.c, no diretório /tmp/nada-1.0, com o seguinte conteúdo: #include <stdio.h> int main() { puts(“nada…”); return 0; } Agora precisamos compilar o programa: $ gcc -o nada nada.c O binário “nada” precisa de uma estrutura. Então vamos colocá-lo num usr/bin: $ mkdir -p usr/bin $ mv nada usr/bin/ NOTA: Cuidado para não tentar mover o “nada” para o /usr/bin do sistema. Agora temos a seguinte estrutura: $ find . . ./usr ./usr/bin ./usr/bin/nada ./nada.c Precisamos do arquivo de controle. Que tal este? Package: nada Version: 1.0 Architecture: amd64 Maintainer: Você <seu@email.com.br> Homepage: http://www.tacomnada.com Installed-Size: 6560 Depends: libc6 (>= 2.2.5) Description: program that does nothing Na realidade o nada conseguie imprimir a string “nada…” na tela. Claro que pode servir para algo, mas nao saberia dizer para que. Talvez para aprender a empacotar no Debian, ou para nao fazer nada. . Depois de falar tanto, nao vou dizer mais nada. Basta salvar como control (sem extensão mesmo). Para o campo Installed-Size, eu contei os bytes do binário “nada”: $ wc -c nada 6560 nada Já no campo Depends, é interessante avaliar a saída do ldd: $ ldd nada linux-vdso.so.1 => (0x00007fffea5ff000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcebbf5d000) /lib64/ld-linux-x86-64.so.2 (0x00007fcebc2fe000) A primeira entrada é a uma biblioteca virtual para interface com o kernel. Ela sempre existirá e também pode aparecer como linux-gate.so.1. Em seguida temos duas bibliotecas reais. Supondo que não saibamos em qual pacote elas se encontram, podemos usar o apt-file: $ apt-file search libc.so.6 libc6: /lib/x86_64-linux-gnu/libc.so.6 libc6-i386: /lib32/libc.so.6 O pacote de nosso interece é o libc6. Agora, a versão da biblioteca requerida vai depender das funções que o programador utilizou. Isto consultado ser pego no site do projeto ou diretamente com o desenvolvedor. Usei 2.2.5. Vamos buscar a última lib que o ldd detectou: $ apt-file search ld-linux-x86-64.so.2 libc6: /lib/ld-linux-x86-64.so.2 libc6: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 Também está no pacote libc6. Beleza, então só temos esta dependência. Agora precisamos gerar os arquivos control.tar.gz (com o control dentro), data.tar.gz (com toda a árvode usr dentro) e debian-binary (com a string 2.0 dentro): $ tar cvzf data.tar.gz usr/ usr/ usr/bin/ usr/bin/nada $ tar cvzf control.tar.gz control control $ echo 2.0 > debian-binary $ ar r nada-1.0_amd64.deb debian-binary control.tar.gz data.tar.gz ar: creating nada-1.0_amd64.deb fernando@localhost:/tmp/wget/nada-1.0$ file nada-1.0_amd64.deb nada-1.0_amd64.deb: Debian binary package (format 2.0) Perceba que o primeiro arquivo a ser adicionado no ar é o debian-binary. E agora vamos testar. $ sudo dpkg -i nada-1.0_amd64.deb Selecting previously deselected package nada. (Reading database … 146331 files and directories currently installed.) Unpacking nada (from nada-1.0_amd64.deb) … Setting up nada (1.0) … $ nada nada… $ sudo dpkg -P nada (Reading database … 146332 files and directories currently installed.) Removing nada … 6. Conclusão O pacote funciona. Inclusive eu fiz um script (makedeb_v2.sh) para empacotar [quase que] desta forma o Evan’s Debugger [7]. Vale a pena dar uma olhada, pois tem outros arquivos e comandos que não mencionei aqui. No entanto, ressalto que a preferência deve ser para pacotes com alta qualidade. Provavelmente escreverei um outro artigo sobre a forma correta de se criar pacotes, com base na política do Debian e com as ferramentas providas pela comunidade. Não é fácil fazer um pacote de qualidade, mas o primeiro passo, na minha opinião, é entender com o que estamos lidando e espero que este artigo tenha atingido este objetivo. [1] http://www.debian.org/doc/#manuals [2] http://packages.debian.org/wheezy/pev [3] http://catb.org/~esr/faqs/hacker-howto.html#believe2 [4] http://www.gnu.org/s/binutils/ [5] ftp://ftp.astron.com/pub/file/ [6] http://www.debian.org/doc/debian-policy/ch-controlfields.html [7] http://codef00.com/projects#debugger
  2. Fernando Mercês

    Extraindo dados de dumps

    1. Introdução Dumps de memória, discos ou arquivos binários em geral podem conter outros arquivos dentro. Por exemplo, um arquivo TAR (agrupado, sem compactação) praticamente concatena vários arquivos e um só. O arquivo resultante contém todos os bytes dos arquivos de entrada e mais algumas informações que o formato TAR exige. O mesmo acontece com dumps feitos de memória gerados com software de cópia bit a bit, como o dd, parte integrante do coreutils [1], do projeto GNU. Estes podem, e geralmente é que acontece, conter vários arquivos de diferentes tipos. Neste artigo mostrarei uma forma manual, usando ferramentas básicas, para extrair dados de dentro destes dumps. Ao ministrar um dos cursos de segurança na 4Linux, gerei este desafio: O objetivo é extrair dados válidos de um dump de 1 MB fornecido. Dentro dele, há dois arquivos. Não sabemos que tipo de arquivo há dentro do dump, então temos que procurar. NOTA: Este texto é didático e você pode seguir utilizando uma máquina com Linux para fazer a análise do dump. Basta baixar o binário dump.bin. 2. Como procurar tipos de arquivo Antes de tudo, é preciso saber o que se vai procurar. Você pode querer procurar milhares de tipos diferentes, mas terá que conhecer o formato de cada um deles para identificar possíveis bytes dentro do dump. Neste artigo vamos buscar por arquivos BMP e GIF mas este texto pode servir de guia para buscar qualquer tipo. Para isso precisamos estudar o a especificação de cada formato. Este tipo de documento quem fez é o desenvolvedor do formato e é particularmente interessante para desenvovledores de software que trabalharão com imagens como editores, visualizadores, browsers etc. A Wikipedia é uma ótima fonte para isso, mas o site dos consórcios que desenvolvem e mantêm os padrões também podem ser utilizados. Basta googlar por “<extensão> file format” e você achará muitos links. 3. Analisando a especificação do bitmap (BMP) Para o nosso interesse, que não é desenvolver um aplicativo que trabalhe com o formato, mas sim entender o básico do formato, a parte mais interessante está na estrutura de um arquivo bitmap [2], onde cada grupo de bytes de um arquivo deste tipo ganha um significado. O que queremos é saber os bytes que definem o início de um arquivo bitmap. Em outras palavras, queremos saber que bytes estão no cabeçalho (header) de um arquivo bitmap. Veja que na especificação consta: “the header field used to identify the BMP & DIB file is 0x42 0x4D in hexadecimal, same as BM in ASCII” Achamos. Isso nos leva a crer que um bitmap tradicional começa com os bytes 0x42 e 0x4d, o mesmo que BM em ASCII. Sabendo disso podemos checar as strings dentro de nosso dump e fazer um filtro pela string “BM”, certo? 3.1 Buscando a string que identifica um bitmap Para isso, nada mais indicado que o strings, do conjunto binutils [3], também do projeto GNU (thanks FSF!). $ strings -t x dump.bin | grep BM 6ae6d BMP& 8f699 g,UBM_ be081 ?O~BMY ed589 YBMG f63c2 xBM5 A opção “-t x” do strings faz com que ele imprima os endereços (posições) em hexa das strings que encontrou. NOTA: Já se perguntou como funciona o strings? Uma ideia é ler cada byte e testar se este é imprimível, ou seja, tem representação gráfica na tabela ASCII. Caso seja imprimível, só mandar pra tela. Um código de exemplo seria: #include <stdio.h> #include <string.h> int main(int argc, char *argv[1]) { unsigned char byte; FILE *fp = fopen(argv[1], “rb”); while (fread(&byte, sizeof(unsigned char), 1, fp)) putchar(isprint(byte) ? byte : ‘n’); fclose(fp); } Código apenas para fins didáticos. Precisaria de melhorias se fosse usado pra valer. De acordo com a saída do strings, parece que temos 5 bitmaps dentro deste arquivo. Será? Na verdade não podemos garantir. Os bytes referentes aos caracteres ‘B’ e ‘M’ podem ser parte de outro arquivo, de uma música, de um texto ou simplesmente parte de uma instrução de algum programa. Não pode-se garantir que é um bitmap. Temos que analisar! 3.2 Analisando a primeira ocorrência da string BM Sabemos a posição da primeira ocorrência porque o comando strings nos deu. Agora vamos usar um visualizador hexa/ascii para ver o que há próximo destes bytes. No conjunto coreutils há o od, mas eu estou acostumado ao hexdump (hd), do BSD: $ hd -s 0x6ae6d -n 32 dump.bin 0006ae6d 42 4d 50 26 bf 29 c1 f3 f3 81 f0 99 aa f0 aa fd |BMP&.)……….| 0006ae7d d3 d1 e0 3e 92 54 84 b1 18 74 4e b5 00 c1 ce 06 |…>.T…tN…..| A opção “-s 0x6ae6d” faz com que o hd pule (skip) essa quantidade de bytes a partir do início do arquivo, caindo diretamente em nossa string. Já a opção “-n 32” faz com que o hd mostre apenas bytes à frente. Só estamos dando uma olhada, não precisamos ver o arquivo inteiro neste momento. A documentação também diz que os próximos 4 bytes de um bitmap representam o tamanho do arquivo em bytes. Então o tamanho da nossa *possível* imagem seriam os 4 bytes “50 26 bf 29”. Organizando-dos em little-endian (de trás para frente) pois estes representam um número inteiro e não texto, temos 0x29bf2650. Quanto dá isso em decimal? O bash responde: $ echo $((0x29bf2650)) 700393040 O bc também responderia (mas as letras precisam estar em maiúsculo): $ echo “ibase=16;29BF2650” | bc 700393040 Quanto dá isso em megabytes? $ echo $((0x29bf2650 / 1024 / 1024)) 667 Então nosso provável bitmap tem mais de 700 milhões de bytes, aproximadamente 667 MB. Impossível para um dump de 1 MB, certo? Descartado… esses bytes não fazem parte de um bitmap e foi somente coincidência a string “BM”, ainda mais seguida de um “P” (eu fiz isso sem querer hehe). Deixarei para o leitor analisar as outras ocorrências da string “BM”. Vá se divertir! 4. Buscando a string que identifica um GIF Agora vamos buscar GIF. Assim como fizemos com o bitmap, vamos olhar a especificação do GIF [4]. De cara, vemos o header da última versão do formato, que deve ser composto pelos bytes 0x47 0x49 0x46 0x38 0x39 0x61, que representam em ASCII a string “GIF89a”. Se quiser confirmar, pode usar o comando ascii do Linux: $ sudo apt-get install ascii $ ascii Então vamos ao grep: $ strings -t x dump.bin | grep GIF89a 80000 GIF89ae Opa, casamos com a string inteira. Seria muita coincidência esses 6 caracteres casarem se isso não for o início de um GIF? Não sei. Vamos analisar: $ hd -s 0x80000 -n 64 dump.bin 00080000 47 49 46 38 39 61 65 01 1a 02 f7 00 00 bb 9c 91 |GIF89ae………| 00080010 6e 5b 54 d9 ad 9c 6b 69 69 ca a4 94 e3 8c 7d 3f |n[T…kii…..}?| 00080020 1e 0e 33 0d 09 f6 cb ba e1 b4 a3 e3 bb aa eb ca |..3………….| 00080030 8a c8 44 39 0b 05 04 6b 26 21 44 27 19 fa f2 e4 |..D9…k&!D’….| A documentação diz que depois do header de 6 bytes, temos 2 bytes identificando a largura (0x165) e mais 2 para a altura (0x21a), o que definiria um GIF de 357×538 pixels. Aceitável… O próximo byte, segundo o exemplo na documentação, quando é 0xf7, diz que o GIF tem 256 cores, dentre outras informações. Este byte bate com o nosso 0xf7. Parece mesmo ser um GIF… Vamos testar se é um GIF mesmo? Não precisamos ir até o final checando todos os campos. A maioria dos formatos de arquivo definem um ou mais bytes para marcar o fim do arquivo. No caso do GIF, veja na documentação que os últimos bytes são 0x00 (end) e 0x3b (GIF terminator). Lembre-se que isso é *específico* do formato GIF e não é regra para qualquer tipo de arquivo. Cada um tem seu formato. NOTA: Os formatos que não possuem bytes que marcam o fim geralmente possuem um campo que diz o tamanho completo do arquivo, como vimos no bitmap. 4.1 Estratégia para extrair o possível GIF do dump Podemos usar a estratégia de extrair os bytes desde o ‘G’ do “GIF89a” até a primeira sequência 0x00 0x3b. Se for um GIF real, funcionaria, concorda? Vamos buscar então: $ hd -s 0x80000 dump.bin | grep –color “00 3b” 00082b60 3d 97 87 80 00 00 3b 55 d9 60 ab 23 eb 24 ac f1 |=…..;U.`.#.$..| 000ef4e0 2b 61 8d 77 00 3b 7c 58 62 23 4a dc 4c 15 42 da |+a.w.;|Xb#J.L.B.| A primeira sequência que “00 3b” que o grep encontrou após o offset 0x80000 (início do GIF) está em 0x82b65, conseguiu visualizar? É só ir somando 1 em hexa, para cada byte. Neste offset está o 0x00 e em 0x82b66 está o 0x3b. Seguindo nossa teoria, o próximo byte, 0x55 em 0x82b67 não faz parte do GIF. Se diminuirmos este valor de 0x80000, teremos o tamanho total do suposto GIF. Vamos ver: $ echo $((0x82b67-0x80000)) 11111 A resposta é em decimal. Só lembrando algumas informações que leventamos: Tipo: GIFResolução: 357×538 pixelsTamanho: 11111 bytes (11 KB) 4.2 Extração com o dd Se estivermos certo, veremos um GIF quando extrairmos esses bytes. Para isso, podemos usar o dd: $ dd if=dump.bin of=possivel.gif bs=1 count=11111 skip=$((0x80000)) 11111+0 registros de entrada 11111+0 registros de saída 11111 bytes (11 kB) copiados, 0,036675 s, 303 kB/s A opção bs (block size) informa ao dd para assumir blocos de 1 byte. A opção count diz quantos blocos ele vai ler, então vão dar exatamente 11111 bytes. E por fim a opção skip, que só aceita números em decimal (por isso a conversão com o bash) informa quantos bytes o dd vai pular para começar a ler, assim como a opção “-s” do hd. Temos que começar a extração do byte 0x80000, que é onde começa o GIF, lembra? Vamos conferir: $ file possivel.gif possivel.gif: GIF image data, version 89a, 357 x 538 $ wc -c possivel.gif 11111 possivel.gif Agora é só visualizar… 5. Ferramentas para automatizar o trabalho Agora a notícia chata depois que você leu tudo isso: existem ferramentas que fazem tudo isso de maneira automatizada. Uma delas é o foremost [5], que conhece vários tipos de arquivo e é capaz de extrair com precisão a partir de dumps como este. No entanto, considero que mais importante que conhecer ferramentas é saber como elas funcionam e/ou como fazer as coisas sozinho. Sem elas. Say no to script kiddies! 6. Referências A ilustração utilizada neste artigo foi gentilmente cedida por Anderson Barros [6] e seu uso foi autorizado. [1] http://www.gnu.org/software/coreutils/ [2] http://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header [3] http://www.gnu.org/software/binutils/ [4] http://en.wikipedia.org/wiki/Graphics_Interchange_Format#Example_GIF_file [5] http://foremost.sourceforge.net/ [6] http://anderson-barros.blogspot.com
  3. Fernando Mercês

    Desativando LD_PRELOAD no Linux

    O preloading é um recurso suportado pelo runtime loader de binários ELF implementado na glibc (GNU C Library), mais especificamente no arquivo rtld.c. Ele consiste em carregar uma biblioteca antes de todas as outras durante o carregamento de um programa executável. Assim é possível injetar funções em programas, inspecionar as funções existentes, etc. Por exemplo, considere o programa ola.c abaixo: #include <stdio.h> void main() { printf("ola, mundo do bem!"); } Ao compilar e rodar, a saída é conforme o esperado: $ gcc -o ola ola.c $ ./ola ola, mundo do bem! A função printf() foi utilizada com sucesso pois este binário foi implicitamente linkado com a glibc graças ao gcc. Veja: $ ldd ola linux-vdso.so.1 (0x00007ffe4892b000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8a3a2dd000) /lib64/ld-linux-x86-64.so.2 (0x00007f8a3a692000) E portanto a função printf() é resolvida. Até aí nenhuma novidade. Agora, para usar o recurso do preloading, temos que criar uma biblioteca, que será carregada antes da glibc (libc6). A ideia é fazer com o que o binário chame a nossa printf() e não a da glibc. Isso pode ser chamado de usermode hook (incompleto, porém, já que eu repassei o argumento para a função puts() ao invés da printf() original da glibc). Considere o código em hook.c: #include <stdio.h> int printf(const char *format, ...) { puts("hahaha sua printf tah hookada!"); return puts(format); } O protótipo da printf() é o mesmo do original (confira no manual). Eu não reimplementei tudo o que precisaria para ela aqui, somente o básico para ajudar na construção do artigo. E como expliquei antes, o hook não está completo uma vez que eu passo o que recebo na minha printf() para a função puts() da glibc. O ideal seria passar para a printf() original mas para isso eu precisaria buscar o símbolo, declarar um ponteiro de função, etc. E o assunto desde artigo não é hooking de funções. Por hora vamos compilar a biblioteca: $ gcc -shared -fPIC -o hook.so hook.c $ ldd hook.so linux-vdso.so.1 (0x00007ffffadb8000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f011dfbc000) /lib64/ld-linux-x86-64.so.2 (0x00007f011e572000) E agora precisamos instruir o loader a carregá-la antes de todas as outras quando formos executar o nosso programa (ola). Há pelo menos duas formas de acordo com a documentação oficial: Definir uma variável de ambiente LD_PRELOAD contendo o endereço de uma ou mais bibliotecas para serem carregadas. Colocar o path de uma ou mais bibliotecas num arquivo /etc/ld.so.preload (caminho e nome são fixos aqui). Então vamos testar. Primeiro uma execução normal, depois com a variável LD_PRELOAD setada e finalmente com o recurso do arquivo /etc/ld.so.preload: ## Execução normal $ ./ola ola, mundo do bem! ## Com caminho em variável de ambiente $ export LD_PRELOAD=$PWD/hook.so $ ./ola hahaha sua printf tah hookada! ola, mundo do bem! ## Com caminho em arquivo $ unset LD_PRELOAD # echo $PWD/hook.so > /etc/ld.so.preload $ ./oi hahaha sua printf tah hookada! hello world Percebe o perigo? Não é à toa que existem vários malware para Linux utilizando este recurso. Alguns exemplos são os rootkits Jynx, Azazel e Umbreon. Além disso, algumas vulnerabilidades como a recente CVE-2016-6662 do MySQL dependem deste recurso para serem exploradas com sucesso. É razoável então um administrador que não utilize este recurso num servidor em produção querer desabilitá-lo, certo? Desabilitando o preloading Não há mecanismo no código em questão da glibc que permita desabilitar este recurso. Pelo menos eu não achei. Uma saída é alterar os fontes e recompilar, mas a glibc demora tanto pra ser compilada que eu desisti e optei por fazer engenheira reversa no trecho necessário e verificar quão difícil seria um patch. Analisando o fonte do rtld.c fica fácil ver que a função do_preload() retorna o número de bibliotecas a serem carregadas no preloading. Primeiro a checagem é feita na variável de ambiente LD_PRELOAD: O número de bibliotecas é armazenado na variável npreloads., que mais tarde alimenta uma repetição para de fato carregar as bibliotecas. Mais abaixo, o vemos que o trecho de código que busca o arquivo /etc/ld.so.preload também usa a do_preload(): Sendo assim veio a ideia de encontrar essa função no loader (no meu caso /lib64/ld-linux-x86-64.so.2 – mas pode estar em /lib para sistemas x86 também) e patchear lá diretamente. PS.: Apesar de o código ser parte da glibc, a biblioteca do loader é compilada separadamente e tem um nome tipo ld-linux-$ARCH.so.2, onde $ARCH é a arquitetura da máquina. No meu caso, x86-64. Fiz uma cópia do arquivo /lib64/ld-linux-x86-64.so.2 para o diretório $HOME para começar a trabalhar. Pelo visto ela é compilada sem os símbolos, o que elimina a hipótese de achar a função por nome de forma fácil: $ nm ld-linux-x86-64.so.2 nm: ld-linux-x86-64.so.2: no symbols Sem problemas. Com o HT Editor, um editor de binários com suporte a disassembly, abri o arquivo e busquei pela string “/etc/ld.so.preload” já que ela é fixa na função, que deve referenciá-la. A ideia foi chegar no trecho de código que chama a função do_preload(). Os passos são: Abrir a biblioteca no hte: $ hte ld-linux-x86-64.so.2 No hte, facilita se mudarmos o modo de visualização para elf/image com a tecla [F6]. Depois é só usar [F7] para buscar pela string ASCII /etc/ld.so.preload: Após achar a string percebemos que ela é referenciada (; xref) em 4 lugares diferentes. Um desses trechos de código também deve chamar a função do_preload() que é a que queremos encontrar. Depois de analisar cada um deles, percebemos que tanto na r4294 quando na r4302 logo depois da referência à string tem uma CALL para uma função em 0xae0 que ao seguir com o hte (apertando [ENTER] no nome dela) é mostrada abaixo: Se comparamos com o código da função do_preload() vemos que se trata dela: A ideia é forçar que ela retorne 0, assim quando ela for chamada seja pelo trecho de código que carrega as bibliotecas a partir da variável LD_PRELOAD ou pelo trecho responsável por ler o arquivo /etc/ld.so.preload, ela vai sempre retornar 0 e vai fazer com que o loader não carregue as bibliotecas. Para isso, desça até o trecho de código do salto em 0xb37. Perceba que ele salta para 0xb56 onde o registrador EAX é zerado com um XOR, e depois o registrador AL (parte baixa de AX, que por sua vez é a parte baixa de EAX) é setado para 1 pela instrução SETNZ caso a condição em 0x58 não seja atendida (linha 675 no código-fonte). Só precisamos fazer com que esta instrução SETNZ em 0xb5e não seja executada para controlar o retorno da função. Ao pressionar [F4], entramos no modo de edição. Há várias maneiras de fazer com que esta instrução em 0xb5e não execute, mas vou fazer a mais clássica: NOPar seus 3 bytes. No modo de edição, substitua os bytes da instrução SETNZ AL (0f 95 c0) por 3 NOP’s (90 90 90), ficando assim: Dessa forma, o EAX é zerado em 0xb56, a comparação ocorre em 0xb58 mas ele não é mais alterado, tendo seu conteúdo zerado até o retorno da função. [F2] para salvar. Agora para testar vou usar duas técnicas combinadas. A primeira é de declarar uma variável de ambiente só para o contexto de um processo. A outra é de usar o loader como se fosse um executável (sim, ele pode receber o caminho de um binário ELF por parâmetro!). Veja: $ LD_PRELOAD=$PWD/hook.so ./ld-linux-x86-64.so.2 ./ola Inconsistency detected by ld.so: rtld.c: 1732: dl_main: Assertion `i == npreloads' failed! Para nosso azar, o loader checa o número de funções a serem carregadas dentro de uma repetição, fora da função do_preload(). Precisamos achar essa confirmação (assertion) para patchear também. Usando a mesma técnica de buscar pela string primeiro (nesse caso busquei pela string “npreloads” exibida no erro) você chega na referência r3148: Que te leva diretamente para a repetição da assert(): Comparando com o fonte: Para o salto em 0x3134 sempre acontecer e a CALL de erro em 0x3154 não executar, resolvi patchear a instrução JZ para que sempre pule para 0x2d60. No modo de edição dá pra ver que há um JMP negativo (salto para trás) em 0x315f de 5 bytes, conforme a figura: Podemos usá-lo só para copiar o opcode. Como em 0x3134 temos 6 bytes, NOPamos o primeiro e copiamos o opcode do JMP negativo (que é 0xe9), ficando assim: Após salvar e testar, voilà: ## Com variável de ambiente $ LD_PRELOAD=$PWD/hook.so ./ld-linux-x86-64.so.2 ./ola ola, mundo do bem! ## Com arquivo # echo $PWD/hook.so > /etc/ld.so.preload $ ./ld-linux-x86-64.so.2 ./ola ola, mundo do bem! Agora se você for bravo o suficiente é só substituir o loader original para desativar completamente o recurso de preloading e ficar livre de ameaças que abusam dele. Fica também o desafio para quem quiser automatizar este processo de alguma maneira e/ou trabalhar na versão de 32-bits do loader. O Matheus Medeiros fez um script maneiro para automatizar o patch! Valeu, Matheus! Patches de código e recompilação seriam melhores opções, de fato, mas quis mostrar uma maneira usando engenharia reversa por três motivos: Se automatizada, pode ser mais fácil de ser colocada em prática em um ambiente em produção. Recompilar a glibc demora muito. Se alguém souber de uma maneira de recompilar somente o loader, por favor, me avise! Engenharia Reversa é divertido.
  4. Fernando Mercês

    Como hookei a execve() em x86-64 num LSM

    Este foi um problema que tive há bastante tempo, quando precisei fazer com que o módulo de kernel do antivírus Trend Micro ServerProtect funcionasse em versões de 64-bit do Linux. Acontece que este módulo utiliza o LSM (Linux Security Module) framework. Até aí tudo bem, foi como o jeito que programadores do módulo usaram para hookar a execve() nesta arquitetura, essencial para um antivírus por motivos óbvios: toda vez que um arquivo fosse executado no sistema, este seria escaneado por vírus. Apesar de um pouco defasado, decidi escrever agora pois me animei quando fui ao 11º Encontro da comunidade C/C++ Brasil [3]. De fato, atualmente um LSM não pode mais ser carregado num kernel rodando, como um LKM (Loadable Kernel Module) e isso tira toda a praticidade deste patch em específico, mas a técnica utilizada pode ser útil em outras ocasiões. Ou não. Indo direto ao ponto, a estrutura default_security_ops não era mais acessível diretamente na versão do kernel que trabalhei e por isso o seguinte trecho de código não funcionava num contexto LSM: unsigned long addr = kallsyms_lookup_name("default_security_ops"); Minha intenção não era reescrever todo o módulo, então tive que dar um jeito rápido. A ideia foi buscar uma função exportada que manipulasse a estrutura default_security_ops, assim eu teria acesso ao endereço dela. Várias funções o fazem, mas buscando pela mais simples/menor encontrei a reset_security_ops(), presente em security/linux.c: void reset_security_ops(void) { security_ops = &default_security_ops; } Essa função só faz uma coisa: coloca o endereço da estrutura que quero em outra. Sendo assim, é uma perfeita candidata para minha gambiarra. Pelo tamanho daria para tentar advinhar quão distante está o endereço da estrutura default_security_ops do endereço da função reset_security_ops(), mas vamos disassemblar só pra garantir: 1. Extraindo a imagem do kernel O kernel fica comprimido em /boot e no próprio fonte existe um script para descomprimi-lo chamado extract-vmlinux. Usei da seguinte maneira: $ sudo cp /boot/vmlinuz-$(uname -r)-generic vmlinuz # trabalhar com um backup, só pra garantir ;) $ sudo chown $(whoami): vmlinuz $ /usr/src/linux-headers-$(uname -r)/scripts/extract-vmlinux vmlinuz > vmlinux O arquivo vmlinux (com “x” ao invés de “z”) criado é a imagem descomprimida do kernel, que precisamos disassemblar. 2. Disassemblando a imagem Por padrão a imagem do kernel não contém símbolos, então minha tentativa com o gdb foi frustrada: $ gdb -q ./vmlinux Reading symbols from ./vmlinux...(no debugging symbols found)...done. (gdb) disassemble reset_security_ops No symbol table is loaded. Use the "file" command. Mas nem tudo está perdido. No kernel rodando, dá pra ver o endereço das funções no arquivo System.map: # grep reset_security_ops /boot/System.map-$(uname -r) ffffffff812d6be0 T reset_security_ops Sabendo o endereço, voltei ao gdb e pedi pra printar 8 intruções começando neste endereço, mas não antes de setar a sintaxe para Intel. (gdb) set disassembly-flavor intel (gdb) x/8i 0xffffffff812d6be0 0xffffffff812d6be0: call 0xffffffff81731480 0xffffffff812d6be5: push rbp 0xffffffff812d6be6: mov QWORD PTR [rip+0xcdd14f],0xffffffff81c80100 # 0xffffffff81fb3d40 0xffffffff812d6bf1: mov rbp,rsp 0xffffffff812d6bf4: pop rbp 0xffffffff812d6bf5: ret 0xffffffff812d6bf6: nop WORD PTR cs:[rax+rax*1+0x0] 0xffffffff812d6c00: call 0xffffffff81731480 (gdb) Essa call no início apontar para um ret e honestamente eu não sei por que ela existe: (gdb) x/i 0xffffffff81731480 0xffffffff81731480: ret 3. Contando os bytes Lembrando que esta função simplesmente implementa a atribuição do endereço que queremos (default_security_ops) para uma variável, fica fácil perceber que a varíavel (security_ops) é RIP+0xcdd14f e o endereço da estrutura que queremos é 0xffffffff81c80100. Mas claro, a ideia aqui é fazer de forma genérica, então não posso trabalhar com esse endereço fixo. Bem, admitindo que essa função não mude, é razoável dizer que o endereço é um número de 64-bits que tem seu primeiro byte em uma posição fixa a partir do endereço da função reset_security_ops(). Isto está longe de ser uma solução profissional, mas resolveu meu problema na época. Ao invés do x/i (examine as instruction), vou usar o disassemble pra poder contar melhor os bytes: (gdb) disassemble /r 0xffffffff812d6be0, 0xffffffff812d6bff Dump of assembler code from 0xffffffff812d6be0 to 0xffffffff812d6bf4: 0xffffffff812d6be0: e8 9b a8 45 00 call 0xffffffff81731480 0xffffffff812d6be5: 55 push rbp 0xffffffff812d6be6: 48 c7 05 4f d1 cd 00 00 01 c8 81 mov QWORD PTR [rip+0xcdd14f],0xffffffff81c80100 0xffffffff812d6bf1: 48 89 e5 mov rbp,rsp 0xffffffff812d6bf5: c3 ret End of assembler dump. Para disassemblar sem símbolo você precisa dizer ao gdb até onde ir, por isso fui até 0xffffffff812d6bff, mas cortei o que veio depois do ret no dump. Se contarmos, vamos perceber que o número começa em (endereço da função) + 13 e tem 4 bytes. Só pra confirmar: (gdb) x/x 0xffffffff812d6be0 + 13 0xffffffff812d6bed: 0x81c80100 Agora vamos seguir (#medo)! 4. Implementação Ficou deste jeito: unsigned long default_security_ops = 0xffffffff00000000; unsigned long _reset_security_ops = 0; _reset_security_ops = kallsyms_lookup_name("reset_security_ops"); memcpy(&default_security_ops, (void *) (_reset_security_ops + 13), 4); A variável default_security_ops já é inicializada com sua parte alta toda setada, pois só a parte baixa do endereço está no assembly. A kallsyms_lookup_name() me dá o endereço da função reset_security_ops(). A memcpy() então copia os 4 bytes que compõem o segundo operando da instrução mov, que é o nosso endereço. O resultado abaixo foi obtido com este código implementado em um módulo: # grep default_security_ops /boot/System.map-3.13.0-44-generic ffffffff81c80100 d default_security_ops # rmmod teste; make >/dev/null && insmod teste.ko && dmesg | tail -1 [15999.471619] default_security_ops address: 0xffffffff81c80100 Os endereços batem, no entanto, essa coisa não foi para produção (graças ao Divino) e não recomendo que utilizem nada parecido em nenhum sistema crítico, mas será que dá pra aplicar essa técnica de “contagem de bytes” para outras coisas?
  5. No últmo artigo falei sobre como montar uma máquina virtual básica para ER em Windows. Agora chegou a vez do Linux, já que o mundo não é feito só de PE. A ideia aqui é montar um ambiente legal para reverter binários ELF. Dá uma olhada neste vídeo (em tela cheia de preferência) pra ter uma ideia do poder dessas ferramentas. Legal né? Então mãos à obra! Máquina virtual 512 MB de memória Placa de rede em modo NAT Placa de rede em modo host-only Sistema operacional Utilizo a ISO netinstall do Debian 7 64-bits mas como sempre você é livre para utilizar a distribuição que quiser, só que este artigo é escrito com base nesta. Algumas dicas de instalação: Não utilizar seu nome verdadeiro na criação da conta de usuário. Não instalar as extensões do software virtualizador como VMware Tools ou VirtualBox Guest Additions. Não configurar nenhuma regra de firewall ou qualquer software de proteção. /etc/apt/sources.list Eu deixo do seguinte jeito: deb http://ftp.br.debian.org/debian/ jessie main contrib non-free deb http://security.debian.org/ jessie/updates main deb http://ftp.br.debian.org/debian/ jessie-updates main deb http://ftp.br.debian.org/debian/ jessie-backports main O importante aqui é ter o “contrib non-free” após o main, infelizmente, pois alguns programas como o rar não são livres. Depois de configurado este arquivo, é bom atualizar os pacotes existentes: # apt-get update # apt-get upgrade -y Pacotes básicos # apt-get install zip unzip rar unrar p7zip file sudo git vim rcconf openssh-server Git para clonar repositórios de outros software que precisamos, servidor ssh para acessar a máquina de forma fácil, descompactadores etc. Software específico wxHexEditor: Este é o melhor editor hexa que tem em minha opinião. Edita dispositivos e até processos em memória. Para compilá-lo, primeiro você vai ter que instalar suas dependências: # apt-get install autoconf libtool libwxgtk2.8-dev gettext Depois é só baixar o tarball, descomprimir, entrar no diretório e comandar os famosos: $ ./configure $ make # make install Bokken: IDE muito boa para o pyew e radare2 (especialmente este útlimo). Com o Bokken é possível gerar inclusive um diagrama de fluxo das funções utilizadas pelo ELF. Na prática, ele server como disassembler, não como debugger. Ele é escrito em Python. Vamos à instalação das dependências então: # apt-get install python-radare2 pyew python-gtk2 python-gtksourceview2 graphviz python-rsvg python-utidylib Depois baixe o tarball (não use o pacote .deb disponível, ele está desatualizado com relação às dependências), descompacte e mova o diretório bokken-1.6 para um de sua prefência (/opt em nosso caso). Aí basta editar a varíavel BOKKEN_DIR no script /opt/bokken-1.6/bokken para refletir o novo diretório do programa (BOKKEN_DIR=/opt/bokken-1.6) e criar um link simbólico para este script em /usr/local/bin, para que este possa ser chamado a partir de qualquer diretório: # ln -s /opt/bokken-1.6/bokken /usr/local/bin/bokken Evan’s Debugger: Este projeto é simplesmente fenomenal. A ideia do Evan foi criar um debugger livre com base no OllyDbg. Eu apresentei este projeto na conferência H2HC de 2010 (fiz algumas contribuições) e e de lá pra cá o edb, como é chamado seu binário principal, só melhora. Dependências: # apt-get install libqt4-dev libboost-dev xterm yasm Após baixar a última versão do debugger e descomprimir, para compilar e instalar: $ qmake $ make # make install Agora em ~/.config/codef00.com/edb.conf você precisa configurar os diretórios utilizados pelo edb: [Directories] directory.symbol.path=/home/<usuario>/.config/codef00.com/symbols directory.plugin.path=/lib64/edb directory.session.path=/tmp E criar o diretório de symbols: $ mkdir -p ~/.config/codef00.com/symbols bashacks: Valeria a pena só pelas funções asciitable e utf8table. Brincadeiras à parte, tem várias funções úteis para ER, como a hexcalc: $ hexcalc 4f + 2e 0x7d Para instalar, é clonar o repositório com o git, mover para um diretório /opt por exemplo e adicionar no ~/.bashrc: $ git clone https://github.com/merces/bashacks.git # mv bashacks /opt $ echo 'source /opt/bashacks/bashacks.sh' >> ~/.bashrc Pronto. Ao relogar todas as funções estarão disponíveis. Se quiser saber um pouco mais sobre basta assistir ao nosso vídeo sobre esta ferramenta. Utilizo ainda os seguintes pacotes (apt-get install neles): ht: instala o programa hte, um poderoso editor e disassembler de binários que utiliza a ncurses. Já me salvou onde não tinha X. strace: rastreia chamadas de sistema feitas por binários ltrace: rastreia chamadas de bibliotecas feitas por binários tcpdump: captura de tráfego de rede foremost: ajuda nos casos em que há binários dentro de binários unhide: mostra processos e conexões ocultas E há ainda os nativos do Linux que também são úteis: readelf: mostra informações sobre binários ELF como symbols, cabeçalhos, seções etc objdump: tipo o anterior, mas suporta outros formatos. Disassembla também. Um comando legal com ele é: $ objdump -M intel -d <arquivo> Observações Após instalar todos os softwares, é de extrema utilidade criar um snapshot da máquina virtual, pra você voltar facilmente a este estado limpo após analisar um arquivo suspeito, por exemplo. Não precisa instalar um ambiente gráfico. Pode conectar na máquina com ssh -X e rodar os programas gráficos. Existe uma distribuição Linux chamada REMnux com foco em engenharia reversa. Eu sugeri ao autor que incluisse as ferramentas que menciono aqui.
  6. Fernando Mercês

    Criando um media server com Debian

    Configurar um servidor de mídia pode ser uma boa maneira de aproveitar um PC de baixo desempenho (mas de razoável capacidade de armazenamento). Além de centralizar suas músicas, fotos e vídeos, torná-los acessíveis a dispositivos como smart TVs, smartphones, tablets, video games e outros que possam atuar como clientes de streaming é realmente interessante. Tudo que precisamos para configurar este servidor é de uma LAN ou WLAN e o Debian GNU/Linux. Sem complicação, sem custo. Configurar o Debian com IP fixo No media server, configuramos um Debian Wheezy com IP fixo. A máquina que eu utilizei acessa a WLAN através de um adaptador wireless USB, então eu coloquei uma reserva de IP (através do MAC address) no próprio roteador wireless, fazendo com que o mesmo IP seja entregue ao servidor, mas você configurar de acordo com a topologia da sua rede. A configuração de IP no Debian fica em /etc/network/interfaces. Lembrando que não precisamos de ambiente gráfico. Criando o diretório de mídia Tendo o IP, é hora de criar um diretório que mídia que vai armazenar seus arquivos. Escolhi /home/share, mas poderia ser qualquer outro. Dentro dele vamos criar diretórios separados para, por exemplo, filmes, shows e músicas: $ sudo mkdir -p /home/share/{filmes,shows,mp3} Eu optei por não compartilhar fotos por questões de privacidade. Agora é hora de colocar arquivos nos diretórios, de modo a popular o media server. Para poder gerenciar os arquivos sem privilégios de root, é interessante tornar seu usuário comum dono do diretório share. No meu caso, o nome de usuário é fernando: $ sudo chown -R fernando: /home/share Certifique-se de que os arquivos e diretórios possuem permissões para serem visualizados, mas nada de 777 hein. Se necessário, aplique as permissões padrão neles: $ find /home/share -type d -exec chmod 0755 {} ; $ find /home/share -type f -exec chmod 0644 {} ; Instalando e configurando o minidlna O minidlna [1] é um servidor de mídia para clientes DLNA/UPnP. Resumidamente, enquanto o UPnP é um conjunto de protocolos que permitem dispositivos compatíves se encontrarem numa rede (auto-discovery), o DLNA é um serviço que utiliza UPnP para streaming de mídia. Algumas pessoas preferem usar o MediaTomb, que tem mais recursos que o minidlna, mas este último é bem modesto e simplista. Para instalar é bem difícil: $ sudo apt-get install minidlna Após a instalação, vamos configurar três parâmetros em /etc/minidlna.conf: media_dir=/home/share root_container=B friendly_name=Debian Home Server A opção root_container=B faz com que os dispositivos vejam os três diretórios que criamos abaixo de /home/share, por padrão. Eu configurei assim porque não gosto de localizar mídia por artista, gênero, ano etc já que não mantenho tags IDv3 e similares atualizadas. Se não é o seu caso, pode comentar essa opção para que ela seja configurar com seu valor padrão. Em friendly_name você configura um nome pelo qual os dispositivos clientes reconhecerão seu media server. E por fim, a única opção realmente necessária para o servidor entrar em funcionamento, media_dir, define qual o diretório raiz de mídia. Após salvar o arquivo, é preciso forçar que o banco de dados de mídia (em /var/lib/minidlna) seja recriado: $ sudo /etc/init.d/minidlna force-reload Por padrão, as portas UDP 1900 e TCP 8200 são utilizadas. Se você configurou um firewall no servidor, deve liberá-las. Isto é tudo que você precisa fazer para ter um media server funcional. Vamos agora para o lado cliente. Usando clientes no Linux e Windows Em minha humilde opinião, tá pra nascer um player melhor que o VLC [2]. Além de fazer café, ele é multiplataforma (apt-get install vlc) e age como cliente UPnP tranquilamente. Para isso, instale-o numa máquina que está na mesma rede que o servidor e faça o seguinte: Abra o VLC e vá em “View -> Playlist”. Na navegação do lado esquerdo, expanda “Local Network” e vá em “Universal Plug’n’Play”. O friendly_name do seu media server deve aparecer do lado direito em alguns segundos e você já pode começar o streaming. Usando cliente no Android Usuários de smartphones Samsung já possuem um clinte instalado chamado AllShare. Na verdade ele é um servidor também, e você pode compartilhar os arquivos de mídia do seu aparelho na rede, se for de seu interesse. O VLC para Android [3] suporta UPnP, mas os testes foram feitos com uma alternativa para a época que ainda não havia suporte. A ferramenta utilizado foi o UPnPlay [4], que é gratuito e dá conta do recado. Depois de instalar, basta abri-lo e começar o streaming: Outros clientes Qualquer dispositivo compatível com o UPnP na sua rede vai encontrar seu servidor. Smart TVs, DVD/Blu-ray players, video games (como o PS3) e outros. No caso de outros smartphones como iPhone ou Blackberry, pode ser necessário instalar algum aplicativo, mas duvido que seja difícil. Segue uma lista com vários softwares servidores e clientes [5]. Agora não tem desculpa. Referências [1] http://sourceforge.net/projects/minidlna/ [2] http://www.videolan.org/vlc/ [3] https://www.videolan.org/vlc/download-android.html [5] http://en.wikipedia.org/wiki/List_of_UPnP_AV_media_servers_and_clients#Android
×