Just Parry Lol

Descrição do Desafio:

Categoria: pwn Descrição:

Welcome, warrior. Inspired by his favorite game, For Honor, my friend made a turn-based combat simulator to familiarize people with frame data. However, the system is against you. Every move you make is just too slow. You have one secret tool: the ability to manipulate time.

Can you win the fight and retrieve the flag?

Arquivos

Arquivo
Descrição

JustParryLol

Executável.

📥 Download: Arquivos

Passo a Passo da Solução

1. Análise do arquivo fornecido

O desafio nos fornece apenas um executável. Ao executá-lo, o programa apresenta a seguinte interface:

=== Frame Trap ===
The bot is overwhelming... there's no fair way to win.
Enter your warrior name: HenriUz
Choose your action:
(1) Heavy Attack
(2) Light Attack
(3) Guard Break
(4) Block
(5) Parry
(6) Dodge
Enter choice: 1

[TURN 1]
Bot uses: Heavy Attack
You use: Heavy Attack
[DEBUG] Player startup: 633 (recovery 0 + startup 433 + penalty 200)
[DEBUG] Bot startup: 433 (recovery 0 + startup 433)
The bot hits you for 30 damage. Your health: 70
Choose your action:
(1) Heavy Attack
(2) Light Attack
(3) Guard Break
(4) Block
(5) Parry
(6) Dodge
Enter choice: 2

[TURN 2]
Bot uses: Heavy Attack
You use: Light Attack
[DEBUG] Player startup: 667 (recovery 267 + startup 200 + penalty 200)
[DEBUG] Bot startup: 700 (recovery 267 + startup 433)
You hit the bot for 15 damage. Bot health: 85
Choose your action:
(1) Heavy Attack
(2) Light Attack
(3) Guard Break
(4) Block
(5) Parry
(6) Dodge
Enter choice:

O jogo segue em um loop, solicitando novas ações a cada turno. Contudo, independentemente da escolha do jogador, o bot sempre vence. Com isso, devemos analisar como é a lógica disso por meio do Ghidra, ou outra ferramenta similar.

Ao abrir o binário no Ghidra, identificamos a função FUN_00401150() como sendo a main(). O código decompilado gerado inclui um switch que controla o estado interno do jogo (DAT_004042c4), mas a estrutura não é realmente um switch tradicional — as execuções ocorrem sequencialmente:

A função principal de lógica é a FUN_00401620(). Nela, algumas comparações são realizadas, e determinam quem acerta quem, porém há uma comparação com valores "mágicos" que chama a atenção:

O valor 0x72726150 em little-endian corresponde à string "Parr" e 0x79 é o caractere 'y'. Ou seja, esse trecho está verificando se o jogador usou o movimento "Parry". E se usou, uma nova comparação é feita usando a variável DAT_004042d4, e neste caso se ela for diferente de 0, o bot é quem leva o dano.

Procurando onde essa variável é modificada, podemos notar que é na função de entrada do usuário.

E por mais que está função tenha a vulnerabilidade de buffer overflow, o objetivo aqui é apenas digitar "AUTOPARRY" no nome e pronto, modificamos a variável.

2. Exploit

Seguindo o que foi descoberto acima, obtemos o seguinte resultado:

Flag

DawgCTF{fr4me_d4ta_m4nipulat10n}

Autor da WriteUp

Membro de Exploitation - HenriUz

Atualizado