hiding python code on the board

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: hiding python code on the board

Post by dhylands » Sat Feb 04, 2017 11:17 pm

flash contains a bunch of stuff:
1 - The Micropython firmware - i.e. the compiled C
2 - The internal filesystem
3 - Any frozen bytecode that you've compiled into the firmware.

Extracting the frozen bytecodes and internal filesystem is straight forward given a memory dump or debugger access, just using the standard tools, and not even having to resort to a decompiler.

If the key and the code for the key is in the image, then when I reverse engineer things, I just let that code do the work for me and capture the "unscrambled" stuff at an appropriate place.

I used to crack copy-protection schemes in my youth :)

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: hiding python code on the board

Post by v923z » Sun Feb 05, 2017 7:45 am

dhylands wrote:flash contains a bunch of stuff:
1 - The Micropython firmware - i.e. the compiled C
2 - The internal filesystem
3 - Any frozen bytecode that you've compiled into the firmware.

Extracting the frozen bytecodes and internal filesystem is straight forward given a memory dump or debugger access, just using the standard tools, and not even having to resort to a decompiler.
I think I am not too concerned about the extraction of the bytecode or similar. As stated, the critical stuff would be scrambled.
dhylands wrote: If the key and the code for the key is in the image, then when I reverse engineer things, I just let that code do the work for me and capture the "unscrambled" stuff at an appropriate place.
But exactly this is what I don't completely understand: if I have a function written in C, and compiled into the firmware that looks like this

Code: Select all

void safe_execute(char *scrambled_code, char *key) {
	ucode = unscramble(scrambled_code, key);
	exec(ucode);
	del ucode; // this is probably not necessary, given that 'ucode' is local, and will be destroyed anyway
}
then what amounts to "capturing the unscrambled stuff at an appropriate place"? Is it possible to write a piece of python code that can catch ucode before it is destroyed?
I should, perhaps, have stated in the first post that I am not aiming for absolute security. If someone is determined enough to open the device, deploy a debugger and then disassemble the code, so be it. I would mostly like to prevent others from being able to read out the code through the REPL or just by mounting the board, and copying the content to the computer. This is why I don't want to store .py or .mpy files, e.g., on the flash.
I could also reformulate the original question a bit: does what I outlined make it any harder to get to the code, or is it still just as naked and exposed as the byte code in a .mpy file itself?

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: hiding python code on the board

Post by dhylands » Sun Feb 05, 2017 8:40 am

You can read out the code through the REPL.

Once you've read out the code, and acquired the key, you run the code in a more controlled environment (one that allows a debugger) and set a breakpoint after the unscramble function.

Being a bit clever, you could call the C function from the REPL as well (by constructing an appropriate memory blob).

This is not something a typical person would know how to do, but it can be done. Compiling to bytecode would be sufficient to keep most people away.

As @pythoncoder said, this is really just "Security by Obscurity", which is essentially no security.

User avatar
marfis
Posts: 215
Joined: Fri Oct 31, 2014 10:29 am
Location: Zurich / Switzerland

Re: hiding python code on the board

Post by marfis » Sun Feb 05, 2017 8:46 pm

To make things a bit harder why not:
1) disable REPL (do not compile it into your FW)
2) disable debugger access (blowing JTAG fuse)
3) enable HW security features, such as readout protection
4) bytecompile as much as possible

If JTAG lines remain enabled it's no problems to readout and reverse engineer. As @dhylands said, an appropiate breakpoint at the right place makes your C "srcamble" function useless.

Careful usage of HW security features will make things hard for an attacker (see also http://www.st.com/content/ccc/resource/ ... 186528.pdf for an overview of the F4 security features). There are ways to overcome things like JTAG fuses though. Heck - nowadays they even etch the housing of the MCU in a DIY fashion at home and read the flash content via a microscope (as seen on the CCC days).

But ignoring those guys... Check chapter 3 of the document above ("PCROP protection overview). Python bytecode (or C code for that matter) could be placed in a sector where PCROP is enabled (I guess that's possible via the linker script file). This actually may be a nice option to be included in uPy. This way even if somebody manages to enable debugger access, he'll have a hard time introspecting the critical parts.

PS:
Why not make the *key* hidden and use a encryption algorithm like AES256 for your scrambling function? Make a bootloader that self-encrypts your staff after an update using a random key (as described on the esp32, see http://esp-idf.readthedocs.io/en/latest ... .html#keys) and place that key into a PCROP section - you are probably fine then :)

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: hiding python code on the board

Post by dhylands » Sun Feb 05, 2017 11:45 pm

Storing python bytecode in a PCROP section wouldn't be beneficial. The VM wouldn't be able to read the byte codes.

User avatar
marfis
Posts: 215
Joined: Fri Oct 31, 2014 10:29 am
Location: Zurich / Switzerland

Re: hiding python code on the board

Post by marfis » Mon Feb 06, 2017 5:56 am

yeah right. overlooked that!

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: hiding python code on the board

Post by v923z » Mon Feb 06, 2017 7:16 am

dhylands wrote:You can read out the code through the REPL.
Interesting. So, how would I do that? I mean, given the compiled C code for unscramble, what would I have to do on the python prompt to get the unscrambled code?

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: hiding python code on the board

Post by v923z » Mon Feb 06, 2017 7:22 am

marfis wrote:To make things a bit harder why not:
1) disable REPL (do not compile it into your FW)
But that is the whole point. I would like to retain the REPL. Otherwise, I could just write the whole stuff in C on a microcontroller that is tamper-proof.
marfis wrote: PS:
Why not make the *key* hidden and use a encryption algorithm like AES256 for your scrambling function? Make a bootloader that self-encrypts your staff after an update using a random key (as described on the esp32, see http://esp-idf.readthedocs.io/en/latest ... .html#keys) and place that key into a PCROP section - you are probably fine then :)
It probably doesn't matter, whether you hide the key and use a standard encryption algorithm, or make the key public, and use a custom algorithm. Either way, you have to hide at least one component.

As for ESP32, I wanted to bring that up. That has one or two encryption engines on the silicon itself, and I was wondering, whether one can make use of that.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: hiding python code on the board

Post by dhylands » Mon Feb 06, 2017 7:38 am

The stm32f415 also has an onboard cryto unit.

To make it work you also need to have some non-readable one-time programmable memory where you can store the key, so that the crypto engine can read the key but the firmware can't.

But even that doesn't help if the unencrypted data is stored in memory anyplace.

Code: Select all

x = stm.mem32[0x20000000]
reads the first word of RAM.

Code: Select all

x = stm.mem32[0x08000000]
reads the first word of flash memory.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: hiding python code on the board

Post by dhylands » Mon Feb 06, 2017 7:42 am

Basically, you need to an object in memory that looks like it has a native method. Classes like Timer, ADC, Pin and all of the other native classes have these.

You can use stm.mem8/16/32 to read or write any memory location you want.

You could also use the uctypes/ustruct to to achieve the same thing.

You can also write some inline assembler to pretty much anything you want. Here's an example of some inline assembler: https://github.com/dhylands/bioloid3/bl ... ort.py#L60

Post Reply