xoseperez / espurna

Home automation firmware for ESP8266-based devices
http://tinkerman.cat
GNU General Public License v3.0
2.99k stars 636 forks source link

Air quality sensor JQ-300 request #1644

Open fastjack opened 5 years ago

fastjack commented 5 years ago

I found a chinese air quality sensor on Aliexpress. There doesn't seem to be a manufacturer associated with it. The device is simply called JQ-300. It contains an ESP-8266 and what looks like a SHARP GP2Y1010AUF0F (looks very similar to the dust sensor in the Sonoff SC)

I have attached pictures of the board and sensor.

2B54B191-F1CE-4B11-B007-CB088FA2ED59 2072FF90-DA44-46A2-BA56-BD8BC4FC594B CCA5F0F2-9C02-42CC-BFF9-4508EFE809A6 CF6162BF-F2CE-46AC-A60B-F7A306B6A72B

Stoatwblr commented 3 years ago

Got some moderate success on Tasmota with this template:

How did you manage to tasmotize it? If I tie down gpio0 then I can't talk to the ESP8266 (standard way of putting device into programming mode) tieing down EXT_RSTB appears to prevent the ESP8266 booting up at all (rather than blocking U5 from transmitting)

I get the impression that U5 is a pretty dumb device

Leo-PL commented 3 years ago

Got some moderate success on Tasmota with this template:

How did you manage to tasmotize it? If I tie down gpio0 then I can't talk to the ESP8266 (standard way of putting device into programming mode) tieing down EXT_RSTB appears to prevent the ESP8266 booting up at all (rather than blocking U5 from transmitting)

I get the impression that U5 is a pretty dumb device

I struggled with connecting UART too, despite putting it in programming mode, so I did a chip-off and used CH341A-based SPI flash programmer together with flashrom. I needed to dump an empty flash and "patch" it with some xxd hackery for flashrom to not complain about Tasmota image being to small for the device. Something along the lines of cat <(xxd empty_flash.bin) <(xxd tasmota.bin) | xxd -r > tasmota-fullflash.bin. If you hold EXT_RSTB low, you might have some luck with programming SPI-flash using a clip, if you have one available, this should avoid the chip-off.

Leo-PL commented 3 years ago

Turns out that mere 115200bps is the correct baud. Who knew.

00:16:31 CMD: BaudRate 115200
00:16:31 SER: Set to 8N1 115200 bit/s
00:16:31 RSL: stat/tasmota_8F0A5B/RESULT = {"Baudrate":115200}
00:16:34 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382736280025000445F0"}
00:16:37 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000428F0"}
00:16:40 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000449F0"}
00:16:44 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000439F0"}
00:16:47 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382734280025000430F0"}
00:16:51 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000451F0"}
00:16:54 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735270025000433F0"}
00:16:58 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735270026000421F0"}
00:17:01 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735270026000440F0"}
00:17:04 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382736270026000470F0"}
00:17:08 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382728270026000448F0"}
00:17:11 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382734270026000456F0"}
00:17:15 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382734280026000463F0"}
00:17:18 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280026000442F0"}
00:17:22 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382734280026000426F0"}
00:17:25 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000446F0"}
00:17:29 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000443F0"}
00:17:32 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382736280025000454F0"}
00:17:35 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000451F0"}
00:17:39 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000417F0"}
00:17:42 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382734280025000439F0"}
00:17:46 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382722280026000438F0"}
00:17:49 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000439F0"}
00:17:53 RSL: tele/tasmota_8F0A5B/RESULT = {"SerialReceived":"5950FE0027382735280025000449F0"}

So the proper config would be:

SerialConfig 8N1
Baudrate 115200
SerialDelimiter 255
Rule1 ON System#Boot SerialSend4 "device_request_all_data\n"
Rule1 on
Stoatwblr commented 3 years ago

I have some pogo pins on the way in order to 3dprint a chip clip on other devices. I'll make a clip for the SPI and try that, although I wonder if lifting the MCU might work

We really do need to find a way of breaking into these things without needing to get too fancy. All this work is defeating the attraction of the cheapness of the device

wvsbsp commented 3 years ago

A lot of the time these blanked out chips have been painted over. I'm going to try an acetone attack and see if it helps identify the thing (EDIT: nope, acetone didn't work. These really do seem to be some kind of unbranded a/d converter)

I think, U5 is a microcontroller. Perhaps a PIC16F688 or PIC16F1824. Both have UART, I2C and a 8Ch 10Bit ADC. Only the assignment of Rx (Pin5) and Tx (Pin6) does not match the layout. And i dont't think they are using software serial at 115200 when the hardware UART is othewise unused... Also SDA ans SCL do not match. However, the UART-Pins match for the AtTiny804, but not the SCL/SDA (which is no big deal with software-i2c) Maybe it is just some chinese 5ct microcontroller.

zerog2k commented 3 years ago

Thanks @Leo-PL On a JQ-200 (no dust sensor), was able to flash Tasmota 9.2.0 with flash chip in-circuit with an 8 pin clamp and pulling pin 13 (esp nrst) low on the U5 namless mcu. I ordered a wch341a chip (darned buspirate is just too slow). (I wasted troubleshooting time trying to use minimal build to find out that doesn't work properly), and then get the serial strings pumping out to mqtt. Will lash up a python script for reading and decoding from mqtt if I get a chance.

tele/tasmota_CFD737/RESULT {"SerialReceived":"5950FE0021522152190032000000F0"}
tele/tasmota_CFD737/RESULT {"SerialReceived":"5950FE0021542152190033000000F0"}
tele/tasmota_CFD737/RESULT {"SerialReceived":"5950FE0021522142190033000000F0"}
tele/tasmota_CFD737/RESULT {"SerialReceived":"5950FE0021522143190033000000F0"}
tele/tasmota_CFD737/RESULT {"SerialReceived":"5950FE0021522150190034000000F0"}
tele/tasmota_CFD737/RESULT {"SerialReceived":"5950FE0021522142190033000000F0"}
tele/tasmota_CFD737/RESULT {"SerialReceived":"5950FE0021522143190033000000F0"}

goodbye craptastic ypyt I'll also try this on my JQ-300 (which has dust sensor attached).

zerog2k commented 3 years ago

also observed that if I hold down the button on the back (which is connected to u5 mcu):

  1. more than 2 secs: {"SerialReceived":"5950F3909090F0"}
  2. more than 6 secs: {"SerialReceived":"5950F4000000F0"}
Leo-PL commented 3 years ago

It may make sense to check for those, and trigger deep sleep, the reset line on "unknown" MCU connected to ESP2866 NRST is likely output to wake ESP up.

zerog2k commented 3 years ago

ok got some basic output working (TODO: parse and send to influxdb/grafana)

https://gist.github.com/zerog2k/804feb1d9159bf5610be89d6662e5749

$ ./tasmota_sensor_parse.py tele/+/RESULT
Connected with result code 0
Sun Jan 17 15:20:56 2021 tele/tasmota_CFD737/RESULT
msg: a=2279 b=2262 temp=21 hum=30 dust=0000
Sun Jan 17 15:20:59 2021 tele/tasmota_D3D1A7/RESULT
msg: a=2439 b=2421 temp=25 hum=27 dust=0556
Sun Jan 17 15:21:00 2021 tele/tasmota_CFD737/RESULT
msg: a=2279 b=2262 temp=21 hum=30 dust=0000
Sun Jan 17 15:21:02 2021 tele/tasmota_D3D1A7/RESULT
msg: a=2439 b=2422 temp=25 hum=27 dust=0526
Sun Jan 17 15:21:03 2021 tele/tasmota_CFD737/RESULT
msg: a=2279 b=2262 temp=21 hum=30 dust=0000

note the significant temperature and humidity variance between two units sitting next to each other in same room

The a and b values as discussed earlier in this thread seem to be some raw values relating to hcho/tvoc/eco2, but not sure what they are. Does anybody know what sensor is being used? (anybody sniff the i2c or whatever to get an idea of the register set in use, to possibly identify the chip being used?)

I did observe when putting a napkin soaked with isopropyl alcohol near the unit, the b value started to decrease rapidly (into 1600's), whilea value stayed about the same. Not really sure what units this is (raw mV, etc)? "Normally" these two values seem to be about the same.

jmw6773 commented 3 years ago

I was able to install Tasmota on my board tonight by flashing the Winbond flash using chip-clip and bridging EXT_RSTB to GND. No need to remove the flash from the board. Thanks @Leo-PL for the xxd commands.

If you compile Tasmota with scripting enabled and MAXSVARS set to at least 7, you can parse the serial string and publish it directly to MQTT. If previous testing, temperature and humidity needs to be offset (Temp-12, hum+24). I'm not sure if it's possible to convert a string to int in Tasmota directly, so this would need to be done by the receiving system.

>D 35
is=""
tmp=""
a=""
b=""
temp=""
hum=""
dust=""

>BS
=>SerialConfig 8N1
=>Baudrate 115200
=>SerialDelimiter 255
=>SerialSend4 "device_request_all_data\n"

>E
is=SerialReceived

tmp=sb(is 0 4)
if tmp=="5950"
then
  if sl(is)==14
  then
    a=sl(is 4 2)
    switch a
      ; short press "5950F3909090F0"
      case "F3"
        ->wakeup
      ; long press  "5950F4000000F0"
      case "F4"
        ->restart
    ends
  endif

  if sl(is)==30
  then
    ; data packet
    a=sb(is 8 4)
    b=sb(is 12 4)
    temp=sb(is 16 2)
    hum=sb(is 20 2)
    dust=sb(is 24 4)

    ; publish data
    =>Publish tele/%topic%/SENSOR {"a": %a%, "b": %b%, "temp": %temp%, "hum":%hum%, "dust":%dust }
  endif
endif

Outputs: {"a": 2322, "b": 2307, "temp": 31, "hum":66, "dust":0410}

Leo-PL commented 3 years ago

@jmw6773 thanks a lot for the script, I'll try it out for sure.

zerog2k commented 3 years ago

+1 thanks for the script - I was planning on looking into tasmota scripting, but you managed to solve it, yay! a few random notes:

  1. I think tasmota scripting has some bug, in that is does not seem to be interpolating the value of %topic%: it's resulting in tasmota_%02X rather than tasmota_ABCDEF. I'm researching more, and will likely open an issue if I cant fix.
  2. I'm starting to believe the a and b values may have some relationship to voltage values corresponding to R_s/R_0. Seems to me that a may be some kind of maximum voltage reading (maybe for baseline/calibration?), and b may be current voltage reading? Just guesses. This has been informative: https://jayconsystems.com/blog/understanding-a-gas-sensor
  3. The temperature and humidity values look correct (close enough) as they are for me. I placed the unit near my accurite base station, and it read 71F/37%RH, while the JQ-200 output 22C/37%RH - so pretty much the same. I'm not sure about any offset required. Wonder what other folks experience is on this.
zerog2k commented 3 years ago

My initial suspicions are that this TVOC MEMS sensor may be a GM-502B https://www.winsen-sensor.com/d/files/PDF/MEMS%20Gas%20Sensor/mems--voc--gm-502b--manual%EF%BC%88ver1_1%EF%BC%892017_5_10.pdf The way the sensor is wired in w/ MCU, it may be: Vcc -- Rl -- Vs -- Rs -- GND where: Vcc = 3.3v, Rl = 47kohms, Vs is sensor output (a or b values in mV), and Rs is the sensor's equivalent resistance Given this, I think the correct relationship is:

Vs = Vc ( Rs / [Rs+Rl] )

So I think? that yields:

Rs  = (Rl*Vc) / (Vc-Vs)

and a is Vs of R0, and b is Vs of Rs (in mV) if this makes sense? Someone please check my work ;)

fabbarix commented 3 years ago

Would anyone be able to share the dumped firmware for analysis? I think there could be something to be learned from it - like getting to do an OTA update to Tasmota.

jmw6773 commented 3 years ago

@zerog2k Thanks for the pointers.

  1. I built from current dev branch and this does seem to be an issue. It looks like scripting doesn't expand the %02X into the MAC address. I you use a static topic, like jq300, it publishes to the correct topic (tele/jq300/SENSOR)
  2. I'll try to look through the datasheets you provided and see if I have anything to add. I haven't dealt with gas sensors before, so it's new to me.
  3. I'm either seeing an offset in my sensor, it needs time to calibrate, or is just a poor sensor. I'm currently showing about 8 degrees above other sensors in my room.
fabbarix commented 3 years ago

There is some information on a suspiciously similar looking board that matches this: https://www.alibaba.com/product-detail/Integrated-Air-quality-sensor-module-for_1600137315460.html

fabbarix commented 3 years ago

Some more information about the protocol: https://pdf.directindustry.com/pdf/jinan-rainbow-technology-co-ltd/indoor-air-quality-sensor-module/224565-935992.html

zerog2k commented 3 years ago

Thanks @fabbarix I suspect that you are right that Jianan Rainbow Tech is probably behind the hardware development of the JQ-200/300, but while similar, the protocol seems a bit different from what you posted vs what is observed. However, looking at other rainbowtech stuff, seems like the VOC sensor may be S1013V and here is a good "datasheet" for it: http://www.rainbowtechnology.cn/productinfo/1487.html

I'm pretty sure that the values of a & b are the voltage output (in mV) from the MEMS sensor. I observed this myself while measuring the voltage divider network output (Vs) from the sensor, and verified it's the b value. I'm not sure if there is a way to have the mcu calculate this directly - perhaps there is some other data output package which can be obtained. However, I think you can calculate the Rs/R0 relationship from Vs, and seems like you can then derive the ppm concentration of various gases by log-log regression? from their charts. (What the jayconsystems link above discusses.) Edit: seems like it may also need to be corrected for temperature & humidity as well. Edit2: the responses here also useful for discussion: https://electronics.stackexchange.com/questions/388548/how-to-calculate-gas-sensor-ppm-from-analog-readings - TLDR; it's not so simple, and not so accurate ;)

fabbarix commented 3 years ago

To open up the casing of this units: there are two screws on the bottom, where the USB port and reset button are. The screws are hidden behind a plastic mask that can be peeled off with a plastic pryer.

There are also three plastic clips, two on the sides and one on the top. After removing the screws you can gently pry the unit open using leverage between the stand and the back cover.

16115169147055355264857324415325

PXL_20210124_193815124

Leo-PL commented 3 years ago

Would anyone be able to share the dumped firmware for analysis? I think there could be something to be learned from it - like getting to do an OTA update to Tasmota.

I wonder how to do it without breaking Github rules or the law. In any case, I backed up mine for this very purpose.

fabbarix commented 3 years ago

Can you share the strings and binwalk results on the firmware dump? It's also a good way to figure out if there is any GPL code in it.

Leo-PL commented 3 years ago

Can you share the strings and binwalk results on the firmware dump? It's also a good way to figure out if there is any GPL code in it.

Here you are, results of strings and binwalk:

jq-300.zip

fabbarix commented 3 years ago

Wait a minute.... There is a private RSA key in the firmware? Rarely a good sign in security! :/

Update: jumped the gun on this one! 🤦 That seems to be a false positive coming from the string template used to load the certificate, at least by looking at the string dump. Got my clip today to get the firmware out.

Leo-PL commented 3 years ago

Yeah, laughed hard after seeing this ;-)

Leo-PL commented 3 years ago

It might be worthwhile if we hit up on private, and compare full binary dumps, too.

brainstorm commented 3 years ago

@fabbarix @Leo-PL Count me in as well for that binary please, I've been following this with attention and I do have a couple of those devices coming in my mail soon enough ;)

fabbarix commented 3 years ago

@Leo-PL Tried to dump my firmware, but it's reading junk. When you pull down PIN 13 of U5 do you keep it at ground? Are you using the 1.8v adapter or plain CH341A?

zerog2k commented 3 years ago

@Leo-PL Tried to dump my firmware, but it's reading junk. When you pull down PIN 13 of U5 do you keep it at ground? Are you using the 1.8v adapter or plain CH341A?

You can use the ch341a with 8-pin soic chip clip, and keep pin 13 of U5 at ground (which should hold ESP in reset, and not interfere with the flash operations) I was able to dump just fine. Beware, the dump will contain some settings which are unique to your config such as SSID/Passwords, and maybe other stuff, so beware during sharing)

Leo-PL commented 3 years ago

@Leo-PL Tried to dump my firmware, but it's reading junk. When you pull down PIN 13 of U5 do you keep it at ground? Are you using the 1.8v adapter or plain CH341A?

I did a chip-off with ZIF socket and plain CH341A, so I didn't have to bother with holding EXT_RSTB low. But even with trying to pull it low, flashromm wouldn't detect the flash on my board - hence the chipoff.

jmw6773 commented 3 years ago

@fabbarix I was able to detect the flash and get a dump using CH341A and software in Windows. I cut a female jumper wire in half, soldering the cut in to the pin on U5 and the female connector into the GND of the dust sensor connector.

Make sure you power the board using 3.3v and not the USB connector. This should prevent the 2nd IC from booting and trying to start the ESP.

Leo-PL commented 3 years ago

Powering the device from USB connector would indeed explain my experience.

Stoatwblr commented 3 years ago

Thanks @Leo-PL On a JQ-200 (no dust sensor), was able to flash Tasmota 9.2.0 with flash chip in-circuit with an 8 pin clamp and pulling pin 13 (esp nrst) low on the U5 namless mcu

I've just "kind of" duplicated this feat using a ch341a_spi programmer to read the chip https://www.aliexpress.com/item/4001045543107.html?spm=a2g0s.12269583.0.0.43f577c3QuLfnb

SSID and pass are stored in cleartext in the generated image (twice) at 0x0007D010, along with a bunch of other bits and pieces

0x0007D000: FCE4FFFF FFFFFFFF 0100FFFF 0A000000 ................

SSID here: 0x0007D010: xxxxxxxx xxxxxxxx xxxxxxxx 00000000 xxxxxxxxxxxx..... 0x0007D020: 00000000 00000000 00000000 00000000 ................

Pass here: 0x0007D030: 03050300 03000057 xxxxxxxx xxxxxxxx .......xxxxxxxxx 0x0007D040: xxxxxxxx xxxxxxxx xxxxxxxxx xxxxxxxx xxxxxxxxxxxxxxxx 0x0007D050: xxxxxxxx 00000000 00000000 00000000 xxxx............ 0x0007D060: 00000000 00000000 00000000 00000000 ................

What's this? 0x0007D070: 00000000 00000000 78D7A455 EADCAEB0 ........x..U.... 0x0007D080: A9490ABC B7BB5602 DF752F96 302B5AB3 .I....V..u/.0+Z. 0x0007D090: 9C5F02E0 4720DF8B FFFFFFFF FFFFFFFF ._..G .......... 0x0007D0A0: FFFFFFFF FFFFFFFF FF008C53 C3E8AA03 ...........S....
0x0007D0B0: 0A000000 4553505F 38453841 39420000 ....ESP_8E8A9B.. 0x0007D0C0: 00000000 00000000 00000000 00000000 ................

"ESP_8E8A9B" is how it appeared in the local network

0x0007D0D0: 00000000 00000000 00000000 00000000 ................ 0x0007D0E0: 00000000 00000000 00000000 00000000 ................ 0x0007D0F0: 00000000 00000000 00000000 00000000 ................ 0x0007D100: 00000000 00000000 00000000 00000000 ................ 0x0007D110: 00000000 FFFFFFFF FFFFFFFF FFFFFFFF ................ 0x0007D120: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF ................ 0x0007D130: FFFFFFFF FF010000 04FFFFFF 0100FFFF ................

SSID again

0x0007D140: 0A000000 xxxxxxxxx xxxxxxxxx xxxxxxxxx ....xxxxxxxxxxxx 0x0007D150: 00000000 00000000 00000000 00000000 ................

Password again

0x0007D160: 00000000 xxxxxxxx xxxxxxxx xxxxxxxx ....xxxxxxxxxxxx 0x0007D170: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxxxxxxxxx 0x0007D180: 00000000 00000000 00000000 00000000 ................ 0x0007D190: 00000000 00000000 00000000 00000000 ................ 0x0007D1A0: 00000000 FFFFFFFF FFFFFFFF FFFFFFFF ................

It's 0xff from here down to

0x0007E000: FCE4FFFF FFFFFFFF 0100FFFF 03000000 ................

flashing blue mode? Key = aaa (and remnants of SSID preivously set here)

0x0007E010: 61616100 xxxxxxxx xxxxxxxx 00000000 aaa.xxxxxxxx..... 0x0007E020: 00000000 00000000 00000000 00000000 ................

that wildly insecure password again (and remnants of previously set password)

0x0007E030: 03050300 03000131 32333435 36373800 .......12345678. 0x0007E040: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxxxxxxxxxx 0x0007E050: xxxxxxxx 00000000 00000000 00000000 xxxx............ 0x0007E060: 00000000 00000000 00000000 00000000 ................ 0x0007E070: 00000000 00000000 78D7A455 EADCAEB0 ........x..U.... 0x0007E080: A9490ABC B7BB5602 DF752F96 302B5AB3 .I....V..u/.0+Z. 0x0007E090: 9C5F02E0 4720DF8B FFFFFFFF FFFFFFFF ._..G .......... 0x0007E0A0: FFFFFFFF FFFFFFFF FF008C53 C3E8AA03 ...........S.... 0x0007E0B0: 0A000000 4553505F 38453841 39420000 ....ESP_8E8A9B.. 0x0007E0C0: 00000000 00000000 00000000 00000000 ................ 0x0007E0D0: 00000000 00000000 00000000 00000000 ................ 0x0007E0E0: 00000000 00000000 00000000 00000000 ................ 0x0007E0F0: 00000000 00000000 00000000 00000000 ................ 0x0007E100: 00000000 00000000 00000000 00000000 ................ 0x0007E110: 00000000 FFFFFFFF FFFFFFFF FFFFFFFF ................ 0x0007E120: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF ................ 0x0007E130: FFFFFFFF FF010000 04FFFFFF 0100FFFF ................

and again

0x0007E140: 03000000 61616100 xxxxxxxx xxxxxxxxx ....aaa.xxxxxxxx 0x0007E150: 00000000 00000000 00000000 00000000 ................ 0x0007E160: 00000000 31323334 35363738 00xxxxxx ....12345678.xxx 0x0007E170: xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxxxxxxxxx 0x0007E180: 00000000 00000000 00000000 00000000 ................ 0x0007E190: 00000000 00000000 00000000 00000000 ................

If someone would like to analyse the image and see if this can be kludged for OTA upgrade, please let me know (it's only 256kB gzipped)

EDIT: There's a LOT of plaintext in this thing, including what appears to be a complete set of debuigging symbols, possibly built in -g mode

zerog2k commented 3 years ago

Not sure if there is a direct way to force local ota update, but I hinted at it before. I'm guessing there is some command messages coming over mqtt which could force update/reprovision/ota, etc. I don't recall any local api ports open from nmap scan on which you could try to poke on to force some local ota update.

Best of luck for OTA hunting!

Stoatwblr commented 3 years ago

Not sure if there is a direct way to force local ota update

Judging from the plaintext in order to attempt to thwart being put into a sandbox it looks up whatismyip.com and wikipedia before going to http://173.194.45.65 and http://www.youpinyuntai.com:32413/link/fastLink

Stoatwblr commented 3 years ago

$ binwalk /tmp/jq300.img

DECIMAL HEXADECIMAL DESCRIPTION

248212 0x3C994 SHA256 hash constants, little endian 349456 0x55510 CRC32 polynomial table, little endian 355452 0x56C7C PEM RSA private key 355552 0x56CE0 PEM certificate

Stoatwblr commented 3 years ago

$ esptool image_info /tmp/jq300.img esptool.py v2.8 Image version: 1 Entry point: 40100294 3 segments

Segment 1: len 0x00574 load 0x40100000 file_offs 0x00000008 [IRAM] Segment 2: len 0x00308 load 0x3ffe8000 file_offs 0x00000584 [DRAM] Segment 3: len 0x0021c load 0x3ffe8308 file_offs 0x00000894 [DRAM] Checksum: c0 (valid)

Leo-PL commented 3 years ago

@Stoatwblr it'd be great if you could get in touch with @fabbarix with the binary, so we can all compare them and look for differences in dumps.

Hakon commented 3 years ago

I have been following this thread for a while. I have 2 identical units and have ordered the programmer @Stoatwblr linked to (thanks!). I am a bit newcomer to reverse engineering, but I would love to give it a try. Would you mind sending me a dump and I'll try my best?

Stoatwblr commented 3 years ago

send me a private message and I'll fire it over. As the image contains my SSID and Wifi password I'm not comfortable putting it in public

Stoatwblr commented 3 years ago

flashrom dropped tasmota-sensors on it happily, but that's not much use in terms of decoding the sensors

Hakon commented 3 years ago

I found no direct message functionality on github, you can send me at hakon@lerring.no

Hakon commented 3 years ago

I managed to dump my firmware if someone is interested

JaneX8 commented 3 years ago

@Hakon yes please. Could you publicly share?

brainstorm commented 3 years ago

I've just tried to load it in Ghidra with this extension, but there seems to be an assumption with the loader https://github.com/hank/ghidra-esp8266/issues/3 that all ESP8266 firmwares must have:

    public final static byte ESP_MAGIC_BASE = (byte) 0xe9;

But that particular byte is nowhere to be found in the image I got from @fabbarix (thx, btw!!)... @Hakon, any progress with that? Has anybody built a signatures database (.FID) for ESP8266 (IDF) projects? It'll greatly inform the analysis.

Hakon commented 3 years ago

@ElleshaHackett Mine also contains password, but I can email it.

Juan-ma commented 3 years ago

Hi everybody. I'm interested in this challenge. I have tried to read the flash ROM with the PirateBus and flashrom with no success. I have set the U5's 13 pin to ground as suggested. This is the command I have used:

flashrom -p buspirate_spi:dev=/dev/ttyUSB1,spispeed=1M -r ./flashROM.bin -n -V -c W25Q32.V

But always get:

Probing for Winbond W25Q32.V, 4096 kB: RDID byte 0 parity violation. probe_spi_rdid_generic: id1 0x00, id2 0x00

Is it possible to read the ROM with the PirateBus or I need the CH341A programmer? I have other tools like j-link, PickKit, etc. I want to have a look with Ghidra (no experience here). I would appreciate if any could send me the bin file. Thanks!

zerog2k commented 3 years ago

Depending upon the pcb rev, you may not be successful in dumping in circuit. On one of mine, I had to desolder it to get it dumped.

Juan-ma commented 3 years ago

I have desoldered it but I can't dump it either. Have you used flashrom? Have you used the option -c W25Q32.V? In my pcb the chip is a 25Q32JVSIQ but there is not this model in flashrom options. Most of the time I obtain the RDID byte 0 parity violation error but other times I have obtained this result:

Probing for Winbond W25Q32.V, 4096 kB: probe_spi_rdid_generic: id1 0xef, id2 0x4016 Found Winbond flash chip "W25Q32.V" (4096 kB, SPI) on buspirate_spi. Chip status register is 0x00. This chip may contain one-time programmable memory. flashrom cannot read and may never be able to write it, hence it may not be able to completely clone the contents of this chip (see man page for details). Protocol error while sending SPI write/read! RDSR failed! Reading flash... Protocol error while sending SPI write/read! Read operation failed! FAILED.

Maybe my test clip is not very reliable...

Juan-ma commented 3 years ago

I've just bought a new clip and an CH341A programmer and now I have a dumped image of the ROM with the command:

flashrom -p ch341a_spi -r ./flashROM.bin -V

I'm now trying to dig into the image with ghidra 10.0.2 (my first time with it) but I don't know how to install the extension mentioned by @brainstorm. I have tried these steps:

git clone the project into the Processors folder move into GhidraESP8266_2 execute gradle -PGHIDRA_INSTALL_DIR=/path_to.../ghidra_10.0.2_PUBLIC/

Also I don't know how to use the extension to load the image. Can somebody help me?

Thanks!

Juan-ma commented 3 years ago

Thanks to the author of the GhidraESP8266_2 extension, I have managed to compile and install it. You can read the steps in this link.

git clone the project into a new folder move into GhidraESP8266_2 execute gradle -PGHIDRA_INSTALL_DIR=/path_to.../ghidra_10.0.2_PUBLIC/ copy the new created GhidraESP8266_2/dist/ghidra_10.0.2_PUBLIC_20210909_GhidraESP8266_2.zip file into ghidra_10.0.2_PUBLIC/Extensions/Ghidra Install the extension with the Ghidra 'Install Extensions' manager. Restart Ghidra

Edited: You need to install ghidra-xtensa extension before.