Unconfigured Ad Widget

Collapse

Anúncio

Collapse
No announcement yet.

Iniciação prática ao debug e cracking

Collapse
X
 
  • Filter
  • Tempo
  • Show
Clear All
new posts

  • Font Size
    #1

    Tutorial Iniciação prática ao debug e cracking

    Olá.
    Teremos agora uma iniciação prática às funções de um debugger. Isto quer dizer que não vou estar falando a fundo sobre tudo o que é possível fazer (impossível), e nem dar conceitos da linguagem Assembly.
    Mas claro que ninguém vai ficar desnorteado. Vamos dar uma introdução ao conceito de "debug".
    Inicialmente, é bom dizer que debugger não é o mesmo que disassembler.
    Um disassembler transforma a linguagem de máquina, transcritas das instruções enviadas ao processador, para a linguagem Assembly, diferentemente da de máquina, legível por humanos.
    Já debuggers analisam e testam aplicativos. Se você trabalha com programação já deve ter trabalhado com um, pois qualquer boa IDE sempre traz um consigo. São muito utilizados para tratamento de erros.
    Debuggers de executáveis já compiladas (binários) trabalham da mesma forma, mas utilizam-se de um disassembler antes de executar sua ação.
    Nenhum desses pode ser confundido com um decompiler.

    Conceitos básicos
    Ok, agora sou professor de curso de informática de esquina.
    Sabe o que é e qual a função da memória RAM? Claro que sabe, mas vamos encher linguiça.
    A memória RAM (memória de acesso aleatório) é volátil, servindo como armazenamento temporário de arquivos, programas e dados de programas em execução.
    O processador é o cérebro do computador, executando instruções e operações.
    Endereçamento de memória é uma espécie de tabela que indica ao processaodr onde está localizado, na memória, determinado dado.
    A pilha é uma estrutura de armazenamento de dados. Você já deve ter ouvido falar em "estouro de pilha", não é mesmo?
    Registradores são peças de memória localizados no processador, de uso temporário para realização de operações. Processadores de 32 bits conseguem guardar 32 bits em cada registrador. Processadores de 64 bits...
    Os registradores têm alta velocidade de acesso. Sua capacidade (e quantidade) dependem totalmente do processador.
    Por exemplo, um processador i386, de 32 bits da Intel, possuem 9 registradores de 32 bits. São eles: EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI e EIP.
    Na teoria, cada qual possui sua função, mas na prática todos eles são usados como qualquer um, já que o programador pode usá-los como bem entender, com apenas uma restrição: não mexer no último registrador (EIP), pois ele tem a função de endereçamento de instruções. Se você alterá-lo, o fluxo de execução de seu programa vai ser alterado, podendo gerar uma operação ilegal ou falha de segmentação.

    Assembly básico
    Claro que não vamos ver muita coisa em Assembly, apenas uma introdução.
    No entanto, aconselho a você que aprofunde seus estudos nessa linguagem, se realmente esta área lhe interessar.
    É uma linguagem de baixo nível (alta perfórmance, sintaxe diferente da linguagem humana, trabalha diretamente com a arquitetura e registradores do processador), que lê os opcodes (códigos operacionais, instruções enviadas e interpretadas pelo processador) e converte-os para suas mnemónicas (palavras reservadas da linguagem que constituem a sintaxe).
    O Asm tem sua dificuldade na sintaxe, que não é o que você está acostumado a ver. Pense em "goto" do Basic, AutoIt1-2 e Batch. É naquele estilo.
    Os debuggers atuais podem comentar o código e demarcá-lo, facilitando o trabalho. Mas não é nada que dispense o olhar, papel e caneta.
    Por mais que você dê um nome para uma variável enquanto programava um software, na hora de compilar ele é convertido para o endereço na memória o qual a variável ocupa. Cada instrução tem seu endereço, e é nesta base que trabalham os JUMPS (saltos).

    Vamos ver agora algumas das instruções bases (algo como funções nativas).

    MOV destino,origem
    Move o valor de um campo para outro, podendo-se trabalhar com constantes, valores, pilhas etc.
    CMP/TEST string1,string2
    Como a função strcmp() do C, realiza uma comparação entre os dois argumentos.
    No caso do TEST, pode também verificar se um valor é menor que o outro (e, logicamente, se é maior que o outro).
    A instrução CMP realiza apenas uma subtração entre os dois valores. Se o resultado for zero, os dois valores são iguais (12345-12345=0 :. 12345=12345).
    JMP endereco
    Salta para um determinado endereço (veremos sobre endereços logo a seguir).
    JE/JZ endereço
    (Jump if Equal) salta para um endereço se a última comparação retornou verdadeiro.
    JNE/JNZ endereço
    (Jump if Not Equal) salta para um endereço se a última comparação retornou negativo.
    ADD/SUB/MUL/DIV destino,valor
    Realiza uma das 4 operações básicas.
    PUSH valor
    Adiciona o valor para o topo da pilha, muito utilizada nas chamadas (CALL), já que uma função busca seus argumentos através das pilhas.
    POP valor
    Remove o valor do topo da pilha. Note que, como em uma pilha de livros, você só pode acessar dados na pilha do último ao primeiro.
    CALL func
    Chama uma função interna ou externa (de uma DLL).

    Claro que há muito mais instruções, mas esta são as que mais veremos.

    Já falamos sobre registradores, mas além deles temos também as chamadas flags, bits comumente usados como resultados das operações (um booleano - 1 (verdadeiro) ou 0 (falso) - por exemplo). Por isso são usadas em comparações (CMP/TEST). As mais conhecidas são:
    ZF/Z
    Uma operação resultou em zero (no caso de uma CMP, os dois valores são iguais).
    CF/C
    O resultado de uma operação estourou o valor máximo suportado pelo registrador (um overflow).
    SF/S
    Indica um valor negativo.

    Todos os aplicativos em ASM são baseados em um endereçamento. Variáveis que você cria durante o desenvolvimento transformam-se em endereços (uma árae da memória). Os saltos (JMP) também trabalham com esses endereços.

    OllyDbg
    Vamos agora conhecer a interface principal do Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar....
    Claro que a curiosidade vai ajudá-lo mais do que qualquer tutorial. Aqui vou apenas mostrar por onde iniciar.
    A janela é dividida entre algumas seções.
    A primeira delas possui 4 colunas e é ali onde veremos o código Assembly do programa.
    A primeira coluna exibe os endereços em que a linha estão.
    A segunda coluna exibe o hex dump da instrução. Você vai reparar que existem certos padrões. Por exemplo, "PUSH 0" é sempre representado como "6A 00". Quando usados valores numéricos inteiros como argumentos, a instrução "PUSH" é sempre representada como "6A", seguido da representação do argumento. Isto porque é assim que o disassembler trabalha: gera um hex dump do arquivo e vai procurando por padrões.
    A terceira coluna é nada menos do que o código Assembly daquela instrução.
    A quarta coluna possui comentários do debugger de grande valia para nós.
    Bem ao lado deste frame nós temos uma área ("Registers") que mostra os registradores e flags, sendo atualizada durante a execução do aplicativo.
    Abaixo temos dois frames. O primeiro deles exibe a memória RAM usada pelo aplicativo, byte por byte.
    Com três colunas, exibe o endereço, a representação hexadecimal (8 bytes/linha) e a representação ASCII.
    O último frame (mas muito importante) exibe o estado da pilha.
    A pilha é muito utilizada para passagem de parâmetros (argumentos) para funções.
    Possui 3 colunas, exibindo o endereço, o valor e um importante comentário feito pelo debugger.

    Para abrir um arquivo binário pelo Olly você deve arrastá-lo para seu ícone ou usar o comando "Open" (File > Open).
    Vamos ressaltar que o que vai ajudá-lo agora é a sua própria curiosidade. Crie pequenos programas, compile e jogue para dentro. Boa sorte nos estudos.

    Vamos nessa?
    Vou agora iniciá-lo no debug, crackeando 2 pseudo-softwares.

    Os dois pseudo-softwares são crackme's (feito especialmente para serem crackeados).
    No primeiro há um serial estático, que precisamos saber. No segundo, o serial não é estático. Como ele pede também o nome, julgamos que o serial é calculado a partir deste dado.
    Estarei usando o Olly Debugger.

    Os dois crackme's foram desenvolvidos por mim em C. Não têm interface gráfica por preguiça. Você pode baixá-los com o código-fonte Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar.... É claro que você não vai olhar o código-fonte antes de vencê-los, ou vai perder a graça (e o problema vai ser seu!).

    Serial estático
    É impossível que ainda exista isso, mas não improvável. Além disso, precisamos iniciar da forma mais simples.
    Vamos então abrir o arquivo "estatico.exe".
    Aparece uma janela dizendo "Insira o serial".
    Não temos ideia de qual seja esse serial, portanto, vamos digitar qualquer coisa: "oleodehamburguer".
    Apareceu uma janela de título "CrackMe" e texto "Errado!", uma MessageBox padrão do Windows. É muito importante guardar tipos e textos de mensagens de erro.
    Vamos clicar no Ok e sair do programa.
    Arraste o arquivo "estatico.exe" para a frente do ícone do OllyDbg. Em pouco tempo ele mostrará o nosso programa, em Assembly, no maior frame (principal) da janela.
    Precisamos encontrar aquela mensagem de erro, para definir o que foi que a causou.
    Clique com o botão direito do mouse no frame principal > Search for > All referenced text strings.
    Lembre-se de que este não é a única forma de encontrar um erro. Alguns softwares apenas fecham. Você poderia usar o "All intermodular calls" e procurar por um ExitProcess. Mas não vem ao caso, agora.
    Note que é exibida uma tabela com textos presentes no programa. Você deve conhecer alguns e outros não.
    O que era exibido na mensagem de erro? Perceba que o texto que procuramos ("Errado!") está indicado ali da seguinte forma:
    Código:
    ASCII "Errado!"
    Clique duas vezes nessa string. Veja que foi selecionada uma linha onde encontramos nosso texto nos comentários. No final, é chamada a função MessageBoxA. Interessante...
    Logo em seguida vemos uma MessageBox com o texto "Correto!", que é o que queremos. Mas o que foi que causou isso?
    Podemos procurar por um CMP ou TEST, mas já disse que desenvolvi este crackme em C. A função de comparação usada no C é strcmp().
    Linhas antes dos MessageBoxes, vemos nos comentários (logo abaixo de 'puts' - uma função que envia um texto para a saída - e gets() - uma função que obtém entrada do teclado) a função que procuramos (strcmp()).
    Agora é simples: vamos criar um breakpoint naquela linha onde está o strcmp() e ver o que se passava na memória do computador.
    Um breakpoint (ponto de parada) indica ao debugger que, quando ele chegar naquela parte do código, ele irá pausar a execução e selecionar a linha onde esteve. Após uma pausa, você pode usar os controles de Play/Pause na barra de ferramentas para continuar a execução, ou Debug > Restart na barra de menu para reiniciar a execução.
    Para criar um breakpoint, selecione a linha onde está o strcmp, clique com o botão direito > Breakpoint > Toggle ou simplesmente pressione F2. Note que o endereço será marcado com uma cor diferente.
    Tudo certo? Clique no botão de play na barra de ferramentas e, na barra de tarefas, veja a janela do nosso aplicativo.
    Insira um serial qualquer, mas que você possa reconhecer posteriormente, como AAAAAAAAAAAAAAAAAAAA.
    Note que a execução foi pausada e a linha com nosso breakpoint (strcmp) foi selecionada. No frame de memória RAM, veja que interessante que encontramos:

    Ali existem duas strings (s1 e s2). Uma corresponde ao que digitamos, e a outra possui o valor "SMURF".
    Feche o Olly (oi minimize), abra o nosso aplicativo e digite nosso serial: SMURF. Resultado: "Correto!"

    Serial dinâmico
    Agora a coisa poderia complicar um pouco.
    Geralmente quando se fala em serial dinâmico, é difícil se gerar um serial e no final se comparar com o serial digitado - e pronto (mesmo que você possa encontrar isso em softwares de pequenas empresas).
    Normalmente vai se fazendo testes com o serial, como por exemplo se o primeiro número é par, se o segundo caractere é uma letra de G a L, se o terceiro número é um número primo, se dividindo-se o quarto com o último número se obtém resto 3, e por aí vai...
    Mas aqui vamos ver um exemplo bem simples, onde se é gerado um serial a partir do nome digitado e se compara com o serial digitado.
    Não vamos fazer um keygen, afinal, este tutorial é apenas uma iniciação. Por enquanto, vamos apenas conseguir um serial para nosso nome.
    Claro que você pode se aventurar pelo Assembly gerado e, com um básico conhecimento em C, entender a fórmula que eu uso para converter um nome em um serial (e eu recomendo isso). Mas, como dizia Chuck Norris, "vamos por partes".
    Execute o arquivo "dinamico.exe". Note que ele pede um nome e um serial. Digite qualquer dados.
    Nos foi exibida uma MessageBox de título "CrackMe" e texto "Errado!".
    Como anteriormente, botão direito no frame principal > Search for > All referenced text strings. Procure por "Errado!" e clique duas vezes sobre sua linha.
    Note que a função MessageBoxA é chamada apenas uma vez. Antes, o valor "Errado!" ou "Correto!" é transferido para uma variável e enviado na chamada à função. Viu como são importantes os comentários?
    Não vamos fazer diferente dessa vez. Procure por uma chamada à função strcmp pouco antes da string "Errado!" e ali crie um breakpoint.
    Execute o programa, digite seu nome/nick e um serial qualquer. Quando pausar a execução, lembre-se de que você tem o direito de saber o que se passa na memória do seu computador.
    Para meu nickname (0KaL), veja o serial válido:

    Note que se perde todos os hífens ("-") digitados. Além disso, se pedem apenas 16 caracteres (sem contar com os hífens), e o serial válido possui 4 a mais do que isso.
    Assim, conte de trás para frente os 16 primeiros caracteres. Note que ficaram de fora desde o primeiro "S" até o primeiro "w".
    Agora, separe o serial em grupos de 4 caracteres, concatenados por hífens. Resultado: 416b-403c-416b-403C.
    É bem provável que para o nome que você digitou o serial seja diferente. Vamos testá-lo? Anote-o em algum pedaço de papel, feche o Olly, execute o programa e teste : )
    Mas agora vamos explicar um pouco mais as linhas ao redor do "Errado!":
    Código:
    00401643  |. E8 E8050000    CALL <JMP.&msvcrt.strcmp>                ; |\strcmp
    00401648  |. 85C0           TEST EAX,EAX                             ; |
    0040164A  |. 74 18          JE SHORT dinamico.00401664               ; |
    0040164C  |. C74424 04 4731>MOV DWORD PTR SS:[ESP+4],dinamico.004031>; |ASCII "Errado!"
    00401654  |. 8D85 A8FAFFFF  LEA EAX,DWORD PTR SS:[EBP-558]           ; |
    0040165A  |. 890424         MOV DWORD PTR SS:[ESP],EAX               ; |
    0040165D  |. E8 EE050000    CALL <JMP.&msvcrt.strcpy>                ; \strcpy
    00401662  |. EB 16          JMP SHORT dinamico.0040167A
    00401664  |> C74424 04 4F31>MOV DWORD PTR SS:[ESP+4],dinamico.004031>; |ASCII "Correto!"
    0040166C  |. 8D85 A8FAFFFF  LEA EAX,DWORD PTR SS:[EBP-558]           ; |
    00401672  |. 890424         MOV DWORD PTR SS:[ESP],EAX               ; |
    00401675  |. E8 D6050000    CALL <JMP.&msvcrt.strcpy>                ; \strcpy
    Vemos primeiro uma chamada à função strcmp(), que compara se duas strings são iguais.
    No C, caso as strings sejam iguais, a função retorna zero (0). No Assembly, o resultado é jogado no registrador "EAX".
    Então, vemos um TEST EAX,EAX, seguido de um Jump if Equal. Ou seja, se o TEST EAX,EAX (resultado da strcmp()) for 0, pule pare o endereço 00401664. Caso contrário, continue normalmente.
    Mas o que existe no endereço 00401664? Note que ele também foi copiado no pedaço de código acima, com o comentário 'ASCII "Correto!"'.
    Mas o que acha de, ao invés de liberar um nome + serial válido, permitir ao usuário que digite qualquer coisa, fazendo o programa aceitar qualquer serial, sem validá-lo? Veremos agora.

    Patch
    Apesar de alguns acharem que o entendimento de fórmulas e liberação de seriais ou keygens sejam as formas mais legais de se promover o cracking, eu particularmente sempre gostei da arte de alterar executáveis, manipulando suas instruções. Isso parte de cada um.
    O que vamos ver aqui não é nada difícil. Vimos pouco acima que temos uma condicional TEST seguida de um JE. O JE (Jump if Equal) neste caso indica o endereço para o qual o processador irá saltar, caso a condicional anterior seja verdadeira.
    Então podemos fazer diferente: ao invés de saltar se for igual, saltar de qualquer maneira.
    Clique duas vezes na linha 0040164A (a linha que contém o JE). Na janela que aparece há uma caixa de texto com o seguinte:
    Código:
    JE SHORT 00401664
    Nossa linha de raciocínio: não pule se igual. Pule de qualquer forma.
    Desta forma, substitua "JE" por "JMP" (Jump - mas independente de If Equal), ficando:
    Código:
    JMP SHORT 00401664
    Correto?
    Se a caixa "Fill with NOP's" não estiver marcada, marque-a. Ela serve para completar bits restantes com "NOP" (No Operation - não faça nada).
    Clique no botão Assembly e agora vamos salvar o arquivo.
    Para isso, clique com o botão direito do mouse no frame principal > Copy to executable > All modifications. Clique em "Copy all".
    Vai aparecer uma outra janela com o código assembly do programa. Clique com o botão direito nela > Save file. Selecione onde salvar seu novo arquivo.
    Execute o arquivo que você acabou de salvar. Ele vai pedir o nome e o serial. Digite qualquer coisa e, veja que fantástico!, ele aceitou!

    -+-

    Como eu já disse, esta foi apenas uma introdução básica.
    Continue pesquisando e aprendendo.
    Escovem os dentes após cada refeição e mantenham as mãos limpas.

    Até a próxima!
    Este material pode ser compartilhado, desde que os devidos créditos sejam dados.



    Notify-list · Twitter · Blog

    Nova lei: Invadir computadores protegidos é crime.
    Lógica: Se eu invadi, não é protegido. Logo, não é crime :-)
    Similar Threads

  • Font Size
    #2
    gostei muito 0kal vo fcar no aaguardo de mais em...*.*
    sigpicToda verdade passa por três estágios. Primeiramente, é ridicularizada. Em segundo lugar, é violentamente confrontada. Por último, torna-se aceita como evidência

    Comment


    • Font Size
      #3
      muito bom! tenho bastante interesse em aprender sobre essa área, e estou caminhando devagar no meu rítmo. Obrigado por compartilhar.

      Comment


      • Font Size
        #4
        Isso mesmo filho, aprendeu direitinho comigo, rsrs.
        Obs: Não li nada, tá muito grande e cansativo de lê, kkkk...
        "Nunca desista de seus sonhos. Desisti de seus sonhos é abrir mão da felicidade."
        (Augusto Cury)



        Meu Blog... http://www.lab-infor.blogspot.com
        Meu canal do Youtube... http://www.youtube.com/user/rodrigo32323232

        Comment


        • Font Size
          #5
          Dei um obrigado apenas pela boa iniciativa de escrever o post!
          Porque existe muitos tutoriais na internet, mas alguém para compartilhar seu ponto de vista, existe poucos.

          Parabéns e.. keep fine working guy!

          []'s


          Reversing is my life!
          brcrackers.org

          Comment


          • Font Size
            #6
            Ei Boy, VC é muito bom... Parabens pelo seu post!

            Comment


            • Font Size
              #7
              Não tinha visto isso ainda.... pq isso não está fixo? Deveria estar

              Comment


              • Font Size
                #8
                Tá muito bom parabéns, bem explicado, gostei de ver.
                Bom matéria introdutória geralmente só encontramos esse tipo em inglês, (coisa necessária no dia de hoje) mas que muitos ainda pecam.

                Comment


                • Font Size
                  #9
                  parabéns carra boa iniciativa, será que rola uma segunda parte?

                  Comment


                  • Font Size
                    #10
                    Obrigado a todos =)

                    parabéns carra boa iniciativa, será que rola uma segunda parte?
                    Opa, com certeza. Já estou planejando exemplos com programas reais. Em pouco tempo já posto.
                    Este material pode ser compartilhado, desde que os devidos créditos sejam dados.



                    Notify-list · Twitter · Blog

                    Nova lei: Invadir computadores protegidos é crime.
                    Lógica: Se eu invadi, não é protegido. Logo, não é crime :-)

                    Comment

                    X
                    Working...
                    X