quarta-feira , julho 26 2017
Últimas Notícias

Dicas para iniciantes – Assembly

Este artigo tem como objetivo falar brevemente da linguagem Assembly (ou asm abreviadamente), suas aplicações, limitações, mitos e indicar alguns materiais de estudo sobre a linguagem e demais áreas que a utiliza como base essencial.

Antes de ler este artigo é indicado a leitura desses artigos:

Dicas para iniciantes – Programação

Eu quero me tornar um Hacker!

O Assembly é uma linguagem de programação de baixo nível, ou também chamado de linguagem de montagem. É a linguagem mais próxima do nível de máquina. (Alguns autores consideram o Assembly uma classe de linguagens e não uma única linguagem em si)

 

Por que aprender Assembly?

Algumas pessoas dizem que não se utiliza mais, porém isso é um equivoco, pode não ser mais tão utilizado para programar como antigamente, justamente pelos sistemas atuais tenderem a ser mais complexos e necessitar de ferramentas mais adequadas para tal, mas existe sim algumas coisas no mundo atual que necessitamos desta linguagem:

  • Conhecimento – Conhecendo Assembly, lhe dará a capacidade de saber com muito mais riqueza de detalhes como o computador funciona e como a própria programação funciona em um nível mais íntimo, conhecimento muito importante na área acadêmica para arquitetura, sistemas operacionais e compiladores.
  • Engenharia reversa:
    • Análise de Malware – Na área forense, existem 2 formas de análise de código, a análise estática (não executa o código) e análise dinâmica (executa o código) , no caso da engenharia reversa se faz o disassembly (transforma código de máquina em código Assembly) e/ou descompilação (transforma a código de máquina em uma linguagem de alto nível) do código binário, o que possibilita analisar um Malware de forma legível, dando a possibilidade de saber tudo (ou quase) que ele pode fazer.
    • Desenvolvimento de exploits – Pode-se sim desenvolver exploits em linguagens de alto nível, mas em baixo nível é onde ele tem a maior fama e onde reside mais perigos. O Assembly te dará um poder grande, podendo manipular os valores de registradores e da memória lhe possibilita explorar falhas que as linguagens de alto nível não lhe permitem, podendo explorar falhas como Buffer/Stack/Heap Overflow, Format String, dentre outros. Essas falhas permitem proezas como executar um outro programa como um backdoor através de outros programa que já está sendo executado na memória, como o  Avast.
    • Desenvolvimento de Malwares – Hoje em dia alguns Malware podem ser feitos parcialmente (maioria dos casos) ou totalmente em Assembly. Malwares como worms tendem a usar uma parte do Assembly para explorar falhas na rede para se propagar, mas outros tipos de Malwares podem se beneficiar da linguagem de baixo nível para atingir ser objetivos.
    • Patching/Cracking – É possível tanto bypassar alguns bloqueios de proteção de código de Malwares como crackear programas editando o seu Assembly e recompilando.
  • Debugging:
    • Análise de Malware – Na área forense outra forma de análise de código é a análise dinâmica, o qual poderá executar o programar debuga-lo e ver como ele age em tempo de execução em nível de Assembly, algumas vezes é necessário quando a análise estática pode não ser suficiente ou inviável.
    • Patching/Cracking – É possível tanto bypassar alguns bloqueios de proteção de código de Malwares como crackear programas editando o seu Assembly em tempo de execução.
  • Ofuscação de código – Manipulando os código via Assembly é possível utilizar algumas técnicas para dificultar a análise do código,isto pode ser usado tanto para proteção de propriedade intelectual de software como para bypassar um antivírus.

 

Conceitos básicos

Linguagem de máquina é a linguagem que o computador realmente entende para executar suas tarefas. Esta linguagem trabalha com os 0’s e 1’s (código binário) famosos dá computação. Antigamente a programação era feita diretamente em código binário pelos programadores, o que era um trabalho cansativo, longo, difícil e muito pouco produtivo. Os cartões perfurados vistos em alguns filmes é como os programadores criavam seus programas usando código binário, onde no cartão os pontos perfurados representavam o 1 e os não perfurados o 0.

Para aqueles que programam já em linguagens de médio e/ou alto nível, tentem imaginar decorar uma sequência binária como 01100111 no lugar de uma instrução comando simples print e pior você teria que usar mais dessas sequências binárias para fazer esse print, agora imagine ter de lembrar os códigos binários para os demais comandos que conhecemos no alto nível, sem contar que alguns comandos em alto nível correspondem corresponder a várias instruções na linguagem de máquina.

O Assembly trabalha com instruções e operadores. Instrução é o que dita qual o procedimento que será realizado, podendo ser uma adição, subtração, saltar para uma linha de código, atribuir valores, comparações lógicas, dentre outros. As instruções em Assembly são chamadas de mnemônicos, pois são palavras curtas que representam as instruções de uma forma mais legível a humanos, como: MOV, ADD, SUB, JMP, CALL e RET. Na linguagem de máquina, as instruções são chamadas de opcodes (código de operação), estas operações são representadas em formato binário, que pode variar dependendo do processador. Os mnemônicos do Assembly são uma abstração legível para humanos dos opcodes em linguagem de máquina, mas um mnemônico pode corresponder a um ou mais opcodes.

Os operadores são os dados passados as instruções, para que executem a sua função, por exemplo, MOV EAX, 14H. Dissecando isto, o MOV é a instrução de mover dados e o EAX e 14H são os operadores.

O Assembly é compilado como qualquer linguagem de programação, o seu compilador é chamado de Assembler (montador), existem mais de um sendo o mais famoso no Linux o NASM. A peculiaridade do assembler é que ele não gera direto código binário (muito antigamente gerava na época do DOS), ele primeiro cria um arquivo com extensão .o chamado de arquivo objeto e em seguida passa pelo link-editor o qual é responsável por incluir referências dentro de um código .o como bibliotecas e módulos o qual o código fonte referencia, ao passar pela linkedição  é gerado finalmente o código de máquina que poderá ser executado.

Note que Assembly e Assembler são coisas diferentes e muitas pessoas costumar inverter ou achar que é a mesma coisa. Assembly é a linguagem de programação e Assembler é o compilador.

O Assembly não é o mais baixo nível do computador, de acordo com a organização estruturada de computadores, o computador é dividido em 6 camadas que variam com o tempo. Note que no topo que é a abstração de mais alto nível tem a camada de linguagem orientada para problemas, que nada mais é do que linguagens que tem como objetivo resolver problemas do mundo real de forma mais objetiva, simples e direta, são as linguagens de médio  a alto nível como C, C++, C#, Java, Python, Cobol, Object Pascal e por ai vai.

 

Logo abaixo dessa camada vem a linguagem de montagem, que é o nosso querido Assembly.

Mais abaixo note que tem ainda o próprio sistema operacional, sim o Assembly não é a ponte direta com o nível de máquina, o sistema operacional faz o intermédio, tendo um grande controle sobre o código, o que deixa o sistema muito mais seguro, na época do DOS o sistema operacional não tinha tanto controle do que estava sendo executado, o que tem seu lado bom e ruim dependendo do ponto de vista.

O lado bom é que como programadores bem intencionados, ter o sistema operacional no meio facilita de forma muito grande a programação em Assembly, pois não precisamos pensar em diversas coisas como controle mais complicado da memória sem causar erros e nem se preocupar com a interação com os drivers, o sistema operacional hoje em dia trata muito bem isso de forma muito transparente com memória virtual com modo protegido (não falo de swap) e as chamadas de sistema que abstrai mais a comunicação com os drives, periféricos e etc…

O lado ruim para os black hats é que antigamente por ter tanto acesso assim mais direto ao hardware, poderia se fazer muita coisa, até Malware projetados para destruir o PC e provocar erros de buffer overflow e os demais, era algo muito fácil. Hoje tanto o sistema operacional como o próprio hardware tem mais proteções e  o Assembly consequentemente perde parte de seu poder.

Em seguida no níveis mais baixos o código passará para as demais camadas passando pro processos de transformação até chegar o nível de hardware de execução.

Para saber mais sobre estas camadas, o livro de Organização estruturada de computadores de Andrew S. Tanenbaum fala inteiramente disso.

 

Peculiaridades

O Assembly tem a peculiaridade de não ser muito portátil, pois o mesmo asm compilado em um SO não servirá para outro, ou seja, se fez para Linux, então não executará em Windows e MAC OS. Também a arquitetura do processador implica, por se fez para 32 bits, poderá tem problemas com 64 bits, ARM e outros (A não ser que use modo de compatibilidade). Essa questão de incompatibilidade melhorou muito com o passar dos anos, antigamente era um grande problema, pois os processadores não mantinha compatibilidade com versões antigas, ou seja, é como se nos dias atuais um programa que roda no core i3, no executasse no core i5 e i7, sendo necessário um novo código para cada um.

Com relação aos sistemas operacionais o problema é que cada um tem chamadas de sistemas diferentes, já entre as arquiteturas diferente, internamente bastante coisa pode mudar como tamanho dos registradores, quais instruções possui e a forma de funcionamento das mesmas. É fácil para quem sabe 32 bits aprender 64 bits, mas migrar para uma arquitetura com ARM é um pouco mais difícil.

Existem duas sintaxes principais para asm: Intel (mais comum em Windows) e AT&T (mais comum em Linux).

A forma de escrever o programa é diferente e tem regras diferentes, mas no fundo todos viram código de máquina e é indiferente se usa um ou outro para Windows ou Linux, apenas um sistema operacional terá mais programas que utilizam uma determinada sintaxe do que no outro SO. Existem sim pequenas diferenças, mas é muito fácil migrar de um para o outro. Segue abaixo um exemplo:

Intex Syntax

mov  eax,1

mov ebx,0ffh

int 80h

AT&T Syntax

movl $1,%eax

movl $0xff,%ebx

int $0x80

 

Mitos e erros

  • Assembly tem o controle total do computador – Na verdade até a época do DOS isto era na verdade devido a organização da memória RAM. No real mode o programa em Assembly tinha total acesso a memória podendo acessar e sobrescrever a região dá memória pertencente a outros programas, além disso o sistema operacional na época apenas chamava o programa e naquele momento ele que tinha o poder igual ao do próprio sistema operacional, hoje com a memória trabalhando com protected mode, o programa tem seu próprio espaço e ele fica proibido de acessar as regiões que não deve (fica mais difícil) e o sistema operacional gerencia as instruções passadas pelo Assembly, algumas operações como alterar alguns registradores sensíveis não é mais possível de forma direta e nem acessar o hardware diretamente dentre outras proteções;
  • Malwares são criados em Assembly – Parcialmente correto, pois eles podem sim ser criados em Assembly, mas também existem malware que são criados em linguagens de alto nível, outros criados em alto nível, convertidos para Assembly, onde serão modificados alguns trechos em Assembly e depois compilados, outros ainda usará o Assembly dentro de uma linguagem de alto nível, conhecido como Assembly in line. Depende muito do caso de como será feito o Malware, cada forma possui algumas vantagens, por exemplo, o Assembly in line é muito utilizado para criação de exploits;
  • Assembly pode fazer o computador queimar – Antigamente isto seria possível sim, mas o hardware e sistema operacional de hoje em dia possui muitas proteções e restringem algumas coisas que Assembly fazia antigamente, isto seria algo muito difícil hoje em dia;
  • Assembly só possui operações de adição e divisão – Atualmente o Assembly tem sim operações de multiplicação e divisão, na verdade no nível digital (lógica eletrônica) do computador que não tem, trabalhamos com camadas de abstração, o Assembly está acima desta camada e é mais abstrato;
  • Assembler x Assembly – Muitos confundem a diferença como citado anteriormente, mas leve em consideração que assembler é compilado e assembly a linguagem;
  • Assembly é difícil – Se você souber estrutura de computadores, o mesmo será bem mais tranquilo de aprender;
  • Ninguém usa mais Assembly – Assembly é sim usado, mas não tanto para desenvolvimento como no início, mas sim para questões como análise de malware, cracking e etc…;
  • Assembly é utilizado para criar códigos mais rápidos – Parcialmente verdade, se criar algo em Assembly de fato poderá criar algo muito mais rápido, mas isso é pouco praticável devido ao tamanho e complexabilidade dos sistemas de hoje, sendo usado alguns algoritmos para ganhar mais desempenho.

 

Curiosidades

O x86 tão famoso nas pastas do Windows se refere a família de processadores X86 da Intel, onde o x era o número de um modelo, exemplo: 8086, 80186, 80286, 80386 e 80486, depois a parou de usar número, pois para patentes não poderia utilizar nomes puramente numéricos, então vieram processadores como Pentium, Celeron, dual core e etc…

Ao entrar em alguns sites como do Debian para baixar a ISO, deve ter percebido que o 64 bits é chamado de amd64, sim se refere ao AMD rival da Intel. Isso é algo histórico, pois quem teve a ideia e planejou foi a AMD para criar a geranção de processadores de 64 bits, porém a Intel pegou essa ideia, deu uma pequena modificada e lançou primeiro um processador de 64 bits, mas teve problemas, pois não era compatível com 32 bits (antigo i386) e em seguida a AMD lança um que possuía esta compatibilidade. Como a AMD teve essa ideia antes e a Intel seguiu mais ou menos este padrão de 64 bits da AMD, se deu o nome amd64.

Os processadores de 64 bits comercialmente, não disponibilizam reais 64 bits para endereçamento de memória (para registradores sim), em vista de que o processador ficaria mais caro com quantidade de transistores gastos atoa que nunca seriam utilizados, pelo menos para usuários casuais, eles reduzem isto, alguns por exemplo possui apenas 40 para endereçamento, o que é muita coisa ainda.

 

 

Pré-requisitos

O para entender o Assembly de forma mais fácil é indicado estudar anteriormente:

  • Arquitetura de computadores – Pois precisará aprender sobre as camadas de abstração e principalmente o funcionamento da memória RAM e processador;
  • Sistemas operacionais – Pois te dará a base de como os sistemas operacionais trabalham e gerenciam os processos e a memória RAM, além das chamadas de sistema.

 

Material de estudo

Com relação a materiais em português, eu desconheço, no máximo que vi foi o Assembly no curso de análise de malware da Clavis e no curso de security specialist da esecurity, mas eles ensinam Assembly rapidamente no meio do curso, não é um curso tão aprofundado e nem focado sobre isto, muito antigamente a OYS dava um curso só de Assembly, mas infelizmente não ministram mais, dessa forma é bom ter um bom inglês para aprender Assembly.

Para aqueles que querem ao menos conhecer o mínimo de Assembly, sem ser em inglês deixo a dica de que no livro de Organização estruturada de computadores – Andrew S. Tanenbaum, no apêndice C fala de Assemnbly.

Um livro que não fala diretamente de Assembly, mas que gosto muito por ele contar a história da tecnologia de baixo pra cima é o Code: The Hidden Language of Computer Hardware and Software, aprendendo o que é um código de forma genérica, sistemas numéricos, elétrica, eletrônica, linguagem de máquina e Assembly. Ele dará uma visão muito boa de como o próprio Assembly funciona por baixo e das camadas abaixo do mesmo, mas para conhecer Assembly ele é uma leitura opcional e não obrigatória.

Outro livro opcional, mas que faz um bom relacionamento entre linguagem de baixo nível e alto nível é o Programming from the Ground Up, que ensina essencial de arquitetura, parte para o Assembly e em seguida para o  C, possui uma didática bem simples e nos dá uma boa visão do de para entre baixo e médio nível.

Livros que falam puramente de Assembly que indico em ordem de sugestão é:

  1. Assembly Language Step-by-Step: Programming with Linux;
  2. The Art of Assembly Language 2nd Edition;
  3. Professional Assembly Language.

Com relação a sites, indico um tutorial rápido sobre Assembly: https://www.tutorialspoint.com/assembly_programming/index.htm

Com relação a cursos, recomendo os da pentester academy.

Nos próximos antigos, este será utilizado como base para engenharia reversa, análise de malware, exploits e outros.

Sobre NullS3c

Possuo especialidade na área de computação forense. Mais informações sobre mim poderá ver em: https://www.linkedin.com/in/victor-cunha-8753073b/
Free WordPress Themes - Download High-quality Templates