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
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
Atualizado