Bem vindos ao Blog da comunidade ITsafe



Boa Leitura


Blog em em português sobre construção . Por favor se encontrar algo que necessite correção entre em contato. Os vídeos do blog ainda estão em hebraico, mas em breve estaremos traduzindo com a mesma qualidade que traduzimos os cursos.


Vencendo campo minado hackeando

O objetivo do jogo é destravar todo o tabuleiro sem acertar as minas espalhadas aleatoriamente pelo tabuleiro. Se você abrir um slot sem uma mina, ele será marcado com a quantidade de minas que estão próximas, assim:

O objetivo deste artigo é mostrar como resolver o jogo usando engenharia reversa e como localizar a função de vitória do jogo. Abaixo, mostrarei como construiremos um arquivo dll que injetaremos no software para nos permitir vencer assim que pressionarmos a tecla "mágica" selecionada.

Também apresentarei outra solução, escrevendo um loader para o software que nos permitirá vencer assim que pressionarmos a tecla "enter".

Abaixo está um vídeo que demonstra como realizar o processo:

Para baixar o jogo:

Neste artigo, usaremos 2 ferramentas:

  • WinDbg – Para conseguir realizar e-debugging
  • Ida – Para conseguir ler o código e a documentação

Além do fato de que no vídeo eu mostrei a vocês o processo de depuração usando OllyDbg, no artigo prefiro demonstrar como você pode fazer a mesma coisa usando WinDbg.

Antes de depurar, devemos examinar a funcionalidade do software que estamos pesquisando e tentar encontrar uma característica'Qualquer ou janela que possa nos ajudar a encontrar a funcionalidade que queremos explorar e não necessariamente explorar todo o jogo.

A janela do jogo é assim:

![](/img/tutorials/winmine-2.png)

Você pode ver que este jogo tem poucas funcionalidade:

  • Início de um novo jogo
  • Diferentes níveis de jogo
  • Cores e marcações
  • Áudio
  • Tabela de resultados

Se você marcar a opção Áudio e começar a tocar, você verá os seguintes sons:

  • O som do relógio
  • Som de mina
  • Som de vitória

Desta forma, é possível concluir que se encontrarmos a função responsável pelos sons, podemos voltar ao código e ver qual função foi chamada e assim encontrar a função de vitória do jogo.

Vamos abrir o jogo em-Windbg:

Não se esqueça de marcar o processo de gravação. Começamos o jogo, agora jogamos um pouco e fechamos a janela do jogo..

E assim que você se encontrará na janela windbg dentro da gravação da execução do jogo, a gravação permite que você se mova para frente e para trás enquanto roda (time travel debugging), Desta forma, você não terá que executar o software novamente se tiver perdido algo para o qual deseja retornar.

Agora precisamos encontrar todas as funções que o software usa: Essas funções estão em uma tabela chamada Import Address Table, esta tabela contém uma lista de todas as dlls que usamos, a função que usamos e, claro, o endereço da função.

Para chegar à tabela devemos primeiro encontrar os endereços do módulo que nos interessa (base address) Em seguida, adicionar a isso a distância (offset) Até a tabela, para fazer isso usaremos um comando:
!dh winmine

E obteremos o seguinte resultado:

Você pode ver que o endereço base é 0100 0000 e a distância da tabela é 1000. Além disso, o tamanho da tabela é 1B8, de modo que para imprimir a tabela usaremos o comando: dps 01000000+1000 01000000+1000+1B8

Claro que você também pode usar o nome do módulo em vez de escrever o endereço base porque ele realmente contém o endereço base, por exemplo, se escrevermos:
?winmine

Parece ser realmente igual ao seu próprio endereço de base, que é 0100 0000

Então você poderia escrever a mesma ordem: dps winmine+1000 winmine+1000+1B8

E o resultado será assim.:

Esta é basicamente uma lista de todas as funções que estão nas bibliotecas externas que o software usa, agora vamos realizar um ponto de interrupção na função PlaySoundW usando o comando: bp WINMM!PlaySoundW

E pressionar g para continuar executando o software. Irá ver que irá parar a função imediatamente antes de o jogo começar, provavelmente é o som do jogo que não está relacionado com a vitória pois ainda nem iniciamos o jogo em si.

Pressione g novamente e pressione a segunda função de call stack, esta é a função que realmente chamou- PlaySoundW:

Clique nele duas vezes e você passará para ele:

Pode-se observar que esta função recebe 3 tipos de sons de acordo com o valor esp+4]] E pule para o som usando je, para verificar o tipo de som iremos realizar um novo break point com as condições de impressão na primeira linha da função e examinaremos os sons que estamos recebendo atualmente: bp 010038ed ".echo SOUND VALUE; ?poi(@esp+4)"

Vamos agora reiniciar o software sem executar tudo novamente pressionando o botão reset e depois o botão go, então você verá que parou na linha desejada e imprimiu o som que é na verdade 1.

Escreva g nos comandos e você verá que parou novamente com 1

Comentário: Se você parou em PlaySoundW cancele o ponto de interrupção, usando bd 0 que é na verdade a sigla para desativar o ponto de interrupção e 0 é o número de pontos de interrupção da lista de pontos de interrupção que podem ser vistos usando o comando bl.
Continue a executar o comando g até perder o jogo, você notou que antes da perda você obteve o som 3?
Portanto, a tarefa é clara, precisamos encontrar uma função que possa nos devolver o som 2 que pode ser deduzido disso que esse é o som da vitória.

Voltamos usando: g-

Até o ponto no tempo em que foi impressos 3:

E vamos verificar qual função chamou este código, voltando no tempo com a ajuda do comando: t-

E assim que chegamos ao seguinte trecho de código:

Pode-se ver que este trecho de código é afetado por esi, então vamos inverter a lógica e ver o qual era o esi quando obtivemos o número 3:`

    eax = 3
    sub eax, 3
    adc eax, eax
    neg eax
    

`

E descobrimos que esi era na verdade 0, agora faremos o mesmo cálculo para o dígito 2 que queremos obter (Mesmas operações matemáticas, mas desta vez colocamos o número 2 em vez de 3 em eax)

![](/img/tutorials/winmine-14.png)

E nós temos 1 (Não se esqueça do-CF), Dê uma olhada na função, será que receber 1 no ESI é algo possível?

Pode-se ver que esi é afetado pelo argumento que passa para a função, então já aqui o exercício pode ser resolvido realizando um breakpoint na linha 01003488 e alterando o valor esi para 1.

Ou apenas crie uma dll que execute a função 0100347c com o argumento 1.

Testaremos nossa funcão agora executando o software novamente, porém sem viajar no tempo desta vez:

Antes de jogar usando g, execute um break point na linha 0100347c e ative o jogo pelo comando g, agora tente localizar uma mina e você verá que o jogo parou em nosso break point:

![](/img/tutorials/winmine-17.png)

Execute step into 3 vezes atravez do comando:
t

E você verá que alcançamos exatamente a linha 01003488 e esi é igual a 0 exatamente como calculamos.

Agora mude o valor de esi usando o comando: r esi=1

Para ver, escreva r, que será assim:

Agora continue o jogo pelo comando g, e você ouvirá o som da vitória do jogo:

Vamos voltar uma função e tentar entender o que faz com que o jogo envie 1 para a nossa função, clique em
t-

Até você voltar uma função e chegar aqui:

É hora de abrir um IDA e olhar para o mesmo endereço usando G, que vai ser assim.:

Você pode ver que a função sabe receber 1 e 0, vamos até o topo da função e realizar um breakpoint na linha 01003512:

Dentro do WinDbg assim:
bp 01003512

Jogue o jogo até parar no breakpoint, agora execute o comando uf para que possamos ver as funções confortavelmente:
Você pode ver que temos uma condição interessante que verifica se o slot que abrimos é igual a 80. Se não for igual há um salto para a área que pode potencialmente retornar 1 caso contrário continuamos normais no código e alcançamos a área que nos retorna 0.

Para testar o código de forma eficaz, realizaremos 2 break points inteligentes, o primeiro nos mostrará o valor da comparação e o segundo nos mostrará quanto vale o eax antes de decidir retornar 1 na próxima seção:

O primeiro breakpoint é assim:
bp 01003529 ".echo VALUE; db @edx L 1 ;gc"
E o outro é assim:
bp 010035A1 ".echo CMP; ?@eax; gc"
Brinque um pouco no jogo e examine os valores impressos:

Você pode ver que perdemos assim que clicamos em um slot que tinha uma mina e além disso o valor que apareceu no depurador era 80, nas outras vezes que abrimos slots sem uma mina o valor era 0.
Como você pode ver, a entrada no CMP exibia 12 assim que 12 slots fossem abertos clicando na placa. Em seguida, abri um único slot e o valor exibido foi 13 e, novamente, um slot e então cheguei a 14. Parece haver 14 campos abertos (Sinta-se à vontade para contar 😊)

Então o jogo basicamente decide que ganhamos assim que conseguimos abrir todos os campos do jogo sem acertar o campo que valia 80.

A comparação é feita com um número em 010057a0, que é afetado pelo tamanho do tabuleiro que você escolhe no menu..


No próximo artigo iremos construir uma dll para injetar no jogo e até mesmo escrever um carregador que irá carregar o jogo e vencer para nós.

Compartilhe este post