EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Patch fixed strings in .hex file

Started by pozz January 16, 2024
In one project I have many quasi-fixed strings that I'd like to keep in 
non volatile memory (Flash) to avoid losing precious RAM space.

static const char s1[] = "/my/very/long/string/of/01020304";
static const char s2[] = "/another/string/01020304";
...

Substring "01020304" is a serial number that changes during production 
with specific device. It has the same length in bytes (it's a simple hex 
representation of a 32-bits integer).

Of course it's too difficult and slow to rebuild the firmware during 
production passing to the compiler the real serial number. I think a 
better solution is to patch the .hex file generated by the compiler.

I'm wondering how to detect the exact positions (addresses) of serial 
numbers to fix.

The build system is gcc, so I could search for s1 in the elf file. Do 
you know of a tool that returns the address of a symbol in the elf or 
map file?

Could you suggest a better approach?

On 16/01/2024 13:19, pozz wrote:
> In one project I have many quasi-fixed strings that I'd like to keep in > non volatile memory (Flash) to avoid losing precious RAM space. > > static const char s1[] = "/my/very/long/string/of/01020304"; > static const char s2[] = "/another/string/01020304"; > ... > > Substring "01020304" is a serial number that changes during production > with specific device. It has the same length in bytes (it's a simple hex > representation of a 32-bits integer). > > Of course it's too difficult and slow to rebuild the firmware during > production passing to the compiler the real serial number. I think a > better solution is to patch the .hex file generated by the compiler. > > I'm wondering how to detect the exact positions (addresses) of serial > numbers to fix. > > The build system is gcc, so I could search for s1 in the elf file. Do > you know of a tool that returns the address of a symbol in the elf or > map file? > > Could you suggest a better approach? >
In the source code, put the serial number in as "PQRXYZ" or some other distinct string of characters. Generate bin files, not hex (or convert with objcopy). Then do a simple search for the special string to find its position and replace it with the serial number using a simple Python script or your other favourite tool (awk, sed, perl, whatever). Oh, and in the source code, don't forget to make the string "volatile".
On 16.01.2024 13:19, pozz wrote:
> In one project I have many quasi-fixed strings that I'd like to keep in > non volatile memory (Flash) to avoid losing precious RAM space. > > static const char s1[] = "/my/very/long/string/of/01020304"; > static const char s2[] = "/another/string/01020304"; > ... > > Substring "01020304" is a serial number that changes during production > with specific device. It has the same length in bytes (it's a simple hex > representation of a 32-bits integer). > > Of course it's too difficult and slow to rebuild the firmware during > production passing to the compiler the real serial number. I think a > better solution is to patch the .hex file generated by the compiler. > > I'm wondering how to detect the exact positions (addresses) of serial > numbers to fix.
Generate two binaries with different substrings and then do a binary file compare to find the position.
Il 16/01/2024 15:07, Herbert Kleebauer ha scritto:
> On 16.01.2024 13:19, pozz wrote: >> In one project I have many quasi-fixed strings that I'd like to keep in >> non volatile memory (Flash) to avoid losing precious RAM space. >> >> static const char s1[] = "/my/very/long/string/of/01020304"; >> static const char s2[] = "/another/string/01020304"; >> ... >> >> Substring "01020304" is a serial number that changes during production >> with specific device. It has the same length in bytes (it's a simple hex >> representation of a 32-bits integer). >> >> Of course it's too difficult and slow to rebuild the firmware during >> production passing to the compiler the real serial number. I think a >> better solution is to patch the .hex file generated by the compiler. >> >> I'm wondering how to detect the exact positions (addresses) of serial >> numbers to fix. > > Generate two binaries with different substrings and then do > a binary file compare to find the position.
Thank you for this?
Il 16/01/2024 13:51, David Brown ha scritto:
> On 16/01/2024 13:19, pozz wrote: >> In one project I have many quasi-fixed strings that I'd like to keep >> in non volatile memory (Flash) to avoid losing precious RAM space. >> >> static const char s1[] = "/my/very/long/string/of/01020304"; >> static const char s2[] = "/another/string/01020304"; >> ... >> >> Substring "01020304" is a serial number that changes during production >> with specific device. It has the same length in bytes (it's a simple >> hex representation of a 32-bits integer). >> >> Of course it's too difficult and slow to rebuild the firmware during >> production passing to the compiler the real serial number. I think a >> better solution is to patch the .hex file generated by the compiler. >> >> I'm wondering how to detect the exact positions (addresses) of serial >> numbers to fix. >> >> The build system is gcc, so I could search for s1 in the elf file. Do >> you know of a tool that returns the address of a symbol in the elf or >> map file? >> >> Could you suggest a better approach? >> > > In the source code, put the serial number in as "PQRXYZ" or some other > distinct string of characters.  Generate bin files, not hex (or convert > with objcopy).  Then do a simple search for the special string to find > its position and replace it with the serial number using a simple Python > script or your other favourite tool (awk, sed, perl, whatever).
I thought about this approach, but is it so difficult to have the same exact sequence of bytes somewhere else in the output?
> Oh, and in the source code, don't forget to make the string "volatile".
Why?
On 2024-01-16, pozz <pozzugno@gmail.com> wrote:

> I'm wondering how to detect the exact positions (addresses) of serial > numbers to fix.
Assuming there's a symbol associated with the address, the link map will tell you what the address is. -- Grant
On 16/01/2024 15:42, pozz wrote:
> Il 16/01/2024 13:51, David Brown ha scritto: >> On 16/01/2024 13:19, pozz wrote: >>> In one project I have many quasi-fixed strings that I'd like to keep >>> in non volatile memory (Flash) to avoid losing precious RAM space. >>> >>> static const char s1[] = "/my/very/long/string/of/01020304"; >>> static const char s2[] = "/another/string/01020304"; >>> ... >>> >>> Substring "01020304" is a serial number that changes during >>> production with specific device. It has the same length in bytes >>> (it's a simple hex representation of a 32-bits integer). >>> >>> Of course it's too difficult and slow to rebuild the firmware during >>> production passing to the compiler the real serial number. I think a >>> better solution is to patch the .hex file generated by the compiler. >>> >>> I'm wondering how to detect the exact positions (addresses) of serial >>> numbers to fix. >>> >>> The build system is gcc, so I could search for s1 in the elf file. Do >>> you know of a tool that returns the address of a symbol in the elf or >>> map file? >>> >>> Could you suggest a better approach? >>> >> >> In the source code, put the serial number in as "PQRXYZ" or some other >> distinct string of characters.&nbsp; Generate bin files, not hex (or >> convert with objcopy).&nbsp; Then do a simple search for the special string >> to find its position and replace it with the serial number using a >> simple Python script or your other favourite tool (awk, sed, perl, >> whatever). > > I thought about this approach, but is it so difficult to have the same > exact sequence of bytes somewhere else in the output?
Try it and see.
> > >> Oh, and in the source code, don't forget to make the string "volatile". > > Why? >
If you have : static const char s1[] = "PQRXYZ"; and your code later does, say : const int last_digit = s1[5] - '0'; the compiler will optimise it to : const int last_digit = '*'; i.e., it will calculate 'Z' - '0' at compile time - and if I remember by ASCII codes correctly, that matches '*'. You will be messing with the string behind the compiler's back. Make it volatile. "volatile const" might be unusual, but it is useful in exactly this kind of circumstance.
On 16/01/2024 16:24, Grant Edwards wrote:
> On 2024-01-16, pozz <pozzugno@gmail.com> wrote: > >> I'm wondering how to detect the exact positions (addresses) of serial >> numbers to fix. > > Assuming there's a symbol associated with the address, the link map > will tell you what the address is. >
Making the symbol extern linkage (remove the "static") would help with that!
On 16/01/2024 13:19, pozz wrote:
> In one project I have many quasi-fixed strings that I'd like to keep in > non volatile memory (Flash) to avoid losing precious RAM space. > > static const char s1[] = "/my/very/long/string/of/01020304"; > static const char s2[] = "/another/string/01020304"; > ... > > Substring "01020304" is a serial number that changes during production > with specific device. It has the same length in bytes (it's a simple hex > representation of a 32-bits integer). > > Of course it's too difficult and slow to rebuild the firmware during > production passing to the compiler the real serial number. I think a > better solution is to patch the .hex file generated by the compiler. > > I'm wondering how to detect the exact positions (addresses) of serial > numbers to fix. > > The build system is gcc, so I could search for s1 in the elf file. Do > you know of a tool that returns the address of a symbol in the elf or > map file? > > Could you suggest a better approach? >
Another - perhaps more reliable - method would be to put the string in its own section with __attribute__((section('serial_number'))), and then have a linker file entry to fix it at a specific known address.
Un bel giorno pozz digit&#4294967295;:

>> In the source code, put the serial number in as "PQRXYZ" or some other >> distinct string of characters.&#4294967295; Generate bin files, not hex (or convert >> with objcopy).&#4294967295; Then do a simple search for the special string to find >> its position and replace it with the serial number using a simple Python >> script or your other favourite tool (awk, sed, perl, whatever). > > I thought about this approach, but is it so difficult to have the same > exact sequence of bytes somewhere else in the output?
Extremely unlikely, especially since you use text strings and therefore you actually use 64 bits (eigth ASCII characters) to represent a 32 bit number. Besides, you don't need to use an ASCII string as the placeholder, you can use any 64 bit number. If for example your binary file is 1 MB, there is one chance over 2.2 trillion to have the same number duplicated somewhere else.
>> Oh, and in the source code, don't forget to make the string "volatile". > > Why?
To avoid that the compiler will optimize the code and "obfuscate" your string. I don't think it is very likely, but it is not impossible, especially if you use a very aggressive optimization level. -- Fletto i muscoli e sono nel vuoto.

The 2024 Embedded Online Conference