Skip to content

Instantly share code, notes, and snippets.

@lab313ru
Created July 14, 2025 08:44
Show Gist options
  • Select an option

  • Save lab313ru/9b461dd532f277526a63521b24b07f18 to your computer and use it in GitHub Desktop.

Select an option

Save lab313ru/9b461dd532f277526a63521b24b07f18 to your computer and use it in GitHub Desktop.
Dump MMC via UBoot
import os.path
import re
import sys
import struct
import serial
from tqdm import tqdm
import re
# 1.8192 .32768 .f4debf7b-01.0c
#
# 2.40960 .655360 .f4debf7b-02.83
#
# 3.696320 .655360 .f4debf7b-03.83
#
# 4.1351680 .6381568 .f4debf7b-04.83
PART_R = re.compile(r'[ \t]+(\d+)[ \t]+(\d+)[ \t]+(\d+)[ \t]+([0-9a-f\-]+)[ \t]+([0-9a-f]+)')
DIR_R = re.compile(r'^<DIR>[ \t]+(\d+)[ \t]+(.+)$')
FILE_R = re.compile(r'^[ \t]+(\d+)[ \t]+(.+)$')
SYM_R = re.compile(r'^<SYM>[ \t]+(\d+)[ \t]+(.+)$')
FILE_GOOD_R = re.compile(r'(\d+) bytes read in .+$')
def exec_cmd(s, cmd):
# print('executing %s' % cmd.decode())
s.write(b'%s\n' % cmd)
lines = []
line = ''
while True:
b = s.read()
if b in [b'\n', b'\r']:
line = line.rstrip('\r\n')
if len(line):
lines.append(line)
line = ''
continue
elif b == b'' and line.startswith('=> '):
break
line += b.decode('utf-8')
return lines
def read_part(s, part):
start, count = part['start'], part['count']
res = exec_cmd(s, b'mmc read 10000000 %x %x' % (start, count))
print(res)
def dump_part(s, part):
size = 770 # 0x200 * part['count']
off = 0
bs = 0x1000
# with open('dump_part_%d.bin' % part['index'], 'wb') as w:
with open('shadow.bin', 'wb') as w:
with tqdm(total=size) as pb:
while size > 0:
lines = exec_cmd(s, b'md.b %x %x' % (0x10000000 + off, min(bs, size)))[1:]
for line in lines:
data, _ = line.split(" ", maxsplit=1)
_, strdata = data.split(maxsplit=1)
# addr = int.from_bytes(bytes.fromhex(straddr[:-1]), byteorder='big')
data = bytes.fromhex(strdata)
pb.update(0x10)
w.write(data)
size -= 0x10
off += bs
def parse_hex_lines(lines, max_size):
res = bytearray()
for line in lines:
data, _ = line.split(" ", maxsplit=1)
_, strdata = data.split(maxsplit=1)
data = bytes.fromhex(strdata)
res.extend(data)
return bytes(res)[:max_size]
def dump_file(s, path, size):
w_path = '/'.join(['./', path])
if size == 0:
with open(w_path, 'wb') as w:
pass
return
res = exec_cmd(s, b'ext2load mmc 1:2 10000000 %s' % path.encode())
m = FILE_GOOD_R.match(res[1])
real_sz = -1
if m is not None:
real_sz = m.group(1)
assert real_sz != -1
off = 0
bs = min(size, 0x1000)
with open(w_path, 'wb') as w:
with tqdm(total=size) as pb:
lines = exec_cmd(s, b'md.b %x %x' % (0x10000000 + off, bs))[1:]
buf = parse_hex_lines(lines, bs)
w.write(buf)
pb.update(bs)
size -= bs
while size > 0:
lines = exec_cmd(s, b'\n')
blk = min(size, bs)
buf = parse_hex_lines(lines, blk)
w.write(buf)
pb.update(blk)
size -= blk
def dump_mmc_1_2(s, root='./', level=0):
os.makedirs(root, exist_ok=True)
res = exec_cmd(s, b'ext2ls mmc 1:2 %s' % root.encode())
res = res[1:]
dirs = []
for line in res:
m = DIR_R.match(line)
if not m:
m = SYM_R.match(line)
if not m:
m = FILE_R.match(line)
if not m:
continue
# do file
size = int(m.group(1))
name = m.group(2)
print('%s%s %d' % (' ' * level, name, size))
dump_file(s, '/'.join([root, name]), size)
continue
# do sym
size = int(m.group(1))
name = m.group(2)
print('%s<%s> %d' % (' ' * level, name, size))
dump_file(s, '/'.join([root, name]), 0)
continue
# do dir
name = m.group(2)
if name not in ['.', '..']:
print('%s[%s]' % (' ' * level, name))
dump_mmc_1_2(s, '/'.join([root, name]), level+1)
# return sub_dirs
def main():
s = serial.Serial('COM15', 115200, timeout=0.001)
# s = serial.Serial('/dev/ttyUSB0', 115200, timeout=0.001)
os.sep = '/'
dump_mmc_1_2(s)
# dump_part(s, '1')
exit()
res = exec_cmd(s, b'mmc part')
parts = []
for line in res:
m = PART_R.match(line)
if not m:
continue
part = {
'index': int(m.group(1)),
'start': int(m.group(2)),
'count': int(m.group(3)),
'uuid': m.group(4),
'type': int(m.group(5), 16)
}
parts.append(part)
read_part(s, parts[0])
dump_part(s, parts[0])
s.close()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment