Georg Lukas, 2014-05-12 18:05
This is the second post in a series covering the Samsung NX300 "Smart" Camera. In the first post, we have analyzed how the camera is interacting with the outside world using NFC and WiFi. In this post, we will have a deeper look at the operating system running on the camera, execute some code and open a remote root shell. This process can be applied (with some adaptations) to different networked consumer electronics, including home routers, NAS boxes and Smart TVs. The third post will leveage that knowledge to add functionality.
Firmware: Looking for Loopholes
Experience shows that most firmware images provide an easy way to run a user-provided shell script on boot. This feature is often added by the "software engineers" during development, but it boils down to a local root backdoor. On a camera, the SD card would be a good place to search. Other devices might execute code from an USB flash drive or the built-in hard disk.
Usually, we have to start with the firmware update file (nx300.bin
from
this 241MB ZIP
in our case), run binwalk on it, extract and mount the
root file system and have our fun. In this case, however, the source archive
from Samsung's OSS Release Center contains
an unpacked root file system tree in TIZEN/project/NX300/image/rootfs
, so we
just examine that:
georg@megavolt:TIZEN/project/NX300/image/rootfs$ ls -l
total 72
drwxr-xr-x 4 4096 Oct 16 2013 bin/
drwxr-xr-x 3 4096 Oct 16 2013 data/
drwxr-xr-x 3 4096 Oct 16 2013 dev/
drwxr-xr-x 38 4096 Oct 16 2013 etc/
drwxr-xr-x 9 4096 Oct 16 2013 lib/
-rw-r--r-- 1 203 Oct 16 2013 make_image.log
drwxr-xr-x 8 4096 Oct 16 2013 mnt/
drwxr-xr-x 3 4096 Oct 16 2013 network/
drwxr-xr-x 16 4096 Oct 16 2013 opt/
drwxr-xr-x 2 4096 Oct 16 2013 proc/
lrwxrwxrwx 1 13 Oct 16 2013 root -> opt/home/root/
drwxr-xr-x 2 4096 Oct 16 2013 sbin/
lrwxrwxrwx 1 8 Oct 16 2013 sdcard -> /mnt/mmc
drwxr-xr-x 2 4096 Oct 16 2013 srv/
drwxr-xr-x 2 4096 Oct 16 2013 sys/
drwxr-xr-x 2 4096 Oct 16 2013 tmp/
drwxr-xr-x 16 4096 Oct 16 2013 usr/
drwxr-xr-x 13 4096 Oct 16 2013 var/
make_image.log
sounds like somebody forgot to clean up before shipping (this
file is actually contained on the camera):
SBS logging begin
Wed Oct 16 14:27:21 KST 2013
WARNING: setting root UBIFS inode UID=GID=0 (root) and permissions to u+rwx,go+rx; use --squash-rino-perm or --nosquash-rino-perm to suppress this warning
If we can believe the /sdcard
symlink, the SD card is mounted at /mnt/mmc
.
Usually, there are some scripts and tools referencing the directory, and we
should start with them:
georg@megavolt:TIZEN/project/NX300/image/rootfs$ grep /mnt/mmc -r .
./etc/fstab:/dev/mmcblk0 /mnt/mmc exfat noauto,user,umask=1000 0 0
./etc/fstab:/dev/mmcblk0p1 /mnt/mmc exfat noauto,user,umask=1000 0 0
./usr/sbin/pivot_rootfs_ubi.sh:umount /oldroot/mnt/mmc
./usr/sbin/rcS.pivot: mkdir -p /mnt/mmc
./usr/sbin/rcS.pivot: mount -t vfat -o noatime,nodiratime $card_path /mnt/mmc
./usr/bin/inspkg.sh: mount -t vfat /dev/mmcblk0 /mnt/mmc
./usr/bin/inspkg.sh: mount -t vfat /dev/mmcblk0p1 /mnt/mmc
./usr/bin/inspkg.sh:mount -t vfat /dev/mmcblk0p1 /mnt/mmc
./usr/bin/inspkg.sh:find /mnt/mmc -name "*$1*.deb" -exec dpkg -i {} \; 2> /dev/null
./usr/bin/ubi_initial.sh:mount -t vfat /dev/mmcblk0p1 /mnt/mmc
./usr/bin/ubi_initial.sh:cd /mnt/mmc
./usr/bin/remount_mmc.sh: nr_mnt_dev=`/usr/bin/stat -c %d /mnt/mmc` #/opt/storage
./usr/bin/remount_mmc.sh: umount /mnt/mmc 2> /dev/null
./usr/bin/remount_mmc.sh: /bin/mount -t vfat /dev/mmcblk${i}p1 /mnt/mmc -o uid=0,gid=0,dmask=0000,fmask=0000,iocharset=iso8859-1,utf8,shortname=mixed
./usr/bin/remount_mmc.sh: /bin/mount -t vfat /dev/mmcblk${i} /mnt/mmc -o uid=0,gid=0,dmask=0000,fmask=0000,iocharset=iso8859-1,utf8,shortname=mixed
[ stripped a bunch of binary matches in /usr/bin and /usr/lib ]
What we have here are some usual Linux boot-up configuration files (fstab
,
rcS.pivot
, ubi_initial.sh
), a very interesting script that installs any
Debian packages from the SD card (inspkg.sh
), and ~50 shared libraries and
executable binaries with the /mnt/mmc
string hardcoded inside.
Package Installer Script
Let us have a look at inspkg.sh
first:
#! /bin/sh
echo $1
if [ "$#" = "2" ]
then
if [ "$2" = "0" ]
then
echo -e "mount mmcblk0.."
mount -t vfat /dev/mmcblk0 /mnt/mmc
else
echo -e "mount mmcblk0p1..."
mount -t vfat /dev/mmcblk0p1 /mnt/mmc
fi
else
echo -e "mount mmcblk0p1..."
mount -t vfat /dev/mmcblk0p1 /mnt/mmc
fi
find /mnt/mmc -name "*$1*.deb" -exec dpkg -i {} \; 2> /dev/null
echo -e "sync...."
sync
This is a shell script that takes one or two arguments. The first one is the
package name to look for (the find
command will find and install all .deb
files containing the first argument in their name). The second argument is
used to mount the correct partition of the SD card. Surely we can use this
script to install dropbear,
gcc or moon-buggy. Now we only need to figure out how (or from where) this
script is run:
georg@megavolt:TIZEN/project/NX300/image/rootfs$ grep -r inspkg.sh .
georg@megavolt:TIZEN/project/NX300/image/rootfs$
Whoops. There are no references to it in the firmware. It was merely a red herring, and we need to find another way in.
The Magic Binary Blob
In /usr/bin
, the most interesting file is di-camera-app-nx300
, making
references to /mnt/mmc/Demo/NX300_Demo.mp4
, /mnt/mmc/SYSTEM/Device.xml
and
a bunch of WAV files in /mnt/mmc/sounds/
that seem to correspond to UI
actions (up
, down
, ..., delete
, ev
, wifi
).
This is obviously the magic binary blob controlling the really interesting functions (like the UI, the shutter, and the image processor). Most consumer electronics branded as "Open Source" contain some kind of Linux runtime which is only used to execute one large binary. That binary in turn encloses all the things you want to tinker with, but it is not provided with source code, still leaving you at the mercy of the manufacturer.
As expected, this program comes out of nowhere. There are traces of the
di-camera-app-nx300
Debian package (version 0.2.387) being installed:
Package: di-camera-app-nx300
Status: install ok installed
Priority: extra
Section: misc
Installed-Size: 87188
Maintainer: Sookyoung Maeng <[snip]@samsung.com>, Jeounggon Yoo <[snip]@samsung.com>
Architecture: armel
Source: di-camera-app
Version: 0.2.387
Depends: libappcore-common-0, libappcore-efl-0, libaul-1, libbundle-0, libc6 (>= 2.4),
libdevman-0, libdlog-0, libecore, libecore-evas, libecore-file, libecore-input,
libecore-x, libedje (>= 0.9.9.060+svn20100304), libeina (>= 1.0.0.001+svn20100831),
libelm, libevas (>= 0.9.9.060+svn20100203), libgcc1 (>= 1:4.4.0),
libglib2.0-0 (>= 2.12.0), libmm-camcorder, libmm-player, libmm-sound-0,
libmm-utility, libnetwork-0, libnl2 (>= 2.0), libslp-pm-0, libslp-utilx-0,
libstdc++6 (>= 4.5), libvconf-0, libwifi-wolf-client, libx11-6,
libxrandr2 (>= 2:1.2.0), libxtst6, prefman, libproduction-mode,
libfilelistmanagement, libmm-common, libmm-photo, libasl, libdcm,
libcapture-fw-slpcam-nx300, libvideo-player-ext-engine, libhibernation-slpcam-0,
sys-mmap-manager, libstorage-manager, libstrobe, libdustreduction, libmm-slideshow,
di-sensor, libdi-network-dlna-api, libproduction-commands, d4library,
diosal
Description: Digital Imaging inhouse application for nx300
So this package is created from di-camera-app
, which does not exist either,
except "inhouse". Thank you Samsung for spoiling the fun... :-(
Besides of some start/stop scripts, the only other interesting reference to
this magic binary blob is in TIZEN/build/exec.sh
, which looks like a mixture
of installation and startup script:
#!/bin/sh
#
cp -f *.so /usr/lib
cp -f di-camera-app-nx300 /usr/bin
sync
sync
sync
sleep 1
cd /
startx; di-camera-app &
(Because with only one sync
, you can never know, and two might still not be
enough if you must be 300% sure the data has been written).
The camera app is accompanied by another magic binary blob for WiFi,
smart-wifi-app-nx300
(Samsung should get an award for creative file names).
However, there are no hints at possible code execution in either program, so
we need to dig even deeper.
Searching Shared Libraries
The situation in /usr/lib
is different, though. We can run strings
on the
files that mention the SD card mount point (limiting the output to the
relevant lines):
georg@megavolt:TIZEN/project/NX300/image/rootfs$ for f in `grep -l /mnt/mmc *.so` ; do \
echo "--- $f" ; strings $f | grep /mnt/mmc; done
[snip]
--- libmisc.so
/mnt/mmc
/mnt/mmc/autoexec.sh
--- libnetwork.so
/mnt/mmc/iperf.txt
--- libstorage.so
/usr/bin/iozone -A -s 40m -U /mnt/mmc -f /mnt/mmc/test -e > /tmp/card_result.txt
cp /tmp/card_result.txt /mnt/mmc
/mnt/mmc/auto_run.sh
Okay, this is starting to get hot! /mnt/mmc/autoexec.sh
and
/mnt/mmc/auto_run.sh
are exactly what we have been looking for. We need to
try one of them and see what happens!
autoexec.sh
To test our theory, we need to mount the camera via USB, and create the
following autoexec.sh
file in its root directory (Windows users watch out,
the file needs to have Unix linebreaks!):
#!/bin/sh
LOG=/mnt/mmc/autoexec.log
date >> $LOG
id >> $LOG
echo "$PATH" >> $LOG
ps axfu >> $LOG
mount >> $LOG
Now we need to unmount the camera,
turn it off and on again, wait
some seconds, mount it, and check if we got lucky. Let's see... autoexec.log
is there! Jackpot! Now we can analyze its contents, piece by piece:
Fri May 9 06:25:20 UTC 2014
uid=0(root) gid=0(root)
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin:/sbin:/usr/local/bin:/usr/scripts
This output was just generated, it was running as root (yeah!), and the path looks rather boring.
PID VSZ RSS STAT COMMAND
[stripped boring kernel threads and some columns]
1 2988 52 Ss init
139 11460 1348 S /usr/bin/system_server
144 2652 188 Ss dbus-daemon --system
181 3416 772 Ss /usr/bin/power_manager
232 12268 4608 S<s+ /usr/bin/Xorg :0 -logfile /opt/var/log/Xorg.0.log -ac -noreset \
-r +accessx 0 -config /usr/etc/X11/xorg.conf -configdir /usr/etc/X11/xorg.conf.d
243 2988 76 Ss init
244 2988 56 Ss init
245 2988 60 Ss+ init
246 2988 56 Ss+ init
247 2988 8 S sh /usr/etc/X11/xinitrc
256 20200 2336 S \_ /usr/bin/enlightenment -profile samsung \
-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it
254 19876 8 S /usr/bin/launchpad_preloading_preinitializing_daemon
255 12648 816 S /usr/bin/ac_daemon
259 3600 8 S dbus-launch --exit-with-session /usr/bin/enlightenment -profile samsung \
-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it
260 2652 8 Ss /usr/bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
267 690688 34760 Ssl di-camera-app-nx300
404 2988 520 S \_ sh -c /mnt/mmc/autoexec.sh
405 2988 552 S \_ /bin/sh /mnt/mmc/autoexec.sh
408 2860 996 R \_ ps axfu
Our script is executed by di-camera-app-nx300
, there is enlightenment and
dbus running, and
i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it.
The mount point list looks pretty standard as well for an embedded device, using UBIFS for flash memory and the exfat driver for the SD card:
rootfs on / type rootfs (rw)
ubi0!rootdir on / type ubifs (ro,relatime,bulk_read,no_chk_data_crc)
devtmpfs on /dev type devtmpfs (rw,relatime,size=47096k,nr_inodes=11774,mode=755)
none on /proc type proc (rw,relatime)
tmpfs on /tmp type tmpfs (rw,relatime)
tmpfs on /var/run type tmpfs (rw,relatime)
tmpfs on /var/lock type tmpfs (rw,relatime)
tmpfs on /var/tmp type tmpfs (rw,relatime)
tmpfs on /var/backups type tmpfs (rw,relatime)
tmpfs on /var/cache type tmpfs (rw,relatime)
tmpfs on /var/local type tmpfs (rw,relatime)
tmpfs on /var/log type tmpfs (rw,relatime)
tmpfs on /var/mail type tmpfs (rw,relatime)
tmpfs on /var/opt type tmpfs (rw,relatime)
tmpfs on /var/spool type tmpfs (rw,relatime)
tmpfs on /opt/var/log type tmpfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
/dev/ubi2_0 on /mnt/ubi2 type ubifs (ro,noatime,nodiratime,bulk_read,no_chk_data_crc)
/dev/ubi1_0 on /mnt/ubi1 type ubifs (rw,noatime,nodiratime,bulk_read,no_chk_data_crc)
/dev/mmcblk0 on /mnt/mmc type exfat (rw,nosuid,nodev,noatime,nodiratime,uid=5000,gid=6,fmask=0022,
dmask=0022,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,namecase=0,errors=remount-ro)
Remote Access
The camera is not connected to your WiFi network by default, you have to
launch one of the WiFi apps first. The most reliable one for experimenting in
your (protected) home network is the Email app. After you launch it, the
camera looks for WiFi networks (configure your own one here), and stays
connected for a long time, keeping the X server (and anything you run via
autoexec.sh
) open.
After tinkering around with a static dropbear
binary downloaded from the
Internets (and binary-patching the references to dropbear_rsa_host_key
and
authorized_keys
), I ran into a really silly problem:
[443] May 09 12:00:45 user 'root' has blank password, rejected
Running a Telnet Server
Around the same time, I realized one thing that I should have checked first:
lrwxrwxrwx 1 17 May 22 2013 /usr/sbin/telnetd -> ../../bin/busybox
Our firmware comes with busybox, and busybox comes with telnetd
- an easy to
deploy remote login service. After
the realization settled, the
first attempt looked like we almost did it:
georg@megavolt:~$ telnet nx300
Trying 192.168.0.147...
Connected to nx300.local.
Escape character is '^]'.
Connection closed by foreign host.
georg@megavolt:~$ telnet nx300
Trying 192.168.0.147...
telnet: Unable to connect to remote host: Connection refused
Wow, the telnet port was open, something was running, but we crashed it! Another two mount-edit-restart-mount cycles later, the issue was clear:
telnetd: can't find free pty
Fortunately, the solution is documented. Now we can log into the camera for sure?
georg@megavolt:~$ telnet nx300
Trying 192.168.0.147...
Connected to nx300.local.
Escape character is '^]'.
************************************************************
* SAMSUNG LINUX PLATFORM *
************************************************************
nx300 login: root
Login incorrect
Damn, Samsung! Why no login? Maybe we can circumvent this in some way? Does the busybox telnetd help provide any hints?
-l LOGIN Exec LOGIN on connect
Maybe we can replace the evil password-demanding login
command with... a
shell? Let us adapt our SD card autoexec.sh
script to what we have
gathered:
#!/bin/sh
mkdir -p /dev/pts
mount -t devpts none /dev/pts
telnetd -l /bin/bash -F > /mnt/mmc/telnetd.log 2>&1 &
Another mount-edit-restart cycle, and we are in:
georg@megavolt:~$ telnet nx300
Trying 192.168.0.147...
Connected to nx300.local.
Escape character is '^]'.
************************************************************
* SAMSUNG LINUX PLATFORM *
************************************************************
nx300:/# cat /proc/cpuinfo
Processor : ARMv7 Processor rev 8 (v7l)
BogoMIPS : 1395.91
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 8
Hardware : Samsung-DRIMeIV-NX300
Revision : 0000
Serial : 0000000000000000
nx300:/# free
total used free shared buffers cached
Mem: 512092 500600 11492 0 132 41700
-/+ buffers/cache: 458768 53324
Swap: 30716 8084 22632
nx300:/# df -h /
Filesystem Size Used Available Use% Mounted on
ubi0!rootdir 352.5M 290.8M 61.6M 83% /
nx300:/# ls -al /opt/sd0/DCIM/100PHOTO/
total 1584
drwxr-xr-x 2 root root 520 May 22 2013 .
drwxr-xr-x 3 root root 232 May 22 2013 ..
-rwxr-xr-x 1 root root 394775 May 22 2013 SAM_0015.JPG
-rwxr-xr-x 1 root root 335668 May 22 2013 SAM_0016.JPG [Obama was here]
-rwxr-xr-x 1 root root 357591 May 22 2013 SAM_0017.JPG
-rwxr-xr-x 1 root root 291493 May 22 2013 SAM_0018.JPG
-rwxr-xr-x 1 root root 232470 May 22 2013 SAM_0019.JPG
nx300:/#
Congratulations, you have gained network access to yet another Linux appliance! From here, you should be able to perform anything you want on the camera, except from the interesting things closed in the Samsung binaries.
Full series:
Hey Georg,
these are great news - thanks for you work. Since the NX300 comes with Tizen i was hoping for something like a "Samsung Magic Latern" and finally it seems there might be a way.
I hope you to do further development, as an example the new Remote Viewfinder of the NX30 might be an addition or of course some more simple tweaks.
Thanks again for your work,
Lars
thnx for this share, nice read. boot
Great digging you did. I tried your effort on my NX2000. Same here:
Now I would like to see to be automatically connected to a certain SSID and having started a permanent 1080p-multicast-streaming-server. Challenge opened ...
Is the buffer/cache memory the one used for buffering of repeated shooting? If so, is it possible to free some more memory in order to enhance the poor buffering capabilities of nx300?
Besides, as already stated, is it possible to adapt the nx30 firmware to run on nx300? They should have the same hw, except for the evf, but the nx30 has some enhanced functions (like remote evf pro).
Fun fact: checking for some web references in the camera app for nx2000
nx2000/project/NX2000/image/rootfs$ strings ./usr/bin/di-camera-app-nx2000 | grep http
result> http://deathclock.com/
WTF? :)
BTW you need some comment spam protection :)
It is well possible that Samsung removed that functionality from their newer devices/firmwares. There are reports that on the NX300M you need to downgrade firmware to 1.11 (or below that) to use
autoexec.sh
.You should download your camera's source tree and grep/string-search it for
autoexec.sh
(or similar things), like I did in the blog post. If you are lucky, they merely renamed the script. If you are less lucky, they removed that functionality altogether.Also, please come to the new Samsung NX Hacks project on github, it is a much better place to track progress. I would suggest you open a new issue there for the NX500.
can you provide details to access the DLNA stream with any device, or how to access the shutter or video recording control? I wanto to make a java app to sync NX cameras (you may easily imagine why).
thanks