telmomarques / xiaomi-360-1080p-hacks

Hacks for the Xiaomi Mi 360 1080p camera (MJSXJ02CM).
762 stars 129 forks source link

Compatibility with Mijia 1080p MJSXJ05CM ? #18

Open Jayah59 opened 4 years ago

Jayah59 commented 4 years ago

Hi !

Is this compatible ? I tried downloading tf_recovery.bin to sdcard and flashing but it did not work and I worse, I think my camera is bricked ...

LED amber is not blinking, it is permanent on and the camera does not move. Same observation without sd card

.<

jandy123 commented 3 years ago

@telmomarques: I can confirm your buildroot toolchain does the trick.

Thanks again !

fumanchi commented 3 years ago

@rezmus Thanks... The retspserver binary file is (or at least seams to be) statically built/linked but does not understand the current arguments (here: "-c ...json" ~> /mnt/data/bin/rtspserver: invalid option -- 'c' I probably need to compile buildroot and the rtspserver on my own :(

fumanchi commented 3 years ago

@jandy123 Do you managed to build a working rtspserver binary from current sources? I would be very pleased to get my hands on a working rtspserver :)

rezmus commented 3 years ago

@fumanchi

you only need -m -s for pipes. look at alpha.v3.zip\hacks\rtsp-server\meta\service\ for the scripts which starts framegrabber/rtspserver.

fumanchi commented 3 years ago

@rezmus I see.. but no success... the binaries run/work.. but i neither get a valid rtsp stream nor a webstream... the named pipes in /mnt/data/etc/framegrabber/ do provide data but i cannot get any connection to the rtsp or web stream...

rezmus commented 3 years ago

can you see the stream in mi home app? it works for me.

extract alpha v3 hacks, replace framegrabber with uclibc version.

cd /mnt/sdcard/hacks/rtsp-server/meta/service/ ./framegrabber-mainstream &

open 2nd telnet window.

cd /mnt/sdcard/hacks/rtsp-server/meta/service/ ./rtsp-server &

connect with vlc to rtsp://cameraip:8554/mainstream

2879597772 commented 3 years ago

A firmware hack is possible, but requires some tools:

  • CH341A flash programmer
  • SOIC8 clip and some dupont wires
  • Complete device teardown

Basic steps are:

  • Create a flash backup: flashrom -p ch341a_spi -r backup.bin
  • Download the firmware and put it into the same folder.
  • Run this script to patch the backup:
#!/bin/bash
# extract firmware
mkdir -p files
dd if=tf_recovery.img of=files/kernel.bin bs=1 count=2097152
dd if=tf_recovery.img of=files/rootfs.bin bs=1 count=7733248 skip=2097152
dd if=tf_recovery.img of=files/data.bin bs=1 count=6488064 skip=9830400
dd if=backup.bin of=files/vendor.bin bs=1 count=131072 skip=16646144

# patch jffs2 partition
sudo modprobe mtdblock
sudo modprobe mtdram total_size=6336
sudo dd if=files/data.bin of=/dev/mtdblock0 bs=1
mkdir mount
sudo mount -t jffs2 /dev/mtdblock0 mount
echo '#!/bin/sh' | sudo tee -a mount/bin/log_diag_platform.sh
echo '/mnt/sdcard/override.sh' | sudo tee -a mount/bin/log_diag_platform.sh
sudo chmod 755 mount/bin/log_diag_platform.sh
sudo umount mount
rmdir mount
sudo dd if=/dev/mtdblock0 of=files/data.bin bs=1

# update flash backup
mkdir -p out
cp backup.bin -f out/flash.bin
dd if=files/kernel.bin of=out/flash.bin bs=1 count=2097152 seek=327680
dd if=files/rootfs.bin of=out/flash.bin bs=1 count=7733248 seek=2424832
dd if=files/data.bin of=out/flash.bin bs=1 count=6488064 seek=10158080
dd if=files/vendor.bin of=out/flash.bin bs=1 count=131072 seek=16646144
  • Re-flash the modified backup: flashrom -p ch341a_spi -w out/flash.bin
  • Prepare the sdcard script:

/sdcard/override.sh

#!/bin/sh
main() {
  # start telnet
  /mnt/sdcard/busybox telnetd
}

if [ ! -f /tmp/.override ]; then
 touch /tmp/.override
 main
fi
  • Press the reset button (briefly) on the camera to launch the override script.

Does anybody know how this was obtained? I used the Binwalk tool and didn't understand how it worked,I don't know how "count" gets "vendor.bin", what is the use, can anyone tell me?

jandy123 commented 3 years ago

@2879597772: just read carefully the instructions you refer to. You'll have to disassemble the camera, and have the appropriate hardware. If you don't, just stay away... just an advice.

fumanchi commented 3 years ago

@rezmus I will try this procedure but I'd actually like to be able to stay as up to date as possible... therefor I am going try "buildroot" to be able to build the latest versions when they are released... I want to integrate the cam(s) into my home automation... the first thing is to detect the remaining times of the washing machine and tumbler in the cellar :)

2879597772 commented 3 years ago

When is the right time to press the button? After power on or?

fumanchi commented 3 years ago

@2879597772 You might wait for the cams initialization (here: calibrating the servos)... but you can safely apply the hack much erlier if you like... e.g. just after the wifi connection has been established (led turns blue)...

jandy123 commented 3 years ago

@telmomarques: I was wondering, is h264 supported by the rtsp server? Apparently h265 (the default of rtsp streamer) is not supported by hassio, so I'm looking into streaming mjpeg as alternative...

rezmus commented 3 years ago

rtspserver can handle h264, but cam firmware does h265 by default. for older cams telmo patched libboardav.so.1.0.0 to enable h264.

jandy123 commented 3 years ago

@rezmus: hmm, very interesting. do you know what this patch consists of ? That lib is definitely available :)

jandy123 commented 3 years ago

@rezmus: Is there a git commit ?

rezmus commented 3 years ago

it was 1 byte found/patched using IDA.

jandy123 commented 3 years ago

Ok, thanks for info. Maybe @telmomarques sees this and shares some light :).

telmomarques commented 3 years ago

@jandy123 the hardware supports both h264 and h265, but xiaomi's firmware only exposes H265. The patch is on rtspserver.go:51

The "problem" is that by changing to H264 the xiaomi mobile app will no longer show any image.

jandy123 commented 3 years ago

@telmomarques: Hmm, I was afraid about this. So, maybe it's still worth offering an mjpg stream, while still keeping the app working, since I think this should be doable... Pity though that we can't have both ;).

telmomarques commented 3 years ago

It's technically doable, the hardware supports multiple channels with independent encodings. The problem is that reverse engineering a patch to do that is much more difficult.

But even if done it would still be limited to h264/h265, as reencoding to something else (e.g. mjpeg) would not be possible on the camera due to lack or processing power.

jandy123 commented 3 years ago

@telmomarques: do you maybe remember what should I search for when patching libboardav ?

Thanks !

telmomarques commented 3 years ago

@jandy123 sorry I don't remember exactly what to look for, but if you're decompiling stuff you can try checking the memory address that is patched on libboardav from 02 cam to see if there's anything identifiable.

jandy123 commented 3 years ago

@telmomarques: My idea wasn't to reencode the hevc stream to mjpeg. Instead, I've noticed that shbf_client takes jpeg snapshots every minute, while still streaming through the app. I thought I could patch/rewrite somoething similar and make an input module for mjpg-streamer, see https://sourceforge.net/p/mjpg-streamer/code/HEAD/tree/. This could then be completely independent, much like the current rtsp server.

====

Anyways, I'll check out your patch against the 02 library. I assume your patch is for libboardav from 3.4.2_0062, right ?

Thanks !

telmomarques commented 3 years ago

Anyways, I'll check out your patch against the 02 library. I assume your patch is for libboardav from 3.4.2_0062, right ?

Yes that's correct!

2879597772 commented 3 years ago

I noticed that we modified the JFFS2 partition, so why don't we change it directly rootfs.bin To achieve better results? I used "unsquashfs files/rootfs.bin” and "mksquashfs squashfs-root files/rootfs.squashfs -comp xz" command refactored rootfs and started successfully

I modified line 27 in the file "squashfs-root/etc/inittab" to support TTL, and modified the file "squashfs-root/etc/init.d/S49factory" so that it can be loaded directly as before manu.sh

After the above modification, the camera can still work normally TTL is on sdcsrd/manu_ test/manu.sh It can also work normally Now that the camera has been completely removed, why not use the new firmware to modify it

jandy123 commented 3 years ago

@2879597772: As far as I understand, there is a hash check of the firmware file.

2879597772 commented 3 years ago

@jandy123 In fact, this modification can still be started normally. I think hash check is aimed at tf_recovery.img The hash check is invalid for programmer firmware

jandy123 commented 3 years ago

@2879597772: I'm sorry, but then I do not understand what you mean. Do you have telnet working ?

telmomarques commented 3 years ago

@jandy123 when flashing through uboot (tf_recovery.img on sdcard), then uboot will indeed reject any wrongly signed/unsigned firmware image.

But if you grab a serial monitor or a flash programmer then you can burn any firmware image because there's no checks.

I didn't pursue the second solution because it's not user friendly, as it requires the camera to be opened and special hardware to be used. A better solution would be to find another exploit, a way to sign custom firmware images or a way to sign the manu exploit (that still exists on newer cameras, but is also signed).

jandy123 commented 3 years ago

@telmomarques: yes this is/was clear to me.

==

Btw. I've seen what your patch of libboardav did with IDA. Unfortunately, in 05CM, the library is completely changed compared to 02CM...

So, I'm after mjpeg ;).

2879597772 commented 3 years ago

@telmomarques I noticed that 02cm is a hack using "s49factory". In 05cm, "s49factory" has been modified as follows

S49factory:

!/bin/sh

must to verify the sdcard

MANUFA="/mnt/sdcard/manu_test" MANUFA_BIN="/mnt/sdcard/manu_test/manu.bin" MANUFA_DAT="/mnt/sdcard/manu_test/md5sum.dat" TMP_BIN="/tmp/manu.bin" TMP_DAT="/tmp/md5sum.dat"

try_ft_mode() { if [ -f "${MANUFA_DAT}" ]; then rm -rf /tmp/manu_test rm -fr ${TMP_BIN} rm -fr ${TMP_DAT} echo "md5sum.dat"

openssl smime -decrypt -in "$MANUFA_DAT" -binary -inform DEM -inkey /mnt/data/data/cfg/public-key.pem -out "$MANUFA_BIN"

    #openssl rsautl -sign -in "$MANUFA_DAT" -inkey RSA.pem  -passin pass:123456 -out "$MANUFA_BIN"
    cp ${MANUFA_BIN} /tmp/
    cp ${MANUFA_DAT} /tmp/
    cd /tmp/
    rm -fr md5sum1.txt
    openssl rsautl -verify -in "${TMP_DAT}" -inkey /mnt/data/data/cfg/public-key.pem -pubin -out md5sum1.txt
    fact_md5=`md5sum -c md5sum1.txt`
    if [ "${fact_md5}" = "manu.bin: OK" ] ; then
        echo "md5 ok"
        rm -fr ${TMP_BIN}
        tar -xf "${MANUFA_BIN}" -C /tmp/
        cd /tmp/manu_test/
        chmod -R 755 *
        if [ -f "/tmp/manu_test/manu.sh" ]; then
            /tmp/manu_test/manu.sh
            return 0
        else
            return 1
        fi
    else
        echo "md5 fail"
    fi
fi
return 1

}

case "$1" in start) mount /dev/mmcblk0p1 /mnt/sdcard || mount /dev/mmcblk0 /mnt/sdcard || exit $? if try_ft_mode; then touch /tmp/factory_mode else umount /mnt/sdcard fi ;; stop) echo "do nothing" ;; restart|reload) "$0" stop "$0" start ;; *) echo "Usage: $0 {start|top|restart}" exit 1 esac

exit $?

Is it still possible to hack?

rezmus commented 3 years ago

they made it to prevent people using it (manu.bin payload is rsa signed). all current imilab ipc cams have the same S49factory. that's why MJSXJ02CM owners have to downgrade to very old firmware without manu_test protection to be able to use hack.

jandy123 commented 3 years ago

mjpg streamer

I've managed to get mjpg streamer working on 05CM. If you want to try it, unpack the archive in some folder on the sdcard, login on the cam and start it in console using:

./mjpg_streamer -i "input_snapshot.so -d 1000" -o output_http.so

Then, on a different computer, in the browser go to http:::8080/?action=stream. You should be able to see the mjpeg stream. To take a snapshot use: http:::8080/?action=snapshot.

The parameter -d above is the delay between frames in ms. As is, the delay is 1 sec. You may try to decrease it, but keep an eye on the CPU load. If too small values are used, seems that streaming stops working, so please be careful.

This is useful here, since I can finally get the stream in hassio, while still keeping the app functional.

Please test and report here.

https://drive.google.com/file/d/1C5dw4VxRW4Hu__eJI2W-2AnMqtHCPcqc/view?usp=sharing

rezmus commented 3 years ago

gdrive share is not public.

jandy123 commented 3 years ago

@rezmus: Sorry, should be fine now ;).

rezmus commented 3 years ago

works as expected.

jandy123 commented 3 years ago

@rezmus: well, glad to hear. Let's still test a bit.

2879597772 commented 3 years ago

Who knows how to trigger the sound of the camera, such as "restart" and "upgrade"

jandy123 commented 3 years ago

I uploaded an improved version of the mjpg streamer.

The improvement is that once a client closes connection, streaming is also paused. I've noticed that the initial version came in conflict with the camera recording. This tries to fix this issue in the sense that if only one client is active at the time (either mjpg or normal recording for e.g. motion detection initiated from app), the behaviour is as expected.

thewh1teagle commented 3 years ago

Can you share source code of the mjpg streamer?

2879597772 commented 3 years ago

@jandy123 MJPG Streamer Version: svn rev: Unversioned directory ERROR: could not find input plugin Perhaps you want to adjust the search path with:

export LD_LIBRARY_PATH=/path/to/plugin/folder

   dlopen: File not found
jandy123 commented 3 years ago

@2879597772: Please set LD_LIBRARY_PATH to point to the dir where you unpacked the sources in the sdcard. Something like:

# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<path_to_dir>

should do. Then start mjpg streamer:

# ./mjpg_streamer -i input_snapshot.so -o output_http.so

jandy123 commented 3 years ago

@thewh1teagle: Code is available below:

https://drive.google.com/file/d/1v5_0D0_peyV06OogRuxyC1P59Znh8qRx/view?usp=sharing

It's based on https://sourceforge.net/p/mjpg-streamer/code/HEAD/tree/ .

To compile change the makefiles in mjpg-streamer-experimental, mjpg-streamer-experimental/plugins/input_snapshot and mjpg-streamer-experimental/plugins/output_http to set the CC var to point to the toolchain gcc. The important plugin is the input_snapshot. If you want to port to 02CM, you may need to change libraries in mjpg-streamer-experimental/plugins/input_snapshot/libs.

Please take it with a grain of salt, since it's still very much of a hack. I'd appreciate if someone makes it available in some git repo and refactors/imrpoves the input plugin. If you have questions, let me know.

2879597772 commented 3 years ago

@2879597772: Please set LD_LIBRARY_PATH to point to the dir where you unpacked the sources in the sdcard. Something like:

# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<path_to_dir>

should do. Then start mjpg streamer:

# ./mjpg_streamer -i input_snapshot.so -o output_http.so

Thank you, but I still don't quite understand. ' path_to_dir> 'What is it, the directory in which mJPg_streamer resides or the directory in which SDcard/Hanks resides

jandy123 commented 3 years ago

@2879597772: Is the sdcard directory where the mjpg files are. Something like: /mnt/sdcard/xxx

telmomarques commented 3 years ago

Hi @tty74it , please join the discord server, you can find the link in the readme.

2879597772 commented 3 years ago

@ 2879597772:是mjpg文件所在的sdcard目录。类似于:/ mnt / sdcard / xxx I'm sorry, but I still fail My MJPgstreamer is in the "/mnt/sdcard/mjpg_streamer" folder I set "export LD_LIBRARY_PATH='/mnt/sdcard/hacks/mjpeg-streamer'" But still report the original error, is there something wrong with my operation? Or can you tell me what environment it needs to run in

jandy123 commented 3 years ago

@2879597772: If mjpeg streamer is in /mnt/sdcard/mjpg_streamer then you should say:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/sdcard/mjpg_streamer

2879597772 commented 3 years ago

@2879597772: If mjpeg streamer is in /mnt/sdcard/mjpg_streamer then you should say:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/sdcard/mjpg_streamer

Thank you, "mjpg_streamer" can work normally. This is good news, but there are still shortcomings. The first is the video image comparison card. Even if it is set at 100ms, it still looks like 1s, but it is not without advantages. At least the image is very clear.

jandy123 commented 3 years ago

@2879597772: I don't think it's possible to get better framerates, so we'll have to live with this...