Protect and hide some of the source code

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, I am new in AVR C.
I want to protect and hide some of the source code.
In my project, i have to include the source code, but i want some important code are protected and hidden.
How to create a compiled library file so that other people can not read and modify the source code of the library.
The source code of the library will be created with the C language or high-level language.

Thank you

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

During compile you can omit the debug informations.
Then you get pure assembler code, which can be read and executed.

But still all global function and variable names are included to give the linker a chance to resolve it.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First identify your C compiler. If it's avr-gcc as found in AS6 then it's easy to build a static library for some part of the code. But as shown here many times it's easy to get this back to AVR Asm though it's true that without comments it's quite tricky to follow. (a C compiler uses the stack with a Y based frame pointer a lot and has a habit of shuffling things round between registers to meet the ABI).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And the counter-question also always raised when such question are asked: Why is it so important to protect some of the code? Is this a customer relationship, and are you afraid the customer will steal your software? If so the relation you have with that customer is questionable, and maybe you should stay away from the deal altogether?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Or, maybe the OP is a student and wants to "share" with other students without them being able to get credit for the OP's code?

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This would be a good competition, how much time is spent to hide the code in a library versus how much time it takes for someone to replicate the library's functionality with source code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As suggested, as soon as you compile code, the source is "hidden" because it is quite difficult to reconstruct source from the assembly language. Thus, a precompiled library will hide the source code.

Now, is it impossible to reconstruct a reasonable source from the compiled code? No, it is not impossible.

As suggested, above, it is all about how much work it is worth.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Let's assume a medium-sized mega, the ATmega168. 16K flash, i.e. 8K instructions. Let's further assume 1/8th of the code needs to be obfuscated. So, 1K instructions. Let's assume a 5:1 ratio instructions:C-source-lines. So, what was originally 200 lines of C code needs to be backward engineered. Perhaps 10-20 functions, of 10-20 lines each (or 50 to 100 instructions each).

Library information necessary to be able to link with the library will reveal start addresses of linkable (i.e. non-static) functions. Perhaps more - link libraries were never designed to solve the problem of IP protection. Function prologues will reveal more. Etc..

Not unfeasible. A couple of days work for a skilled programmer? (2-5 functions per day?)

Just speculation, and a lot of assumptions. But not unreasonable assumptions, IMO.

Hey Ruben! You need to come back here and tell us about what compiler/linker tool chain you are using. The procedure to create a library and link with it is different for different tool chains.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see you've been warned there is no perfect security! With that in mind, this page gives the steps required, when using avr-gcc from the command line...

http://www.nongnu.org/avr-libc/user-manual/library.html

Everyone here is an AVR 'freak' of some sort.

Myself, I am a command line, avr-gcc freak.

Other kinds of freaks here use other compilers, and / or use software packages which have 'pushbutton' library building facilities.

More information about the kind of freak you are, will elicit better responses from freaks similar to you.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are some funny ways of writing C Code that is hard to understand. Some do it on purpose for others its there personal way of writing. So it is possible to convert the code to a hardly readably form, though giving a valid C-source code. There are a few tools to do such funny things. A few thing to make is hard:
1) change variable names to something nonsense and hard to read, like l1lLO0I1 and so on.
2) Use a decent number of #define and #if, possibly with a required command-line parameter.
3) Add some funny parts the compiler can optimize away.

However it's always possible to use the compiler to get the ASM code, though with nonsense variable names.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here are a couple of unreadable code examples:
http://www0.us.ioccc.org/2012/ha...
http://www0.us.ioccc.org/2011/ak...
http://www0.us.ioccc.org/2012/en...

Taken from http://www0.us.ioccc.org/years.html

Alex

p.s. a code formatter would probably restore these to a readable form so I wouldn't consider them safe.

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ubuntu has a package called cutils and within that is a utility called cobfusc. No doubt you could also get the source for that and build it for Windows. It can do this:

clawson@ws-czc1138h0b:/windows/avr$ cat code.c
#include
void adc()                      //initialisation function
{
        ADMUX = (1 << REFS0);   //Aref=Avcc
        ADCSRA = (1 << ADEN) | (0 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);      //enabling adc and setting setting prescalar as 8
}

uint16_t read(uint8_t ch)       //adc reading fuction
{
        ch = ch & 0b00000111;   //reading appropriate channel 
        ADMUX = (1 << REFS0) | ch;
        ADCSRA |= (1 << ADSC);  //start single conversion
        while (!(ADCSRA & (1 << ADIF))) ;       //checking for converson complete
        ADCSRA |= (1 << ADIF);  //stop conversion
        return (ADCW);          //returns the 10bit value
}

void main()
{
        DDRB = 0b00000010;
        DDRD = 0b11111111;
        PORTD = 0b00000000;
        uint16_t res;
        adc();                  //initialisation
        while (1)               //infinite loop
        {
                res = read(0);  //reading channel0
                if (res < 487)  //condition1
                {
                        PORTD = (1 << PD6) | (0 << PD5);        //blinking led at PD6
                        PORTB = (0 << PB1);
                } else if (487 < res < 548) {
                        PORTD = (0 << PD6) | (0 << PD5);        //blinking led at PB1
                        PORTB = (1 << PB1);
                } else if (res > 548) {
                        PORTD = (0 << PD6) | (1 << PD5);        //blinking led at PD5
                        PORTB = (0 << PB1);
                }
        }
}
clawson@ws-czc1138h0b:/windows/avr$ cobfusc -A -o obfus.c code.c
clawson@ws-czc1138h0b:/windows/avr$ cat obfus.c 
#include
void q0()//q1 q2??q17 q18(q19 q20)//q0 q21 q22??void main()??else if(487else if(q46>548)????>??>

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yet another (slight) obfuscation method would be to distribute the source files after preprocessing.

Re Cliffs latest post above, I really wonder how that works. If I remove all the comments I end up with

#include 
void q0() 
q11); 
 q23; 
q30)));
.
.

Assuming a lot of line breaks got lost in posting, and creatively putting some back in I still end up with something beginning

#include 
void q0()//
q1 q2??

which also makes no sense. In fact, there isn't a single gull-wing in the obfuscated code.

And wherer are all those qn's defined or #defined?

What am I missing?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah my bad. I just used -A which pretty much means "some of everything please". However it uses options such as:

cobfusc -i numeric -o obfus.c code.c

which leads to:

#include
void q0()                       //q1 q2
{
        q3 = (1 << q4); //q5=q6
        q7 = (1 << q8) | (0 << q9) | (1 << q10) | (1 << q11);   //q12 q0 q13 q14 q14 
q15 q16 8
}

q17 q18(q19 q20)        //q0 q21 q22
{
        q20 = q20 & 0q23;       //q21 q24 q25 
        q3 = (1 << q4) | q20;
        q7 |= (1 << q26);       //q27 q28 q29
        while (!(q7 & (1 << q30))) ;    //q31 for q32 q33
        q7 |= (1 << q30);       //q34 q29
        return (q35);           //q36 q37 10q38 q39
}

void main()
{
        q40 = 0q41;
        q42 = 0q43;
        q44 = 0q45;
        q17 q46;
        q0();                   //q1
        while (1)               //q47 q48
        {
                q46 = q18(0);   //q21 q49
                if (q46 < 487)  //q50
                {
                        q44 = (1 << q51) | (0 << q52);  //q53 q54 q55 q51
                        q56 = (0 << q57);
                } else if (487 < q46 < 548) {
                        q44 = (0 << q51) | (0 << q52);  //q53 q54 q55 q57
                        q56 = (1 << q57);
                } else if (q46 > 548) {
                        q44 = (0 << q51) | (1 << q52);  //q53 q54 q55 q52
                        q56 = (0 << q57);
                }
        }
}

which has not taken account of the fact that ADMUX etc are predefined macros that cannot be touched. It also appears that it does not understand C++ style comments (yikes!). Like so many of these C processing utilities it also does not know about 0b prefix. So the best I can come up with is:

cobfusc -e -n -w 8 -o obfus.c codea.c

which generates:

#include
void adc
(){ADMUX
=((1*(1*1+0)+0)
<<REFS0)
;ADCSRA=
((1*(1*1+0)+0)
<<ADEN)|
(0<<
ADPS2)|((1*(1*1+0)+0)
<<ADPS1)
|((1*(1*1+0)+0)
<<ADPS0)
;}uint16_t
 read(
uint8_t 
ch){ch=
ch&0b00000111
;ADMUX=(
(1+0)<<
REFS0)|
ch;
ADCSRA|=
((0+1)<<
ADSC);
while(!(
ADCSRA&(
(1*1+0)
<<ADIF))
);ADCSRA
|=((1*(1*1+0)+0)
<<ADIF);
return(
ADCW);}
void 
main(){
DDRB=0b00000010
;DDRD=0b11111111
;PORTD=0b00000000
;uint16_t
 res;adc
();while
((1+0)){
res=read
(0);if(
res<487)
{PORTD=(
(1*1+0)
<<PD6)|(
0<<PD5);
PORTB=(0
<<PB1);}
else if(
487548)
{PORTD=(
0<<PD6)|
((1*(1*1+0)+0)
<<PD5);
PORTB=(0
<<PB1);}
}}

and that still compiles:

avr-gcc -c -mmcu=atmega16 -g -o foo.o obfus.c

However I had to hand-strip the // comments before I started - no doubt I could have scripted that) and I had to fix up the 0b XXXX afterwards to make 0bXXXX without the inserted spaces.