Results 1 to 6 of 6
  1. #1
    Vitrix Maggot
    Vitrix Maggot is offline
    Member-in-training Vitrix Maggot's Avatar
    Join Date
    2013 Apr
    Location
    Brasil
    Posts
    58
    Thanks Thanks Given 
    0
    Thanks Thanks Received 
    43
    Thanked in
    24 Posts
    Rep Power
    0

    Aprendendo basico deASM OLLYDBG


    INTRODUÇÃO


    Seguindo a minha linha de tutoriais voltados a programação, vou tratar sobre um assunto que me interessa muito e talvez seja interessante para os programadores em geral: disassembler e debuggers.

    Primeiramente seria interessante esclarecer um pouco sobre o que é um debugger e o que é um disassembler, pois apesar de andarem quase sempre juntos, possuem finalidades diferentes.

    Disassembler é algo que consegue transformar linguagem de máquina para a linguagem assembly, transcrevendo as instruções enviadas ao processador para os seus mnemônicos em assembly (asm). Não deve ser confundido com um descompilador, que procura converter o código nativo em uma linguagem de mais alto nível como C, C++ ou Basic.

    Debuggers são programas capazes de analisar, depurar e testar aplicações. Atualmente a maioria das IDEs de programação contam com um debugger embutido (Visual Studio, por exemplo). A principal utilidade deles é para a identificação e tratamento de erro, sendo que é possível rodar o código linha por linha (ou instrução por instrução) e analisar a mudança das variáveis e do comportamento do código. Os debuggers de binários já compilados - como os executáveis do Windows (EXE) - seguem o mesmo conceito dos depuradores normais, mas devido ao fato de o código já ter sido compilado, ele precisa ter um disassembler embutido no debugger para decodificar as instruções.

    Atualmente existem dezenas de debuggers e disassemblers por aí, dentre os quais os mais famosos são: W32DASM, IDA, WinDbg, SoftICE e Ollydbg. Neste tutorial será utilizado o OllyDbg, pois é um dos melhores e mais poderosos debuggers (incluindo um disassembler) disponíveis no mercado. É também pequeno e gratuito

    QUAL A UTILIDADE UM DEBUGGER?


    Muita gente se pergunta do porquê de usar um debugger, sendo que na maioria dos casos você tem a acesso ao código fonte original (caso você tenha programado o aplicativo). Vou citar abaixo algumas das maiores utilidades de um debugger:
    Tratamento de erro. Certamente uma das principais. Às vezes durante a programação de um aplicativo um pequeno erro passou despercebido, ocasionando mal funcionamento ou gerando uma operação ilegal. Em muitos casos é mais fácil você analisar o binário já compilado dentro de um debugger do que tentar encontrar o erro no código original. Dentro desse mesmo item podemos citar a correção de bugs de aplicações já descontinuadas (desde que com a autorização da empresa dona dos direitos).
    Engenharia reversa. O processo de engenharia reversa de software não poderia ser feito de forma eficiente sem a utilização de um debugger/disassembler. Muitas pessoas tendem a confundir cracking com engenharia reversa, sendo que são conceitos diferentes. A engenharia reversa por si só é uma atividade completamente legal, pois muito do que vemos hoje só foi possível devido à engenharia reversa. A criação de drivers para Linux de periféricos que antes só funcionavam com o Windows (WinModems) é um bom exemplo de como a engenharia reversa traz coisas boas para nós.
    Aprendizado. O uso de debuggers e engenharia reversa é uma das melhores formas de se aprender a linguagem assembly. Você programa algo em uma linguagem de médio ou alto nível e posteriormente analisa o resultado do binário compilado dentro de um debugger. Com esse conhecimento é possível dominar melhor a linguagem e criar algoritmos mais otimizados e eficientes.

    CONCEITOS NECESSÁRIOS

    Para entender o funcionamento de um debugger é preciso saber um pouco sobre alguns conceitos ligados a informática, como o funcionamento da memória, processador, pilhas e endereços. O conhecimento básico de assembly também é necessário, já que essa é a linguagem que teremos de analisar. Caso não tenha experiência em assembly, fique tranqüilo, pois nos capítulos seguintes darei uma visão geral sobre ela, o suficiente para entender o nosso mini-aplicativo de estudo. Abaixo segue uma breve lista de conceitos:
    Processador/CPU: É o cérebro de todo computador. É ele que decodifica as instruções e executa os códigos operacionais. É composto basicamente por uma unidade lógico-aritmética (ALU), unidade de ponto flutuante (FPU), registradores, cachê, barramento e gerador de clock.

    Memória RAM: Local de armazenamento temporário de dados (são apagados ao desligar o computador). Todo aplicativo se utiliza da memória para armazenar seus dados e estes são buscados e gerenciados pelo processador.

    Endereçamento de memória: É uma faixa de valores que apontam para uma determinada posição de memória. Toda vez que você escreve ou lê algum dado da memória é necessário indicar o endereço de onde está aquele valor, para que o processador possa buscá-lo.

    Pilha (Stack): É uma estrutura de dados. Sua principal característica é a forma de funcionamento, onde você apenas coloca ou retira os valores, sem indicar um endereço (LIFO – Last in, First Out – Último a entrar, primeiro a sair). Ela funciona de forma semelhante a uma pilha de livros em que você vai os empilhando. Quando precisar remover um deles, é necessário tirar todos os livros de cima.

    Registradores: Pequenas partes de memória presentes dentro dos processadores (não confundir com memória RAM). Extremamente rápidas, sendo que a CPU as utiliza como forma temporária de armazenamento de dados e realização de operações. A quantidade de dados que podem ser armazenados vai depender do tipo de processador. Os processadores de 32 bits conseguem armazenar números de até 32 bits em cada registrador, sem precisar de rotinas de conversão.

    UM POUCO DE ASSEMBLY

    Para fazer o debug de binários compilados é necessário ter um conhecimento (ao menos básico) da linguagem assembly, já que é para ela que a linguagem de máquina é traduzida.

    Assembly (ou asm, com é abreviada) é uma linguagem de baixo nível que basicamente interpreta os códigos operacionais (opcodes, veja abaixo) e os transcreve para seus mnemônicos. É literalmente uma tradução da linguagem de máquina. O uso da linguagem assembly pode ser bem variado, podendo fazer de tudo um pouco, mas é amplamente utilizada na programação básica de Kernels e em algoritmos que precisam ser altamente otimizados, onde asm é a linguagem ideal, já que é puramente linguagem de máquina traduzida.

    Não pretendo agora explicar todo o funcionamento, estrutura e comandos da linguagem. Vou dar apenas um apanhado geral sobre alguns termos e uma breve descrição sobre os comandos mais básicos e corriqueiros que se encontra. Precisamos primeiramente definir o que são mnemônicos e o que são os opcodes.

    Opcodes (traduzido em operational code, ou código de operação) é a instrução que é enviada e interpretada pelo processador. Cada opcode, ao ser interpretado pelo processador, vai realizar uma operação. Mnemônicos são as palavras ou combinação de letras utilizadas para representar um opcode, tornando a linguagem de máquina mais legível. Veja abaixo um exemplo de um mnemônico do comando MOV:

    Código:
    MOV EAX,1
    Esse comando em assembly apenas move o valor 1 para o registrador EAX (veremos isso logo adiante na explicação dos comandos). Na hora de transformar isso em linguagem de máquina (por um asssembler), esse comando é traduzido para um conjunto de números que possa ser interpretado pelo processador:

    Código:
    B801000000
    A teoria por trás de tradução de mnemônicos em opcode (e vice-versa) é um tanto complexa, principalmente para a plataforma Intel na arquitetura IA32. É um processo que deve ser realizado bit a bit e fugiria um pouco do contexto deste tutorial.

    A principal dificuldade na linguagem assembly é certamente a sua estrutura, que foge do padrão de linguagens de mais alto nível como C ou Pascal. Nada de Ifs com múltiplas comparações, Switches, For ou While. Tudo é feito com comparações simples e saltos, perdendo a sua linearidade (semelhante aos GoTo do BASIC).
    Felizmente hoje temos debuggers muito inteligentes que conseguem estruturar e identificar rotinas e repetições, facilitando muito o trabalho de interpretação. Mesmo com essas melhorias, ainda acho importante ter um papel e uma caneta ao lado, onde você pode fazer anotações e ir estruturando/convertendo o código na medida em que você os interpreta.

    Para o assembly, a localização dos valores e variáveis é sempre baseada nos endereços que elas ocupam na memória. O nome que você define para uma variável durante a programação é substituído pelo endereço de memória que ela ocupa. Cada instrução também possui um endereço, que é utilizado para controlar o fluxo e a estrutura do código. Sempre que você faz um salto, é necessário indicar o endereço que o código deve ser direcionado, semelhante ao que ocorria nas numerações de linhas dos BASICs mais antigos. Veja um exemplo abaixo de como ficaria um código em C e o seu resultado compilado para assembly, utilizando apenas registradores comuns:

    Código:
    void main() {
    int a = 4;
    int b = 6;
    int c;

    if((a == 4) && (b == 6)) {
    c = 5;
    }
    }
    O código acima quando compilado pode se transformar em algo semelhante a isso (boa parte do código acima é inútil, estou utilizando somente para exemplificar):

    Código:
    00000000 MOV EAX,4h ;move o valor 4 para EAX
    00000005 MOV EBX,6h ;move o valor 6 para EBX
    0000000A CMP EAX,4h ;compara EAX com 4, se for verdadeiro: ZF = 1
    0000000D JNE 00000019h ;se ZF != 1, pule para endereço 00000019h
    0000000F CMP EBX,6h ;compara EBX com 6, se for verdadeiro: ZF = 1
    00000012 JNE 00000019h ;se ZF != 1, pule para endereço 00000019h
    00000014 MOV ECX,5h ;move o valor 5 para ECX
    00000019 RETN ;finaliza execução e retorna
    Pra entender o código acima é necessário entender sobre aquilo que compõe a linguagem assembly. Ela é basicamente composta por registradores, endereços e instruções (mnemônicos).

    Os registradores foram explicados no capítulo anterior, mas vamos agora saber quem são eles. Os processadores da arquitetura Intel de 32 bits possuem basicamente nove registradores de 32 bits comuns: EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI e EIP. Teoricamente cada um desses registradores possui uma determinada “função padrão”, mas devido a sua escassez, muitas vezes eles são utilizados como registradores para qualquer propósito. Você pode criar um código usando livremente os oito primeiros registradores que não haverá muitos problemas (desde que saiba o que está fazendo/modificando). O último registrador, EIP, é quase sempre mantido intacto, pois ele é o responsável por contar as instruções e informar o endereço da próxima instrução. Alterar o seu valor pode desviar completamente o fluxo do aplicativo e provavelmente vai gerar uma falha de segmentação ou uma operação ilegal.

    Esses registradores apresentados são todos de 32 bits. No entanto também é possível utilizar apenas 8 ou 16 bits, como mostra a tabela abaixo utilizando o EAX como exemplo (a teoria vale para os outros registradores também):


    Para o caso da porção de 8 bits, o registrador terminado em L são os 8 bits menos significantes de AX e o terminado em H são os 8 bits mais significantes de AX. Para a porção de 16 bits, são utilizados os 16 bits menos significantes da porção de 32 bits.

    Além dos registradores, também existem as Flags, que são bits utilizados como resultado de operações (verdadeiro ou falso, por exemplo). Elas são usadas principalmente para análise condicional em instruções como CMP e TEST. Dentre as diversas flags, as mais corriqueiras são: ZF (Zero Flag), CF (Carry Flag) e SF (Signal Flag). A ZF é setada sempre que uma operação resulta em zero (uma comparação entre dois números através do comando CMP subtrai seus operandos sem alterar valores e seta a ZF caso o resultado da subtração seja zero, indicando valores iguais). A flag CF é setada quando o resultado de uma operação estoura o valor máximo comportado pelo registrador/local sem considerar o sinal (overflow). Por último, tempos a SF, que é ativada sempre que o bit mais significativo de um operando for 1, indicando um valor negativo (pesquise sobre complemento de dois).

    Os endereços na linguagem assembly são a base para o fluxo do aplicativo e para o armazenamento de dados. As variáveis que você usa durante a programação são substituídas por endereços que apontam para uma área da memória paginada com acesso a leitura e a escrita. Os destinos dos saltos (Jumps) também dependem dos endereços das instruções, pois é através deles que você informa o destino do salto.
    O código abaixo demonstra apenas uma linha de assembly onde é possível ver o endereço da instrução (00401000) e o endereço para um byte de memória (00403000) para o qual o número nove está sendo movido:

    Código:
    00401000 MOV BYTE PTR DS:[00403000], 09h
    Por último temos as instruções, que nada mais são do que os opcodes traduzidos em um mnemônico, como demonstrado e exemplificado alguns parágrafos acima.
    Abaixo eu vou por uma pequena lista mostrando algumas das instruções mais utilizadas, pois seria inviável colocar todas elas (são aproximadamente 130 instruções bases para a arquitetura Intel).
    MOV destino, origem
    Move o valor do campo origem para o destino. Essa instrução possui diversas variações, por isso ela pode aparecer de diversas formas diferentes (pode-se trabalhar com constantes, memória, pilha, etc). Alguns exemplos:

    MOV EAX, 10h
    MOV AX, WORD PTR DS:[00403000]
    MOV BYTE PTR DS:[00403002], 1Ch
    *CMP arg1, arg2

    Realiza uma comparação entre os dois operandos. A comparação é feita simplesmente subtraindo os dois operandos e caso o resultado for zero (valores iguais), ele seta a ZF para 1. Vale lembrar que essa operação não altera os valores dos operandos, apenas as flags.

    CMP EAX, 04h
    *JMP endereço
    Faz um salto incondicional e obrigatório para o endereço indicado.

    JMP 00401008h
    *JZ endereço / JE endereço
    Faz um salto condicional. Caso o valor da zero flag seja 1, ele realiza o salto. Normalmente utilizado junto com um CMP para realizar um desvio caso a comparação seja verdadeira.

    JE 0040101Ah
    *JNZ endereço / JNE endereço
    Semelhante ao item acima, mas realiza o salto somente quando a zero flag não foi setada (ZF = 0).

    JNZ 0040102Ch
    *ADD destino, arg1
    Adiciona o valor de arg1 ao destino. Também possui diversas variações, pelas mesmas razões do comando MOV. Se o resultado estourar o limite do destino, a CF é setada.
    ADD EBX, 04h
    ADD EBX, DWORD PTR DS:[00403032]
    *SUB destino, arg1
    Realiza uma subtração dos operandos. As variações e características são as mesmas do comando ADD.

    SUB ECX, 2Ah
    *PUSH valor
    Coloca o valor no topo da pilha (Stack). O comando PUSH é amplamente utilizado nas chamadas de funções (CALL), pois é através da pilha que a função busca seus argumentos.

    PUSH 08h
    *POP destino
    Remove o valor do topo da pilha e o armazena no destino.

    POP EAX
    *CALL local
    Faz chamada a uma função. É possível passar o local de diversas formas para o comando CALL, desde uma constante, registrador ou até mesmo uma função externa dentro de uma DLL. O comando CALL usa a pilha para indicar o endereço para o qual a função deve retornar depois de finalizada a sua execução.

    CALL User32!GetDlgItemTextA
    CALL 0040115Fh
    I admire most other programmers not paid any dick!!

    Admiro outros Programadores mais nao pago pau pra nenhum !!


    Skype: Vitor Monteiro

  2. The Following 5 Users Say Thank You to Vitrix Maggot For This Useful Post:


  3. #2
    h3ll0
    h3ll0 is offline
    Member-in-training
    Join Date
    2012 Jan
    Location
    Near pc ;)
    Posts
    57
    Thanks Thanks Given 
    39
    Thanks Thanks Received 
    13
    Thanked in
    10 Posts
    Rep Power
    0
    caralho , exelente post vitrix eu queria aprende algo sobre debugger pra aika noxtrap , vc ajudo demais da conta , vlw mesmo!!!!
    Knowledge is the best choice, give me the fish and I will be grateful for a moment or teach to fish and I will be grateful for a lifetime!


    Melhor escolha é o conheçimento,me de o peixe e eu serei grato por um momento ou ensine a pescar e eu serei grato o resto da vida!!

    If i Helped Give me a Thank

  4. #3
    CotocoV1
    CotocoV1 is offline
    Member-in-training CotocoV1's Avatar
    Join Date
    2012 Dec
    Location
    Everywhere
    Posts
    113
    Thanks Thanks Given 
    41
    Thanks Thanks Received 
    44
    Thanked in
    23 Posts
    Rep Power
    0
    Hey cara, poste os créditos por favor (http://www.hardware.com.br/comunidad...ebugger/785195)

    hey dude, post the credits please (http://www.hardware.com.br/comunidad...ebugger/785195)




  5. #4
    Vitrix Maggot
    Vitrix Maggot is offline
    Member-in-training Vitrix Maggot's Avatar
    Join Date
    2013 Apr
    Location
    Brasil
    Posts
    58
    Thanks Thanks Given 
    0
    Thanks Thanks Received 
    43
    Thanked in
    24 Posts
    Rep Power
    0
    o seu otario compara os topicos e ve se é igual
    I admire most other programmers not paid any dick!!

    Admiro outros Programadores mais nao pago pau pra nenhum !!


    Skype: Vitor Monteiro

  6. #5
    leeonardo
    leeonardo is offline
    Moderator leeonardo's Avatar
    Join Date
    2012 Jan
    Location
    Here I am.
    Posts
    2,219
    Thanks Thanks Given 
    48
    Thanks Thanks Received 
    3,122
    Thanked in
    737 Posts
    Rep Power
    15
    CotocoV1 is correct, the topics are the same.


    É pra ficar com medo?



    Apenas observo...



    Não faço nenhum tipo de venda de hack no jogo, então se in game ver algum "Leonardo PGC" não acredite, pois será alguém tentando te roubar.

  7. #6
    CotocoV1
    CotocoV1 is offline
    Member-in-training CotocoV1's Avatar
    Join Date
    2012 Dec
    Location
    Everywhere
    Posts
    113
    Thanks Thanks Given 
    41
    Thanks Thanks Received 
    44
    Thanked in
    23 Posts
    Rep Power
    0
    What need to call sucker? just put the credits and before you ask me to compare the topics you compare.

    Qual a necessidade de chamar de otário? é só colocar os créditos, e antes de pedir pra eu comparar os tópicos, compare você.

Similar Threads

  1. [Info] new OllyDbg v2.01f version is out
    By RunningCPU in forum Files & Tools
    Replies: 0
    Last Post: 2012-09-28, 10:36 AM
  2. [Guide] Guia básico para quem quer começar a jogar WoW
    By rampag3 in forum Português
    Replies: 1
    Last Post: 2012-09-13, 11:58 PM
  3. Replies: 11
    Last Post: 2012-09-04, 06:54 AM
  4. [Help] how to use ollydbg
    By OsosheO in forum General Game Research
    Replies: 1
    Last Post: 2012-08-23, 03:13 AM
  5. [Help] OllyDBG Beginner
    By rhu10 in forum Aika Online
    Replies: 6
    Last Post: 2011-09-05, 02:49 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •