Powerplay
Descrição do Desafio
Categoria: misc
Descrição:
Pump yourself up with power to get an inspirational quote.
Arquivos
chall.py
Código sendo executado no servidor.
solve.py
Script em Python que descobre o número correto.
📥 Download: Arquivos
Solução
O desafio disponibliza o seguinte código python.
import numpy as np
from secret import flag, quotes
prizes = quotes + ['missingno'] * 4 + [flag] * 24
if __name__ == '__main__':
print('Welcome to our playground for powerful people where you can pump yourself up and get awesome prizes!\n')
player_count = int(input('How many players participate?\n'))
power = np.zeros(player_count, dtype = np.int32)
for i in range(player_count):
power[i] = int(input(f'Player {i}, how strong are you right now?\n'))
ready = False
while True:
print('What do you want to do?\n1) pump up\n2) cash in')
option = int(input())
if option == 1:
power = power**2
ready = True
elif option == 2:
if not ready:
raise Exception('Nope, too weak')
for i in range(player_count):
if power[i] < len(quotes):
print(f'You got an inspiration: {prizes[power[i]]}')
exit()
else:
raise Exception('What?')
Analisando esse código, podemos ver que há um vetor prizes que contém várias strings e a flag 24 vezes no final, então, precisamos acessar alguma dessas posições em que a flag está.
Observando o funcionamento do código, é primeiro pedido do usuário a quantidade de jogadores e a "força" de cada jogador, após isso, o usuário pode escolher duas opções. A primeira opção "pump up" eleva todos as "forças" de todos os jogadores ao quadrado e a segunda opção "cash in" acessa uma posição do vetor prizes, porém, so irá acessar a posição caso a "força" do jogador seja menor que a quantidade de strings no vetor "quotes".
Portanto, precisamos escolher uma "força" que, ao elevar ao quadrado, resulte em uma posição em que a flag está no vetor de prizes, porém, como o vetor prizes contém todas as strings de quotes e o código não deixa o usuário acessar alguma posição que seja maior que o tamanho de quotes, não podemos acessar as posições que a flag está de maneira tradicional.
Para passar por essa verificação, podemos usar uma propriedade da linguagem python que é os índices negativos.
Desse modo, precisamos acessar alguma posição entre -1 e -24, que são as posições em que a flag se encontra. Porém, precisamos de algum número que, elevado ao quadrado, resulta em um número nesse intervalo. Podemos fazer isso utilizando integer overflow.
Como a variável power é definido commo um int de 32 bits, podemos encontrar algum número que, elevado ao quadrado, passa do valor máximo de inteiros de 32 bits e resulta em um número negativo. Para fazer isso, podemos fazer um script simples que testa todos os números de 0 até o maior inteiro possível de 32 bits e verifica se esse número ao quadrado se encaixa no intervalo de -24 a -1.
Ao rodar esse script, obtemos o seguinte output.
Agora, basta apenas conectar ao servidor e usar esse número como "força" de qualquer jogador
Flag: ENO{d0_n0t_be_s0_neg4t1ve_wh3n_y0u_sh0uld_be_pos1t1ve}
ENO{d0_n0t_be_s0_neg4t1ve_wh3n_y0u_sh0uld_be_pos1t1ve}Autor da WriteUp
Atualizado