Server:Server Status

Improving the Motorola Blink Baby Monitor/Camera (Part…6?!?)

After all this time...why am I still working on this? The cameras are dead, Motorola shut down the monitoreverywhere service, so the cameras are dead! You can't register them, or join to cameras remotely, right?

Well, they still work on the LAN, so if they're already on the wifi, you can use them as little RTSP streams. The problem is...I want to change my SSID's, and there's no way to rejoin to wifi without the app connecting with the (now offline) monitoreverywhere service.

Enter crazy old Joe. I had a Titanium Backup of the apk and my config from an android device I don't even have anymore. I was able to extract this and decompile it to learn how the app handles registration, then emulate that. First, from previous research, when you factory reset a camera it broadcasts a "Camera-######" SSID when you can connect to as it's open. You'll get a 192.168.2.# address, and the camera will be "192.168.2.1". From there, you can start performing operations on the camera, for example, If you go here in a web browser: http://192.168.2.1/?action=command&command=enable_telnet You will then be able to telnet to the camera.

From previous work, we know a lot of the scripts and commands on there, but I never found how to format the wifi request. So, I started poking through the apk. Here's some snippets that are useful:

this.cam_profile.setBasicAuth_usr("camera");
this.cam_profile.setBasicAuth_pass("000000");

The camera has a basic http authentication piece, and that is the default username and password...maybe. I also found this in defining the variables:

this.usr_name = usrName == null ? "" : usrName;
this.pass_wd = pwd == null ? "" : pwd;

So the user and password will either be "camera:000000" or ":". We can try both.

public String build_setup_core_request() {
    String auth_mode;
    String key_index;
    if (this.security_type.equalsIgnoreCase("WEP")) {
        auth_mode = this.auth_method.equalsIgnoreCase("Open") ? "0" : "1";
        key_index = String.format("%d", Integer.valueOf(Integer.parseInt(this.key_index) - 1));
    } else if (this.security_type.equalsIgnoreCase("OPEN")) {
        auth_mode = "0";
        key_index = "0";
    } else {
        auth_mode = "2";
        key_index = "0";
    }
    String ssid_len = String.format("%03d", Integer.valueOf(this.ssid.getBytes().length));
    String sec_key_len = String.format("%02d", Integer.valueOf(this.pass_string.length()));
    String usr_name_len = String.format("%02d", Integer.valueOf(this.usr_name.length()));
    String passwd_len = String.format("%02d", Integer.valueOf(this.pass_wd.length()));
    String setup_value = String.valueOf("1") + "00" + auth_mode + key_index + "0" + ssid_+ sec_key_len + "0000000" + usr_name_len + passwd_len + this.ssid + this.pass_string + .usr_name + this.pass_wd;
    if (shouldEncodeData()) {
        try {
            setup_value = URLEncoder.encode(setup_value, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Log.d(GcmIntentService.TAG, "Encode setup data");
    } else {
        Log.d(GcmIntentService.TAG, "No need to encode setup data.");
    }
    String setup_request = "/?action=command&command=setup_wireless_save&setup=" + setup_value;
    return setup_request;
}

That is exactly what we need. First of all, since the security type would be "WPA2/PSK" auth_mode is 2 and key_index is 0. The SSID length is formatted to be 3 digits (mine is 32 characters, so 032), and the passcode length is formatted to be 2 digits (mine is 26 characters, so 26).

That means the pieces needed break down into one of these 2:

1 00 2 0 0 032 26 000000 06 06 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS PPPPPPPPPPPPPPPPPPPPPPPPPP camera 000000

or

1 00 2 0 0 032 26 000000 00 00 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS PPPPPPPPPPPPPPPPPPPPPPPPPP

Following all that string concatenation, we have 2 options to set up the wifi, depending on which password configuration it needs (SSID and passcode are obfuscated):

http://192.168.2.1/?action=command&command=setup_wireless_save&setup=1002000322600000000606SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSPPPPPPPPPPPPPPPPPPPPPPPPPPcamera000000
http://192.168.2.1/?action=command&command=setup_wireless_save&setup=1002000322600000000000SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSPPPPPPPPPPPPPPPPPPPPPPPPPP

The 2nd one worked; the camera made a loud beep but the SSID was still active. I telnetted to the camera and this was in /var/log/messages:

Jan  1 15:54:57 MJPG-streamer [1901]: Org client thread : GET /?action=command&command=setup_wireless_save&setup=1002000322600000000000SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSPPPPPPPPPPPPPPPPPPPPPPPPPP HTTP/1.1^M
Jan  1 15:54:57 MJPG-streamer [1901]: After URL Encode : GET /?action=command&command=setup_wireless_save&setup=1002000322600000000000SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSPPPPPPPPPPPPPPPPPPPPPPPPPP HTTP/1.1^M
Jan  1 15:54:57 MJPG-streamer [1901]: Connect 192.168.2.11
Jan  1 15:54:57 MJPG-streamer [1901]: access granted
Jan  1 15:54:57 MJPG-streamer [1901]: command string: setup_wireless_save
Jan  1 15:54:57 MJPG-streamer [1901]: setup=1002000322600000000000SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSPPPPPPPPPPPPPPPPPPPPPPPPPP HTTP/1.1^M
Jan  1 15:54:57 MJPG-streamer [1901]: len=91
Jan  1 15:54:57 MJPG-streamer [1901]: 1002000322600000000000SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSPPPPPPPPPPPPPPPPPPPPPPPPPP HTTP/1.1^M
Jan  1 15:54:57 MJPG-streamer [1901]: len SSID 32 and index 9
Jan  1 15:54:57 MJPG-streamer [1901]: Key Length = 26
Jan  1 15:54:57 MJPG-streamer [1901]: String got is:0
Jan  1 15:54:57 MJPG-streamer [1901]: Len of workport is:0
Jan  1 15:54:57 MJPG-streamer [1901]: SSID='SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS' - Key='PPPPPPPPPPPPPPPPPPPPPPPPPP'
Jan  1 15:54:57 MJPG-streamer [1901]: Before sem wait
Jan  1 15:54:57 MJPG-streamer [1901]: After sem wait
Jan  1 15:54:57 MJPG-streamer [1901]: Finish init Flash
Jan  1 15:54:57 MJPG-streamer [1901]: Flash Init 20 (1901)
Jan  1 15:54:57 MJPG-streamer [1901]: Before sem post
Jan  1 15:54:57 MJPG-streamer [1901]: Flash DeInit 20 (1901)
Jan  1 15:54:57 MJPG-streamer [1901]: Finish deinit Flash
Jan  1 15:54:57 MJPG-streamer [1901]: After sem post
Jan  1 15:54:57 MJPG-streamer [1901]: ===WRITE TO FLASH===
Jan  1 15:54:57 MJPG-streamer [1901]: Before sem wait
Jan  1 15:54:57 MJPG-streamer [1901]: After sem wait
Jan  1 15:54:57 MJPG-streamer [1901]: Finish init Flash
Jan  1 15:54:57 MJPG-streamer [1901]: Flash Init 20 (1901)
Jan  1 15:54:57 MJPG-streamer [1901]: Before sem post
Jan  1 15:54:57 MJPG-streamer [1901]: Flash DeInit 20 (1901)
Jan  1 15:54:57 MJPG-streamer [1901]: Finish deinit Flash
Jan  1 15:54:57 MJPG-streamer [1901]: After sem post
Jan  1 15:54:57 MJPG-streamer [1901]: Wifi configuration saved successfully
Jan  1 15:54:57 MJPG-streamer [1901]: leaving

It looked like it took, so I rebooted the camera, and it connected and got its proper assigned DHCP address! I am able to view the camera connected to the correct SSID! As far as I'm concerned, the camera is now back to as operational as I want it to be, despite the vendor's abandoning of the device.

Leave a Reply