The PROM

Catégorie: Hardware Difficulté: medium Flag: HTB{AT28C16_EEPROM_s3c23t_1d!!!}

Challenge

Description


After entering the door, you navigate through the building, evading guards, and quickly locate the server room in the basement. Despite easy bypassing of security measures and cameras, laser motion sensors pose a challenge. They're controlled by a small 8-bit computer equipped with AT28C16 a well-known EEPROM as its control unit. Can you uncover the EEPROM's secrets?

Résolution

On a devant nous une mémoire EEPROM de type AT28C16. Un rapide tour sur la documentation nous permet de voir ses caractéristiques :

Tous les input pins fonctionnent en 5V sauf le A9 et le OE qui peuvent être monté jusqu’à 12V

On lit également qu’il existe 32 octets réservés à l’identification, c’est ici que se cache le flag

Pour ce faire il faut :

  • Mettre le pin A9 à 12V (en HIGH)

  • Et lire l’adresse de 0x7e0 à 0x7FF

Pour être en mode lecture justement, il faut mettre les pins :

  • CE et OE à LOW

  • WE à HIGH (donc 5V)

Concernant l’adresse, ce sont des les pins de A10 à A0 qui servent à la paramétrer (A10 étant le haut de l’adresse) :

  • 0x7e0 : 0b11111100000

  • 0x7ff : 0b11111111111


Script de résolution

from pwnlib.tubes.remote import remote
import re

# On fonction en 5V
LOW = 0
HIGH = 5

def resolve_address(address: int) -> list[int]:
	address = [5 if b == '1' else 0 for b in bin(address)[2:].zfill(10)]
	# Mettre A9 à 12V pour la lecture
	address[1] = 12
	return address

def parse_read(data: str) -> str:
	b = re.search(r"Read (.*) at", data)
	if b is None:
		return ""
	return bytes.fromhex(b.group(1)[2:]).decode()

def solve(host: str, port: int) -> None:
	# Connection au challenge
	client = remote(host, port)

	# Fonction pour envoyer des commandes et récupérer la sortie
	def send_commands(commands: list[str]) -> str:
		_output = []
		for command in commands:
			_output.append(client.sendlineafter(b'> ', command.encode()).decode() + f"{command}")
			if "read_byte" in command:
				_output.append(client.recvline().decode())
		return '\n'.join(_output)

	# Envoie des commandes pour Setup les pin CE / OE / WE
	print(send_commands([
		f"set_ce_pin({LOW})",
		f"set_oe_pin({LOW})",
		f"set_we_pin({HIGH})"
	]))

	flag = ""
	for address in range(0x7e0, 0x7ff+1):
	  # Paramètrage de l'adresse à lire puis lecture
		output = send_commands([
			f"set_address_pins({resolve_address(address)})",
			f"read_byte()"
		])
		print(output)
		# Parsing de la sortie pour récupérer l'octer lu
		flag += parse_read(output)
	print(f"Flag: {flag}")

if __name__ == '__main__':
	solve('94.237.53.3', 43523)

      AT28C16 EEPROMs
       _____   _____
      |     \_/     |
A7   [| 1        24 |] VCC
A6   [| 2        23 |] A8
A5   [| 3        22 |] A9
A4   [| 4        21 |] !WE
A3   [| 5        20 |] !OE
A2   [| 6        19 |] A10
A1   [| 7        18 |] !CE
A0   [| 8        17 |] I/O7
I/O0 [| 9        16 |] I/O6
I/O1 [| 10       15 |] I/O5
I/O2 [| 11       14 |] I/O4
GND  [| 12       13 |] I/O3
      |_____________|

> set_ce_pin(0)
help

Usage:
  method_name(argument)

EEPROM COMMANDS:
  set_address_pins(address)  Sets the address pins from A10 to A0 to the specified values.
  set_ce_pin(volts)          Sets the CE (Chip Enable) pin voltage to the specified value.
  set_oe_pin(volts)          Sets the OE (Output Enable) pin voltage to the specified value.
  set_we_pin(volts)          Sets the WE (Write Enable) pin voltage to the specified value.
  set_io_pins(data)          Sets the I/O (Input/Output) pins to the specified data values.
  read_byte()                Reads a byte from the memory at the current address.
  write_byte()               Writes the current data to the memory at the current address.
  help                       Displays this help menu.

Examples: 
  set_ce_pin(3.5)
  set_io_pins([0, 5.1, 3, 0, 0, 3.1, 2, 4.2])

> set_oe_pin(0)
> set_we_pin(5)
> set_address_pins([5, 12, 5, 5, 5, 5, 0, 0, 0, 0, 0])
> read_byte()
> Read 0x48 at address 0x7e0

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 0, 0, 0, 5])
> read_byte()
Read 0x54 at address 0x7e1

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 0, 0, 5, 0])
> read_byte()
Read 0x42 at address 0x7e2

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 0, 0, 5, 5])
> read_byte()
Read 0x7b at address 0x7e3

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 0, 5, 0, 0])
> read_byte()
Read 0x41 at address 0x7e4

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 0, 5, 0, 5])
> read_byte()
Read 0x54 at address 0x7e5

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 0, 5, 5, 0])
> read_byte()
Read 0x32 at address 0x7e6

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 0, 5, 5, 5])
> read_byte()
Read 0x38 at address 0x7e7

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 5, 0, 0, 0])
> read_byte()
Read 0x43 at address 0x7e8

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 5, 0, 0, 5])
> read_byte()
Read 0x31 at address 0x7e9

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 5, 0, 5, 0])
> read_byte()
Read 0x36 at address 0x7ea

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 5, 0, 5, 5])
> read_byte()
Read 0x5f at address 0x7eb

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 5, 5, 0, 0])
> read_byte()
Read 0x45 at address 0x7ec

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 5, 5, 0, 5])
> read_byte()
Read 0x45 at address 0x7ed

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 5, 5, 5, 0])
> read_byte()
Read 0x50 at address 0x7ee

> set_address_pins([5, 12, 5, 5, 5, 5, 0, 5, 5, 5, 5])
> read_byte()
Read 0x52 at address 0x7ef

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 0, 0, 0, 0])
> read_byte()
Read 0x4f at address 0x7f0

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 0, 0, 0, 5])
> read_byte()
Read 0x4d at address 0x7f1

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 0, 0, 5, 0])
> read_byte()
Read 0x5f at address 0x7f2

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 0, 0, 5, 5])
> read_byte()
Read 0x73 at address 0x7f3

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 0, 5, 0, 0])
> read_byte()
Read 0x33 at address 0x7f4

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 0, 5, 0, 5])
> read_byte()
Read 0x63 at address 0x7f5

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 0, 5, 5, 0])
> read_byte()
Read 0x32 at address 0x7f6

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 0, 5, 5, 5])
> read_byte()
Read 0x33 at address 0x7f7

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 5, 0, 0, 0])
> read_byte()
Read 0x74 at address 0x7f8

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 5, 0, 0, 5])
> read_byte()
Read 0x5f at address 0x7f9

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 5, 0, 5, 0])
> read_byte()
Read 0x31 at address 0x7fa

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 5, 0, 5, 5])
> read_byte()
Read 0x64 at address 0x7fb

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 5, 5, 0, 0])
> read_byte()
Read 0x21 at address 0x7fc

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 5, 5, 0, 5])
> read_byte()
Read 0x21 at address 0x7fd

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 5, 5, 5, 0])
> read_byte()
Read 0x21 at address 0x7fe

> set_address_pins([5, 12, 5, 5, 5, 5, 5, 5, 5, 5, 5])
> read_byte()
Read 0x7d at address 0x7ff

Flag: HTB{AT28C16_EEPROM_s3c23t_1d!!!}

Dernière mise à jour

Cet article vous a-t-il été utile ?