Menu

Programar diretamente na memória

15 de agosto de 2015 - Praticando

Programar diretamente na memória

Programando com DEBUG

Memoria
viruscore

queshow
Vamos sair para o sub-mundo do sistema operacional, o mundo D.O.S., para construirmos nosso “HELLO WORLD“, para isto, estando no windows,

 

E por que D.O.S. (prompt de comando) ? o problema todo é o seguinte, assembly puro só pode ser construido em D.O.S., nesta primeria fase do curso iremos tratar do assembly puro e depois assembly para Windows (que exigeAPI para funcionar).

Para entender Assembly, vamos esquecer as exigências insanas do Windows na construção do código.

 

um programa que vamos usar muito nesta primeira fase é o DEBUG.EXE, que não está presente no Windows7, Windows Vista nem WIndows 8, parece que o windows vai nos afastando cada vez mais da raiz das coisas … e consequentemente do Assembly.

Teremos que montar uma plataforma de aprendizado, para isto precisamos de um Windows que pelo menos não fique proibido-nos de fazer as coisas em baixo nível !  o último Windows que foi bonzinho foi o WIndows XP ! Sim, ele “ainda” tinha o DEBUG.EXE que iremos usar nesta primeira versão, e não também não exigir assinatura de driver, e vamos praticar neste então.

 

Uma boa técnica é a seguinte, baixar o VirtualBox e depois instalar oWIndowsXP neste VirtualBox (ou VMWare), desta forma, conseguiremos executar o Windows XP dentro do Windows7 ou Windows 8.

 

 

Depois que instalar o VirtualBox e instalar o WIndows XP , executaremos o Windows XP e seguiremos os passos abaixo.

 

Entrando em modo D.O.S.

 

Clicar em Iniciar->Prompt de Comando ,

Então rodar o DEBUG:

debug

 

No exemplo acima, após digitar DEBUG (e enter para passar a linha de baixo), então digitamos a (enter) e digitamos as instruções assembly descritas acima, espero que esteja claro que este ENTER vermelho se refira a apertar ENTER (ou apertar RETURN) para encerrar a linha, eu não vou mais colocar este ENTER em vermelho nos próximos exemplos.

 

Comentando linha a linha:

 

“-a “ Este ( a ) digitado dentro do DEBUG, informa ao DEBUG para acessar a próxima memória disponível, que seria 100h, antigamente todos programas .COM começavam em 100h, então ele já assume este endereço como padrão, como não vamos fazer programas grandes .EXE, podemos utilizar este endereço por enquanto.

 

“MOV AH,9 ” MOV é uma instrução que informa ao microprocessador para mover o valor 9 para a parte alta do registrador AX, e o que seria isto ?

Vamos entender: O Registrador AX possui 16 bits ! ou seja, ele também pode ser dividido em 2 partes, podemos imaginá-lo como aquelas células que se dividem e possuem vida própria, ou seja, este AX pode ser dividido em dois registradores de 8 bits chamado AH e AL (AH = parte alta, AL= parte baixa) (H=High, L=Low), antigamente nos idos anos 80 (Bee Gees, ABBA … isto não é do seu tempo né ? ) isto era tudo que existia nos antigos computadores de  8 bits que andaram pelo mundo como primeiro microcomputadores baseados em 8080 ou Z80, eles tinham somente 8 bits (metade do AX). Logo no comecinho dos anos 90 os computadores de 17 bits ficaram mais baratinhos, e invadiram o mundo todo, então o registradorAX começou a ser utilizado também, embora o recurso de utilizar metade dele (AH ou AL) ainda é usado para diversos fins, inclusive o fim deste programa.

Este texto não acabou ! amos falar mais sobre esta linha, o que significa este 9 colocado no AH ? ele informa o sistema simplesmente para exibir uma frase quando for chamado a interrupção INT 21h logo na frente.

 

“MOV DX,109″ Conforme se leu no texto anterior, o valor 9 em AH informa o sistema que uma frase será impressa quando se chamar o INT 21 logo a frente (ele só vai exibir quando a interrupção INT 21h for chamada), mas … onde fica o tal texto que será exibido ? é este o objetivo desta linha, indicar que local da memória esta a frase, que seria o endereço 109, inserindo o número 109 em DX, já informamos o sistema onde fica o tal texto afinal, o texto em questão é “MINHA FRASE EM BAIXO NIVEL $” no endereço de memória 109.

 

“INT 21″ Este é o cara ! só quando esta interrupção é chamada a frase é exibida, então nada adianta colocar os valore sem DX, em AH se esta interrupção não for chamada, quando ela é acionada o sistema vai pegar seu trabalho em AH (é onde ele fica sabendo o que fazer) e depois sabendo que é para exibir um texto, vai pegar o texto em DX que adivinha ? tem o valor 109 que é o endereço do texto.

 

“db  “MINHA FRASE A SER EXIBIDA” Perceba o número que aparece anes de db, é o endereço de memória 109, então o db (data byte) somente ifnorma ao DEBUG para inserir o texto a frente byte a byte começando no endereço 109, no final do texto vemos o dolar ( $ ) e porque ele está no final ? ele só i vai informar o fim do texto, se não for inserido a interrrupção INT 21 vai imprimindo tudo que estiver na frente do texto  sem parar até o fim da memória ou até encontrar um $no caminho, ele delimita o fim mas não é impresso.

“INT 20″ Esta interrupção somente informa que o programa terminou, sim ! em assembly precisamos informar que nossa festinha acabou, ela pode ser comparada ao ” } ” do C ou do “end.” do pascal (ou delphi).

 

Bem, até agora só vimos teoria, não vimos nada pular na tela, nada acontecer … vamos fazer algo acontecer, vamos RODAR o programa, fazer ele exibir a tal frase, depois vamos gerar um programa com ele SEM COMPILAR NADA ! como ? você se esqueceu que assembly é  a inlguagem do microprocessador ? e estamos escrevendo diretamente para ele ? só compilamos quando escrevemos em linguagem de alto nivel como C , Pascal, etc., e quando compilamos o que acontece ? se transforma em assembly.

 

Para executar, basta digitar G=endereço, onde o endereço é o … 100h , então ficaria ( g = 100 ).

Como visto abaixo:

assembly debug

 

Entendendo melhor este programinha aí, poderíamos descreve-lo em algoritmo da seguinte forma:

AH = 9oque faz: 9 Informa o sistema que algo será exibido

DX = endereco oque faz: DX = endereço, DX sempre vai ter o endereço de memória do que desejamos exibir

Chamar Interrupção 21hoque faz: Executa a operação descrita em AH (que é 9, exibição de texto, mas poderia ser outro processamento)

Chamar Interrupção 20hoque faz: Termina o programa, sim ! a festa termina aqui

 

Vamos continuar explorando mais os recursos do DEBUG, que tal esperar uma tecla antes de terminar o programa ? o famoso INPUT !

Vamos utilizar uma interrupção diferente da velha 21h, vamos utilizar a interrupção responsável pelo teclado, a interrupção 16h , e dando uma olhadinha de como utilizar, vemos que precisamos inserir o valor 0 em AH.

frase no debug

No exemplo acima, saímos da mesmice da impressão de texto, e lemos uma tecla, para começar vemos o primeiro bloco com ah=9, dx=114 e o velho int 21 para exibir o texto, logo após vemos algo diferente, AH=0 e INT 16, que não exibe nada, apenas espera que uma tecla seja digitada, após pressionamos qualquer tecla, novamente exibimos a mesma frase.

 

Para executar o programa, vemos lá o G=100 ( comece a executar a partir do endereço 100h, perceba que começa realmente em 100, olhe lá o endereço 13D8:0100h , ignore este 13D8 , este é o segmento de memória (explicarei mais tarde), e o segmento muda constantemente, o que interessa é o OFFSET 100h mesmo).

 

Logo abaixo do G=100, vemos o texto exibido, aguarda uma tecla ser pressionada, e novamente exibido,e  depois a mensagem “Program terminated normally“.

 

E o que significa tudo isto ? só prática mesmo ! para irmos nos acostumando a usar o MOV para inserir valor em um registrador, e ver como diferentes interrupções fazem coisas diferentes, prática é tudo para sair fazendo sem precisar pensar, assim como fazemos quando precisamos aprender uma língua nova … só praticando vamos ficando fluente nisto,e  a instrução MOV é a mais básica de todas, assim como é utilizada para mover valores em registrador 8 bits ( MOV AH, 9 ), também é utilizada para 16 bits ( MOV AX, 100h ) e 32 bits ( MOV EAX, 100h ).

Espero ter convencido que isto que foi apreendido é muito útil didaticamente.

 

-=-

GERANDO UM PROGRAMA EXECUTÁVEL SEM COMPILAR NADA !

 

Que tal gerar um programa ? até agora inserimos instruções na memória, depois desligamos o PC e perdemos tudo ! ora … como manter isto em um programa ? vamos então gerar através do DEBUG mesmo.

Mas antes ! vamos entender como isto funciona (lá vem teoria !) : Vamos entender como funciona a evolução de alguns executáveis do Windows, pelo menos os principais:

Programas .COM (  APPLE.COM  )

Programas .EXE Comum ( APPLE.EXE )

Programass .EXE Windows ( APPLE.EXE )

 

Existem outros tipos de executáveis, mas vamos nos ater a estes que marcaram a evolução dos executáveis, o primeiro é este .COM , este é o inicio de tudo ! Quando Bill Gates comprou o D.O.S. para vender a IBM como se fosse dele , já era assim ! o sistema rodava nos 640k básicos, e tudo era feito ali, o sistema de contabilidade da empresa e até a folha de pagamento.

Então os programas .COM não poderiam ser maior que 1 segmento de memória, segmento é aquela memória que aparece a esqueda

(segmento : offset). Como vimos no exemplo acima, o valor do segmento é sempre o mesmo, o que muda é o valor do offset que é a extensão do segmento, podemos imaginar uma matriz também.

 

Com o tempo as pessoas começaram a precisar de mais memória, então surgiu o.EXE , ele podia armazenar o programas além de um segmento, isto foi formidável para fazer Vírus de Computador, porque o vírus podia escolher um segmento para ele mesmo rodar, e colocar a vítima em outro segmento, e isto organizava a programação para o Vírus Maker, isto ainda é utilizado hoje nos Malware para Windows, esta manipulação de segmentação que facilita a compreensão das coisas.

Os programas EXE são bem diferentes dos programas .COM, porque eles tem um cabeçalho para avisar os sistema como alocar o programa, onde ele começa, onde ficam as seções de dados e imagens do programas, isto não existe nos programas .COM, do inicio ao fim é o programas em si ! enquanto em tipos .EXE existe um cabeçalho que não faz parte das coisas que programamos.

Daí vem os .EXE para Windows, eles possuem ainda mais um cabeçalho para informar o Windows como seu programas será alojado na memória, etc.

 

No futuro iremos gerar programas .EXE em Assembly, e veremos ele dissecado em nossa frente.

No momento vamos gerar um programa .COM , e por ser um tipo tão simples, não vamos ter dor de cabeça.

frase-com-debug

No exemplo acima, criamos um arquivo chamado PROGRAMA.EXE, vamos explicar o que fizemos ali encima:

Logo apos digitarmos o programa, isto já fizemos nos exemplos anteriores, no endereço 142 digitamos ENTER sem digitar nada, então o DEBUG sai no modo de edição de memória, daí utilizamos a diretiva rcx , ela é utilizada para informar que tamanho terá nosso programa, então colocamos o tamanho 42h ( sim ! todo número que vemos dentro do debg é HEXA !, portanto o número 42h significa 66 bytes no sistema decimal que conhecemos).

Depois digitamos n programa.com (n = nome do programa), colocando programa.com a frente do “ n “, informamos que nome vamos utilizar.

O w informa o debug para gravar o programa que digitamos até o tamanho 42h , utilizando o nome programa.com.

Logo depois, digitamos o nome do programa e vemos ele exibir a frase “Ola mundao preto, aqu Bill Gates comecou sua fortuna !“.

Voialá ! Este programa não perdemos mais ! está gravado e até podemos ver através do Windows Explorer.

assembly-para-dos

Através do Windows Explorer, vemos o programa PROGRAMA.COM criado, no tamanho veremos o tamanho 1Kb, que na verdade é falso ! porque o tamanho gravado foi de 66 bytes (42 hexa lembra ?), é estupidamente pequeno ! absurdamente pequeno ! que compilador gera  um programa no tamanho de 66 bytes ? mas o windows não consegue mensurar isto,e  coloca 1Kb.

Vamos dar uma olhada na propriedades do programa através do Windows mesmo:

programa assembly para dos

Aí está ! agora o Windows mostrou certinho o tamanho absurdamente pequeno de nosso programa.com, isto ocorre porque o executável não carrega nenhuma tabela de alocação e é totalmente inserido em Assembly sem passar pro nenhum compilador.

 

Bem, agora vamos rodar em Windows, veremos ele abrir uma tela e fechar, e isto é … um pouco decepcionante, porque a frase aparece tão rapidamente, que não vemos ela, que tal pedir para o programa esperar um ENTER antes de terminar ? ahhh podemos ver a frase então, vamos lá:

helloworld-para-dos-assembly

Aqui vemos nosso programa que exibe uma frase e… espera por uma tecla apertada.

Rodando ele no Windows, vemos então a frase já que vai esperar algo ser teclado.

rodar-programa-assembly-msdos

 

 

ADS2

 




Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios são marcados com *

Captcha loading...