$20 mini PC (Dolby controller) with unknown firmware password

Notice: Page may contain affiliate links for which we may earn a small commission through services like Amazon Affiliates or Skimlinks.

Mark Linton

New Member
Sep 28, 2018
20
8
3
Ok I managed to score a deal on a complete setup with the camera, conference phone and base unit.

On powering it all up, the phone comes up with settings, and a default password of admin/1739 to get into the phone settings. It also shows settings for the base unit as well. Now to attempt other access.

Webserver seems to be pretty basic from a security vulnerability perspective. I would imagine that the credentials will be the same as the bios, so maybe there's another way to look for the credentials used with the web service.
 
Last edited:

autoturk

Active Member
Sep 1, 2022
239
225
43
I bought a few more of these and have found them more useful than I initially imagined. I've been using them as an opnsense box for a few places I volunteer at, and for Proxmox/VM boxes for friends who want a home network more involved than just an ISP gateway. Nice to be able to just grab one from the shelf and give them away without having to stress about costs.
 

ufear

New Member
May 1, 2022
22
18
3
Utrecht, Netherlands
FWIW; playing with the speakerphone to see if I can get it working standalone; found some credentials for something at least:

Authentication.Local.Admin : U2FsdGVkX190+lBv73dYgPdreXadFxsvnGEx/T03EQQ=

Salted__tPowXkyv/a1=7

Dvms.Server.RegistrationPIN : U2FsdGVkX1/cBn3BV6KqkLmaRoDFvZo0YA57RkvHT/8=
Salted__}WFŽ4`{FKO
 

Mark Linton

New Member
Sep 28, 2018
20
8
3
FWIW; playing with the speakerphone to see if I can get it working standalone; found some credentials for something at least:

Authentication.Local.Admin : U2FsdGVkX190+lBv73dYgPdreXadFxsvnGEx/T03EQQ=

Salted__tPowXkyv/a1=7

Dvms.Server.RegistrationPIN : U2FsdGVkX1/cBn3BV6KqkLmaRoDFvZo0YA57RkvHT/8=
Salted__}WFŽ4`{FKO
Can you share details and where and how you found that?
 
  • Like
Reactions: Samir

aeg

Member
May 6, 2019
27
36
13
That's "openssl enc" output, it looks like obfuscated creds stored in a config file. To get the actual creds, you also need the decryption key.
 
  • Like
Reactions: Samir

hmartin

Well-Known Member
Sep 20, 2017
353
324
63
38
The linux stuff is in flat (encrypted?) files. Somebody more knowledgeable will need to have a look, might still be interesting to have control of the original software.
The firmware is stored on partitions 3 and 5 (1074MB). It's encrypted and the keys are stored in the TPM:
Bash:
setup_encrootfs() {
    rootfs_device=$1
    # index and auth mode defined during manufacturing; keep in sync
    tpm_keyindex=0x1d01b72
    tpm_ownerauth=0x40000001
   
    tpm2_nvread --tcti=device -x $tpm_keyindex -a $tpm_ownerauth -f $keyfile > /dev/null 2>&1
    chkerr $? "TPM read failed"

    key=$(hexdump -vn 32 -e ' /1 "%02x"' $keyfile)
    rootfs_num_sectors=$(parted $BLOCK_DEV unit s print | grep rootfs0 | awk '{print $4}' | sed s/s//)
   
    echo "0 $rootfs_num_sectors crypt aes-cbc-essiv:sha256 $key 0 $rootfs_device 0" | dmsetup create $ACTIVE_ROOT
    chkerr $? "dmsetup on active_root failed"
   
    # setup mapper for alternate rootfs - required to write updates
    curr_part=$(echo ${rootfs_device:(-1)})
    p1=$(echo $(parted $BLOCK_DEV print | grep rootfs0 | awk '{print $1}'))
    p2=$(echo $(parted $BLOCK_DEV print | grep rootfs1 | awk '{print $1}'))

    if [ $curr_part -eq $p1 ]; then
        alt_part=$p2
    else
        alt_part=$p1  
    fi

    alt_rootfs_device=$(echo $rootfs_device | sed "s/$curr_part/$alt_part/")
    echo "0 $rootfs_num_sectors crypt aes-cbc-essiv:sha256 $key 0 $alt_rootfs_device 0" | dmsetup create $ALTERNATE_ROOT
    chkerr $? "dmsetup on alternate_root failed"
   
    # zero out keyfile and remove
    dd if=/dev/zero of=$keyfile bs=512b count=1
    rm $keyfile
}
Someone has a dump of their EMMC and can run the commands against the TPM? I would expect flashing a modified BIOS clears the keys stored in the TPM, but maybe we get lucky?

Booting into the dolby software and then pressing CTRL-ALT-F3 brings up a linux shell. Of course password is still a problem
The admin/1739 login works here, but dumps you into the useless Dolby CLI:

Code:
Enter password: ****

+- - - - - - - - - - - - - - - - - - -+
+   Dolby Voice Room     SN:K0000001  +
+- - - - - - - - - - - - - - - - - - -+

DolbyCli>
If you create a USB with a GPT partition table and an ext4 partition with the partition label data this will be mounted by the Voice Hub to /usr/dolby/data:
Code:
DolbyCli>show disk
Filesystem           1K-blocks      Used Available Use% Mounted on
none                   1965568     34316   1931252   2% /dev
/dev/mapper/root        235776    235776         0 100% /
tmpfs                  1978868       404   1978464   0% /run
tmpfs                  1978868      1308   1977560   0% /var/volatile
tmpfs                  1978868      1308   1977560   0% /var/lib
/dev/disk/by-partlabel/data
                        999320     18936    911572   2% /usr/dolby/data
/dev/mapper/sdata        14839       141     13552   1% /usr/dolby/sdata
/dev/mapper/sstorage      3963        41      3718   1% /sstorage
/dev/disk/by-partlabel/data
                        999320     18936    911572   2% /etc/hosts
There are some configuration files stored there, used by the application. Unfortunately, I have not found any avenues to code execution/shell spawn by modifying the configuration files. Maybe this information will be helpful for someone else though :)
 

hmartin

Well-Known Member
Sep 20, 2017
353
324
63
38
I tried glitching EMMC/LPC during boot, as the init script in the first bzImage ramdisk is supposed to drop to a shell on failure:
Bash:
boot_live_root() {

    if echo "$CMDLINE" | grep -q root=/dev/nfs; then
        nfsrootpath=$(echo $NFS_ROOT | cut -d , -f 1)
        options=$(echo $NFS_ROOT | cut -d , -f 2-)
        echo "Boot from NFS server at $nfsrootpath "
        $MOUNT -t nfs -o $options $nfsrootpath $ROOT_MOUNT

    elif echo "$CMDLINE" | grep -q root=/dev/mmc; then
        echo "Boot from encrypted eMMC flash: $ROOT_DEVICE "
        setup_encrootfs $ROOT_DEVICE
        $MOUNT -o ro /dev/mapper/$ACTIVE_ROOT $ROOT_MOUNT
        ec=$?
        if [ $ec -ne 0 ]; then
            dmsetup remove /dev/mapper/$ACTIVE_ROOT
            dmsetup remove /dev/mapper/$ALTERNATE_ROOT
            chkerr $ec "failed to mount encrypted root filesystem"
            fatal "Failed to mount encrypted root filesystem. Open shell..."
        fi
        # change root in $CMDLINE
        CMDLINE=$(echo $CMDLINE | sed "s@root=\S*@root=/dev/mapper/${ACTIVE_ROOT} @")

    else
        # TODO: remove this section after moving to eMMC flash
        # kernel takes time to identify USB flash; loop until detected
        echo "Boot from flash: $ROOT_DEVICE "
        while true; do
            $MOUNT -o ro $ROOT_DEVICE $ROOT_MOUNT
            ec=$?
            if [ $ec -eq 0 ]; then
                break
            fi
            # check if ROOT_DEVICE is automounted with ext4/rw fs
            mount | grep -q ^$ROOT_DEVICE.on && umount $ROOT_DEVICE
            /bin/usleep 200000
        done
    fi

    # Watches the udev event queue, and exits if all current events are handled
    udevadm settle --timeout=3 --quiet
    # Kills the current udev running processes, which survived after
    # device node creation events were handled, to avoid unexpected behavior
    killall -9 udevadm 2>/dev/null

    #export cmdvar=$CMDLINE
    #fatal "Start debug shell..."

    mount -n --move /dev/ $ROOT_MOUNT/dev
    exec /sbin/switch_root -c /dev/console $ROOT_MOUNT /sbin/init $CMDLINE ||
        fatal "Couldn't switch_root, dropping to shell"
}


fatal() {
    echo $1 >$CONSOLE
    echo >$CONSOLE
    exec sh
}
But no luck, just a black screen. Probably the production units have no console= in the kernel command line.

Here's the pinout of JLPC1 that I was able to determine:
1: LCLK
5: LAD0
7: LAD1
9: LAD2
11: LAD3
13: LFRAME#
14: GND

It seems my Saleae 16 is not fast enough to accurately capture the 25MHz clock:
2025-02-23_14-27.png

Maybe someone here has a more capable logic analyzer and can capture the encryption key from the TPM by sniffing the LPC bus?
 

fohdeesha

Kaini Industries
Nov 20, 2016
2,890
3,397
113
34
fohdeesha.com
I tried glitching EMMC/LPC during boot, as the init script in the first bzImage ramdisk is supposed to drop to a shell on failure:
Bash:
boot_live_root() {

    if echo "$CMDLINE" | grep -q root=/dev/nfs; then
        nfsrootpath=$(echo $NFS_ROOT | cut -d , -f 1)
        options=$(echo $NFS_ROOT | cut -d , -f 2-)
        echo "Boot from NFS server at $nfsrootpath "
        $MOUNT -t nfs -o $options $nfsrootpath $ROOT_MOUNT

    elif echo "$CMDLINE" | grep -q root=/dev/mmc; then
        echo "Boot from encrypted eMMC flash: $ROOT_DEVICE "
        setup_encrootfs $ROOT_DEVICE
        $MOUNT -o ro /dev/mapper/$ACTIVE_ROOT $ROOT_MOUNT
        ec=$?
        if [ $ec -ne 0 ]; then
            dmsetup remove /dev/mapper/$ACTIVE_ROOT
            dmsetup remove /dev/mapper/$ALTERNATE_ROOT
            chkerr $ec "failed to mount encrypted root filesystem"
            fatal "Failed to mount encrypted root filesystem. Open shell..."
        fi
        # change root in $CMDLINE
        CMDLINE=$(echo $CMDLINE | sed "s@root=\S*@root=/dev/mapper/${ACTIVE_ROOT} @")

    else
        # TODO: remove this section after moving to eMMC flash
        # kernel takes time to identify USB flash; loop until detected
        echo "Boot from flash: $ROOT_DEVICE "
        while true; do
            $MOUNT -o ro $ROOT_DEVICE $ROOT_MOUNT
            ec=$?
            if [ $ec -eq 0 ]; then
                break
            fi
            # check if ROOT_DEVICE is automounted with ext4/rw fs
            mount | grep -q ^$ROOT_DEVICE.on && umount $ROOT_DEVICE
            /bin/usleep 200000
        done
    fi

    # Watches the udev event queue, and exits if all current events are handled
    udevadm settle --timeout=3 --quiet
    # Kills the current udev running processes, which survived after
    # device node creation events were handled, to avoid unexpected behavior
    killall -9 udevadm 2>/dev/null

    #export cmdvar=$CMDLINE
    #fatal "Start debug shell..."

    mount -n --move /dev/ $ROOT_MOUNT/dev
    exec /sbin/switch_root -c /dev/console $ROOT_MOUNT /sbin/init $CMDLINE ||
        fatal "Couldn't switch_root, dropping to shell"
}


fatal() {
    echo $1 >$CONSOLE
    echo >$CONSOLE
    exec sh
}
But no luck, just a black screen. Probably the production units have no console= in the kernel command line.

Here's the pinout of JLPC1 that I was able to determine:
1: LCLK
5: LAD0
7: LAD1
9: LAD2
11: LAD3
13: LFRAME#
14: GND

It seems my Saleae 16 is not fast enough to accurately capture the 25MHz clock:
View attachment 42053

Maybe someone here has a more capable logic analyzer and can capture the encryption key from the TPM by sniffing the LPC bus?
I have a scope with protocol decoding that could do it, but I'll be honest I have no free time these days and I can't even muster the motivation to take the stupid thing apart with the 90 hidden screws. do you think there's a high chance the TPM key would be plain over the wire on the LPC1 bus?
 

hmartin

Well-Known Member
Sep 20, 2017
353
324
63
38
I have a scope with protocol decoding that could do it, but I'll be honest I have no free time these days and I can't even muster the motivation to take the stupid thing apart with the 90 hidden screws.
All the screws under the foam are only if you want to remove the PCB, which you don't need to do to access JLPC. If you just want to access the LPC header, then two torx 8 screws on the back above the IO ports is all you need (along with a screw driver or guitar picks to slide under the sides). The metal EMI cage needs to come off too, but that's just a bit of light prying.

The JLPC header is using 2.0mm pitch.

do you think there's a high chance the TPM key would be plain over the wire on the LPC1 bus?
The device is using a discrete SLB 9665TT2.0, which is capable of sending encrypted commands/responses but even vendors like Microsoft haven't bothered to do that: Extracting BitLocker keys from a TPM

Dolby seem to have done [some] homework in the security of this device (mounting anything with the part label data aside).

Is the key on the LPC bus? 100%
2025-02-24_17-09.png

Is the TPM response encrypted? I'm 70/30 it's not.
 

fohdeesha

Kaini Industries
Nov 20, 2016
2,890
3,397
113
34
fohdeesha.com
All the screws under the foam are only if you want to remove the PCB, which you don't need to do to access JLPC. If you just want to access the LPC header, then two torx 8 screws on the back above the IO ports is all you need (along with a screw driver or guitar picks to slide under the sides). The metal EMI cage needs to come off too, but that's just a bit of light prying.

The JLPC header is using 2.0mm pitch.



The device is using a discrete SLB 9665TT2.0, which is capable of sending encrypted commands/responses but even vendors like Microsoft haven't bothered to do that: Extracting BitLocker keys from a TPM

Dolby seem to have done [some] homework in the security of this device (mounting anything with the part label data aside).

Is the key on the LPC bus? 100%
View attachment 42072

Is the TPM response encrypted? I'm 70/30 it's not.
how many of those pins will I actually need to succesfully decode? Haven't dealt with LPC in forever. 4 channels avail on the scope
I tried glitching EMMC/LPC during boot, as the init script in the first bzImage ramdisk is supposed to drop to a shell on failure:
Bash:
boot_live_root() {

    if echo "$CMDLINE" | grep -q root=/dev/nfs; then
        nfsrootpath=$(echo $NFS_ROOT | cut -d , -f 1)
        options=$(echo $NFS_ROOT | cut -d , -f 2-)
        echo "Boot from NFS server at $nfsrootpath "
        $MOUNT -t nfs -o $options $nfsrootpath $ROOT_MOUNT

    elif echo "$CMDLINE" | grep -q root=/dev/mmc; then
        echo "Boot from encrypted eMMC flash: $ROOT_DEVICE "
        setup_encrootfs $ROOT_DEVICE
        $MOUNT -o ro /dev/mapper/$ACTIVE_ROOT $ROOT_MOUNT
        ec=$?
        if [ $ec -ne 0 ]; then
            dmsetup remove /dev/mapper/$ACTIVE_ROOT
            dmsetup remove /dev/mapper/$ALTERNATE_ROOT
            chkerr $ec "failed to mount encrypted root filesystem"
            fatal "Failed to mount encrypted root filesystem. Open shell..."
        fi
        # change root in $CMDLINE
        CMDLINE=$(echo $CMDLINE | sed "s@root=\S*@root=/dev/mapper/${ACTIVE_ROOT} @")

    else
        # TODO: remove this section after moving to eMMC flash
        # kernel takes time to identify USB flash; loop until detected
        echo "Boot from flash: $ROOT_DEVICE "
        while true; do
            $MOUNT -o ro $ROOT_DEVICE $ROOT_MOUNT
            ec=$?
            if [ $ec -eq 0 ]; then
                break
            fi
            # check if ROOT_DEVICE is automounted with ext4/rw fs
            mount | grep -q ^$ROOT_DEVICE.on && umount $ROOT_DEVICE
            /bin/usleep 200000
        done
    fi

    # Watches the udev event queue, and exits if all current events are handled
    udevadm settle --timeout=3 --quiet
    # Kills the current udev running processes, which survived after
    # device node creation events were handled, to avoid unexpected behavior
    killall -9 udevadm 2>/dev/null

    #export cmdvar=$CMDLINE
    #fatal "Start debug shell..."

    mount -n --move /dev/ $ROOT_MOUNT/dev
    exec /sbin/switch_root -c /dev/console $ROOT_MOUNT /sbin/init $CMDLINE ||
        fatal "Couldn't switch_root, dropping to shell"
}


fatal() {
    echo $1 >$CONSOLE
    echo >$CONSOLE
    exec sh
}
But no luck, just a black screen. Probably the production units have no console= in the kernel command line.

Here's the pinout of JLPC1 that I was able to determine:
1: LCLK
5: LAD0
7: LAD1
9: LAD2
11: LAD3
13: LFRAME#
14: GND

It seems my Saleae 16 is not fast enough to accurately capture the 25MHz clock:
View attachment 42053

Maybe someone here has a more capable logic analyzer and can capture the encryption key from the TPM by sniffing the LPC bus?
hmmm thinking about it, if you have a logic pro 16, that'll do up to 100mhz / 500 MS/s which is plenty for a 25mhz clocked signal - have you played with the capture settings? should be able to set sample rate etc, max avail should be 500MS/s
 

hmartin

Well-Known Member
Sep 20, 2017
353
324
63
38
how many of those pins will I actually need to succesfully decode? Haven't dealt with LPC in forever. 4 channels avail on the scope
6: LAD0-3, LCLK, and LFRAME#

hmmm thinking about it, if you have a logic pro 16, that'll do up to 100mhz / 500 MS/s which is plenty for a 25mhz clocked signal - have you played with the capture settings? should be able to set sample rate etc, max avail should be 500MS/s
I have the non-Pro. It will do 100MHz but only 2 channels and even then I do not have the expected waveform for a 25MHz clock.

Another option is an RP2040, there are some LPC sniffing projects but all would need modification because they're either meant to display only POST codes or sniff for a BitLocker key specifically.
 
  • Like
Reactions: fohdeesha