Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- import sys
- import calendar
- CONSOLE_TYPES = {
- 0xff: 'DS',
- 0x20: 'DS Lite',
- 0x57: 'DSi (or 3DS)',
- 0x43: 'iQue DS',
- 0x63: 'iQue DS Lite'
- }
- COLOURS = {
- 1: 'Gray',
- 2: 'Brown',
- 3: 'Red',
- 4: 'Light Pink',
- 5: 'Orange',
- 6: 'Yellow',
- 7: 'Light Green',
- 8: 'Green',
- 9: 'Dark Green',
- 10: 'Teal',
- 11: 'Blue',
- 12: 'Dark Blue',
- 13: 'Dark Purple',
- 14: 'Purple',
- 15: 'Pink',
- }
- WIFI_STATUSES = {
- 0: 'Normal',
- 1: 'AOSS',
- 16: 'WPA/WPA2',
- 255: 'Unconfigured'
- }
- WPA_TYPES = {
- 0: 'None/WEP',
- 4: 'WPA-TKIP',
- 5: 'WPA2-TKIP',
- 6: 'WPA-AES',
- 7: 'WPA2-AES',
- }
- LANGUAGES = {
- 0: 'Japanese',
- 1: 'English',
- 2: 'French',
- 3: 'German',
- 4: 'Italian',
- 5: 'Spanish',
- 6: 'Chinese',
- 7: 'Reserved',
- }
- def format_ip_address(b):
- #Apparently I can't just use str.join for this thanks I hate it
- return '{0}.{1}.{2}.{3}'.format(*b)
- def is_null_ip_address(b):
- return b[0] == 0 and b[1] == 0 and b[2] == 0 and b[3] == 0
- def read_wifi_config(f, offset, slot_number):
- f.seek(offset + 0xe7)
- status = f.read(1)[0]
- if status == 0xff:
- return
- print('Wifi %d status: %s' % (slot_number, WIFI_STATUSES.get(status, 'Unknown 0x{0:02X}'.format(status))))
- f.seek(offset + 0x40)
- ssid = f.read(32).decode('ascii', errors='backslashreplace').rstrip('\0')
- print('Wifi %d SSID: %s' % (slot_number, ssid))
- ssid_aoss = f.read(32).decode('ascii', errors='backslashreplace').rstrip('\0')
- print('Wifi %d SSID for AOSS: %s' % (slot_number, ssid_aoss))
- f.seek(offset + 0xe6)
- wep_mode = f.read(1)[0]
- #0: None, 1 = 5 hex, 2 = 13 hex, 3 = 16 hex, 5 = 5 ascii, 6 = 13 byte, 7 = 16 byte
- print('Wifi %d WEP mode: %d' % (slot_number, wep_mode))
- f.seek(offset + 0xea)
- #DSi only
- mtu = f.read(1)[0] | (f.read(1)[0] << 8)
- print('Wifi %d MTU: %d' % (slot_number, mtu))
- f.seek(offset + 0xc0)
- ip_address = f.read(4)
- if is_null_ip_address(ip_address):
- print('Wifi %d IP address: DHCP' % slot_number)
- else:
- print('Wifi %d IP address: %s' % (slot_number, format_ip_address(ip_address)))
- gateway = f.read(4)
- print('Wifi %d gateway: %s' % (slot_number, format_ip_address(gateway)))
- primary_dns = f.read(4)
- print('Wifi %d primary: %s' % (slot_number, format_ip_address(primary_dns)))
- secondary_dns = f.read(4)
- print('Wifi %d secondary: %s' % (slot_number, format_ip_address(secondary_dns)))
- subnet_mask = f.read(1)[0]
- print('Wifi %d subnet mask: /%d' % (slot_number, subnet_mask))
- if wep_mode > 0:
- f.seek(offset + 0x80)
- wep_keys = [None] * 4
- for i in range(4):
- wep_keys[i] = f.read(16)
- if wep_mode == 5:
- wep_keys[i] = wep_keys[i].decode('ascii', errors='backslashreplace')[:5]
- if wep_mode == 6:
- wep_keys[i] = wep_keys[i].decode('ascii', errors='backslashreplace')[:13]
- if wep_mode == 7:
- wep_keys[i] = wep_keys[i].decode('ascii', errors='backslashreplace')[:16]
- #TODO Format properly when WEP mode is hex
- print('Wifi %d WEP keys: %s' % (slot_number, list(wep_keys)))
- def read_dsi_wifi_config(f, offset, slot_number):
- f.seek(offset + 0xe7)
- status = f.read(1)[0]
- if status == 0xff:
- return
- print('Wifi %d status: %s' % (slot_number, WIFI_STATUSES.get(status, 'Unknown 0x{0:02X}'.format(status))))
- ssid_length = f.read(1)[0]
- f.seek(offset + 0x40)
- ssid = f.read(ssid_length).decode('ascii', errors='backslashreplace')
- print('Wifi %d SSID: %s' % (slot_number, ssid))
- f.seek(offset + 0xe6)
- wep_type = f.read(1)[0]
- if wep_type != 0:
- print('Wifi %d WEP type: %s' % (slot_number, wep_type))
- f.seek(offset + 0x182)
- proxy_enabled = f.read(1)[0] > 0
- if proxy_enabled:
- proxy_uses_auth = f.read(1)[0] > 0
- proxy_name = f.read(100).decode('ascii', errors='backslashreplace').rstrip('\0')
- print('Wifi %d proxy name: %s' % (slot_number, proxy_name))
- proxy_port = f.read(1)[0] | (f.read(1)[0] << 8)
- print('Wifi %d proxy port: %s' % (slot_number, proxy_port))
- if proxy_uses_auth:
- f.seek(offset)
- proxy_auth_username = f.read(32).decode('ascii', errors='backslashreplace').rstrip('\0')
- proxy_auth_password = f.read(32).decode('ascii', errors='backslashreplace').rstrip('\0')
- print('Wifi %d proxy authentication: username %s password %s' % (slot_number, proxy_auth_username, proxy_auth_password))
- f.seek(offset + 0xc0)
- ip_address = f.read(4)
- if is_null_ip_address(ip_address):
- print('Wifi %d IP address: DHCP' % slot_number)
- else:
- print('Wifi %d IP address: %s' % (slot_number, format_ip_address(ip_address)))
- gateway = f.read(4)
- print('Wifi %d gateway: %s' % (slot_number, format_ip_address(gateway)))
- primary_dns = f.read(4)
- print('Wifi %d primary: %s' % (slot_number, format_ip_address(primary_dns)))
- secondary_dns = f.read(4)
- print('Wifi %d secondary: %s' % (slot_number, format_ip_address(secondary_dns)))
- subnet_mask = f.read(1)[0]
- print('Wifi %d subnet mask: /%d' % (slot_number, subnet_mask))
- if status == 16:
- f.seek(offset + 0x120)
- wpa_key = f.read(64).decode('ascii', errors='backslashreplace').rstrip('\0')
- #GBATEK says this is only 16 bytes, but that is clearly wrong as WPA keys can be longer than that
- print('Wifi %d WPA/WPA2 key: %s' % (slot_number, wpa_key))
- f.seek(offset + 0x181)
- wpa_type = f.read(1)[0]
- print('Wifi %d WPA type: %s' % (slot_number, WPA_TYPES.get(wpa_type, 'Unknown 0x{0:02X}'.format(wpa_type))))
- with open(sys.argv[1], 'rb') as f:
- f.seek(8)
- firmware_id = f.read(4)
- print('Firmware ID: %s' % list(firmware_id))
- f.seek(0x18)
- firmware_version = f.read(5)
- #BCD minute hour day month year
- #TODO Convert this
- #TODO Can we get the fat DS firmware version from this?
- print('Firmware build date: %s' % list(firmware_version))
- console_type = f.read(1)[0]
- print('Console type: %s' % CONSOLE_TYPES.get(console_type, 'Unknown 0x{0:02X}'.format(console_type)))
- f.seek(32)
- user_settings_offset = f.read(2)
- offset = ((user_settings_offset[1] << 8) | user_settings_offset[0]) * 8
- f.seek(offset) #I guess?
- #It's always 5, unless something goes wrong
- user_settings_version = f.read(2)
- print('User settings version: %s' % list(user_settings_version))
- favourite_colour = f.read(1)[0]
- print('Favourite colour: %s' % COLOURS.get(favourite_colour, 'Unknown 0x{0:02X}'.format(favourite_colour)))
- birthday_month = f.read(1)[0]
- birthday_year = f.read(1)[0]
- print('Birthday: {0} {1}'.format(calendar.month_name[birthday_month], birthday_year))
- unused = f.read(1)[0]
- print('Secret unused user setting: %s' % unused)
- name = f.read(20).decode('utf-16le', errors='backslashreplace')
- name_length = f.read(1)[0] | (f.read(1)[0] << 8)
- print('Name: %s' % name[:name_length])
- message = f.read(52).decode('utf-16le', errors='backslashreplace')
- message_length = f.read(1)[0] | (f.read(1)[0] << 8)
- print('Message: %s' % message[:message_length])
- alarm_hour = f.read(1)[0]
- alarm_minute = f.read(1)[0]
- print('Alarm time: {0}:{1}'.format(alarm_hour, alarm_minute))
- #TODO Touch calibration and whatnot
- f.seek(offset + 0x64)
- flags = f.read(2)
- language = flags[0] & 7
- print('Language: %s' % LANGUAGES.get(language))
- gba_screen = flags[0] & 8
- print('GBA screen: %s' % 'Upper' if gba_screen == 0 else 'Lower')
- backlight_level = (flags[0] & 48) >> 4 #0 if not DS Lite
- print('Backlight level: %d' % backlight_level)
- #TODO other flags (cbf tbh m8)
- f.seek(0x2f)
- wifi_version = f.read(1)[0]
- print('Wifi version: %d' % wifi_version)
- read_wifi_config(f, offset - 0x400, 1)
- read_wifi_config(f, offset - 0x300, 2)
- read_wifi_config(f, offset - 0x200, 3)
- if console_type == 0x57:
- read_dsi_wifi_config(f, offset - 0xa00, 4)
- read_dsi_wifi_config(f, offset - 0x800, 5)
- read_dsi_wifi_config(f, offset - 0x600, 6)
Add Comment
Please, Sign In to add comment