Created
July 22, 2022 08:26
-
-
Save hberntsen/46936cb0fab7783209a4527843440cec to your computer and use it in GitHub Desktop.
Emulates the password entry function of the Arcadyan WE420223-99 U-Boot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# based on https://www.shielder.com/blog/2022/03/reversing-embedded-device-bootloader-u-boot-p.2/ | |
from unicorn import * | |
from unicorn.mips_const import * | |
from unicorn.unicorn_const import * | |
import subprocess | |
import ctypes | |
import sys | |
libc = ctypes.CDLL("libc.so.6") | |
#callback of the code hook | |
def hook_code(uc, addr, size, user_data): | |
mem = uc.mem_read(addr, size) | |
disas_single(bytes(mem),addr) | |
def hook_printf(uc: Uc, addr, size, user_data): | |
if addr == 0xbfc16d10: | |
a0=uc.reg_read(UC_MIPS_REG_A0) | |
data = uc.mem_read(a0, 1024) | |
libc.puts(ctypes.c_char_p(bytes(data))) | |
ret_addr=uc.reg_read(UC_MIPS_REG_RA) | |
uc.reg_write(UC_MIPS_REG_PC, ret_addr) | |
def hook_puts(uc: Uc, addr, size, user_data): | |
if addr == 0xbfc16cdc: | |
a0=uc.reg_read(UC_MIPS_REG_A0) | |
data = uc.mem_read(a0, 1024) | |
libc.puts(ctypes.c_char_p(bytes(data))) | |
ret_addr=uc.reg_read(UC_MIPS_REG_RA) | |
uc.reg_write(UC_MIPS_REG_PC, ret_addr) | |
def hook_putc(uc: Uc, addr, size, user_data): | |
if addr == 0xbfc16ca8: | |
a0=uc.reg_read(UC_MIPS_REG_A0) | |
print(chr(a0), end='') | |
ret_addr=uc.reg_read(UC_MIPS_REG_RA) | |
uc.reg_write(UC_MIPS_REG_PC, ret_addr) | |
def hook_getc(uc: Uc, addr, size, user_data): | |
if addr == 0xbfc16c48: | |
# print('*',end='', flush=True) | |
uc.reg_write(UC_MIPS_REG_V0, ord(sys.stdin.read(1))) | |
# uc.reg_write(UC_MIPS_REG_V1, ord('a')) | |
ret_addr=uc.reg_read(UC_MIPS_REG_RA) | |
uc.reg_write(UC_MIPS_REG_PC, ret_addr) | |
def hook_gets(uc: Uc, addr, size, user_data): | |
if addr == 0xbfc1032c: | |
a0=uc.reg_read(UC_MIPS_REG_A0) | |
password=b"password" | |
uc.mem_write(a0, password) | |
print(password) | |
ret_addr=uc.reg_read(UC_MIPS_REG_RA) | |
uc.reg_write(UC_MIPS_REG_PC, ret_addr) | |
def hook_print_interesting_stuff(uc: Uc, addr, size, user_data): | |
if addr == 0xbfc01584: | |
print("expected hash:") | |
v1=uc.reg_read(UC_MIPS_REG_V1) | |
expected_hash=uc.mem_read(v1, 256) | |
libc.puts(ctypes.c_char_p(bytes(expected_hash))) | |
elif addr == 0xbfc01524: | |
print("user hash:") | |
s2=uc.reg_read(UC_MIPS_REG_S2) | |
user_hash=uc.mem_read(s2, 16) | |
print(user_hash.hex()) | |
#disassembly each istruction and print the mnemonic name | |
def disas_single(data,addr): | |
subprocess.run(['cstool', 'mips', data[:4].hex(), hex(addr)]) | |
#code to be emulated | |
in_file = open("mtdblock1", "rb") # opening for [r]eading as [b]inary | |
MTDBLOCK = in_file.read() | |
in_file.close() | |
# U-Boot base address | |
ADDRESS = 0xbfc00000 | |
print("Emulate MIPS code") | |
try: | |
# Initialize emulator in MIPS-32bit mode | |
# with "MIPS" MIPS instruction set | |
mu = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32) | |
# map U-boot in memory for this emulation | |
# "// (1024 * 1024)" for memory allign pourses | |
i = len(MTDBLOCK) // (1024 * 1024) | |
mem_size = (1024 * 1024) + (i * (1024 * 1024)) | |
mu.mem_map(ADDRESS, mem_size, perms=UC_PROT_ALL) | |
# write machine code to be emulated to memory | |
mu.mem_write(ADDRESS, MTDBLOCK) | |
# map STACK | |
stack_address = ADDRESS + mem_size | |
# 2MB | |
stack_size = (1024 * 1024) * 2 | |
mu.mem_map(stack_address, stack_size, perms=UC_PROT_ALL) | |
# initialize machine registries | |
mu.reg_write(UC_MIPS_REG_SP, stack_address) | |
FUNCTION_OFFSET = 0x1420 | |
mu.reg_write(UC_MIPS_REG_T9, ADDRESS + FUNCTION_OFFSET) | |
# hook any instruction and disassembly them with capstone | |
# mu.hook_add(UC_HOOK_CODE, hook_code) | |
# mu.hook_add(UC_HOOK_CODE, hook_printf) | |
mu.hook_add(UC_HOOK_CODE, hook_putc) | |
mu.hook_add(UC_HOOK_CODE, hook_puts) | |
mu.hook_add(UC_HOOK_CODE, hook_getc) | |
# mu.hook_add(UC_HOOK_CODE, hook_gets) | |
mu.hook_add(UC_HOOK_CODE, hook_print_interesting_stuff) | |
# Sets expected password to "password" | |
# mu.mem_write(0xbfc1c080, b"5f4dcc3b5aa765d61d8327deb882cf99") | |
mu.emu_start(ADDRESS+FUNCTION_OFFSET, ADDRESS+0x1638) | |
print("Emulation done. ") | |
except UcError as e: | |
print("ERROR: %s" % e) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment