[LHC] [ESP8266 grátis!] Desafio para crackear programas

Leandro A. F. Pereira leandro at tia.mat.br
Fri Mar 17 07:43:29 PDT 2017


2017-03-16 19:31 GMT-07:00 Leandro A. F. Pereira <leandro at tia.mat.br>:
> Bom, passou o tempo, então vamos lá --

Uma coisa que esqueci de falar no email anterior: dá pra converter o
programa num keygen também. Ao invés fazer a chamada para strcmp(), é
só fazer a chamada pra puts(). Vamos patchear e ver o que acontece:

O código original é esse:

  400333:       e8 54 1d 00 00          callq  40208c <snprintf>
  400338:       48 89 e6                mov    %rsp,%rsi
  40033b:       48 89 df                mov    %rbx,%rdi
  40033e:       e8 ad 39 00 00          callq  403cf0 <strcmp>
  400343:       85 c0                   test   %eax,%eax
  400345:       41 89 c5                mov    %eax,%r13d
  400348:       74 0c                   je     400356 <main+0x202>
  40034a:       bf 3a 4f 40 00          mov    $0x404f3a,%edi
  40034f:       e8 b3 1c 00 00          callq  402007 <puts>

E tem uma chamada pra puts() ali no final, então vamos trocar
"AD39000085" por "C41C0000C3". (É 0xc4 ao invés de 0xb3 pois é um
offset relativo à posição atual.) 85 é o opcode pra instrução "test",
e C3 é da instrução "ret". Desse jeito o programa imprime o serial e
sai, se tudo der certo. Editando o arquivo e rodando, olha o que
acontece:

    $ ./crack1
    something something something

Bom, imprimiu alguma coisa, que é o serial errado que tá no arquivo de
configuração. Deve ser por que o strcmp() pega dois parâmetros e o
primeiro deve ser o que veio do arquivo.

Vamos ver quem é quem: https://en.wikipedia.org/wiki/X86_calling_conventions

Em x86-64, no Linux, segundo a tabela listando as convenções de
chamada, dá pra ver que os argumentos ficam em ordem no RDI, RSI, e
outros registradores. Então essa string que tá sendo impressa aí tá no
RDI, e queremos a que tá no RSI. Olhando no código ali em cima dá pra
ver que RSI passa a ter o valor do RSP. Isso faz sentido, pois o RSP é
o registrador que aponta para o topo da pilha e o número de série pode
ter sido gerado nela.

Vamos trocar uma das sequências para "mov %rsp,%rdi"... só que é mais
fácil procurar no próprio disassembly se tem essa sequencia, aí não
precisa codificar nós mesmos.

E por sorte, tem:

  400327:       48 89 e7                mov    %rsp,%rdi

OK, vamos trocar então 4889DF por 4889E7 e ver o que acontece.

  $ ./crack1
  15424-09687-6039

Parece que temos um keygen agora. Vamos confirmar:

  $ rm crack1
  $ cp crack1.orig crack1
  (modifica o ~/.crack1rc para conter o serial que geramos)
  $ ./crack1
    This program is registered to:
             Name: John Smith

    Serial number: 15424-09687-6039

     License type: Enterprise


Opa, o keygen funciona -- e a gente nem teve que descobrir qual era o algoritmo.

Aqui tá todo o código fonte do programa, em C, e aí dá pra seguir
melhor o disassembly: https://hastebin.com/ufejikitis.cpp

-- 
 Leandro



More information about the HSC mailing list