0

Here is an obfuscating technique, where a conditional jump is replaced by a jump table. Each array contains only one valid function pointer, which are called based on a crc value. I kept only a single array of function pointers

#include <stdio.h>
#include <inttypes.h>

typedef void (*crc_check_fn)(uint32_t *); 

static void crc_nib2 (uint32_t *crc) { printf("OK\n"); }

crc_check_fn b1[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, crc_nib2, 0, 0, 0 };

int main(){
        uint32_t crc = 0xFFF7FB7C;
        int index = crc & 0x0F;
        (*b1[index])(&crc);    
}

I have several questions:

  1. Can this array located in the assembly of the binary? I do not know well assembly, so checking it I was unable to tell this.

  2. I assume the answer to the previous question is yes, because the original post recommends initializng b1 like { ..., crc_nib2-8, crc_nib2, crc_ni2+8, ... };. Is this safer? Isn't it possible to tell that these are invalid pointers? Shouldn't be a better option to implement a lot of real dummy functions?

  3. Compiling with gcc -S I got

    b1: ...
    .quad 0
    .quad crc_nib2 .quad 0
    ...

Running objdump -d on the binary produces an assembly without the above lines. Why are the assemblies different? I have not stripped off symbols.

1
  • About objdump -d, elf splitited on sections, .text (with code), '.rodata' constants and so on, objdump -d disassemble only '.text' section, while your data may be in another sections. Commented Nov 6, 2015 at 11:35

2 Answers 2

2
  1. Can this array located in the assembly of the binary? I do not know well assembly, so checking it I was unable to tell this.

Yes, probably. With GCC i get it located in the assembly. One could imagine that it would be placed in BSS (zero-initialized memory) and then initialized before main to contain a single non-NULL pointer.

  1. I assume the answer to the previous question is yes, because the original post recommends initializng b1 like { ..., crc_nib2-8, crc_nib2, crc_ni2+8, ... };. Is this safer? Isn't it possible to tell that these are invalid pointers? Shouldn't be a better option to implement a lot of real dummy functions?

First of all this isn't actually very safe. All information needed to figure this out is available. If we know this has been done one could fairly easy figure out that crc_nib2 is a valid function pointer and the other are. Also one could also conclude that crc_ni2+8 is probably not a valid pointer. This is done by knowing that the start of a function often look very similar and could be recognized automatically with some level of accuracy. If there's a symbol table available it becomes even simpler.

If you're going to make the executable really tamper proof you have to make sure you can't tamper with the code checking the integrity of the executable. If the check is done in the executable itself it would probably be pointless as you (if you can modify in one place) could modify the checks to make them pass even after modifying elsewhere.

  1. Compiling with gcc -S I got

    b1: ...
    .quad 0
    .quad crc_nib2 .quad 0
    ...

Yes, me too, but what was the question?

Note that objdump -d just disassemble everything in the executable sections of the executable and skipping the rest. This is because normally the data types in the other (data) sections so there's not much interresting to "disassemble", it would only be meaningful to do a hexdump of that data.

Sign up to request clarification or add additional context in comments.

Comments

0

Can this array located in the assembly of the binary? I do not know well assembly, so checking it I was unable to tell this.

Not quite sure what "assemby of the binary" is supposed to mean. Just like any other initialized static storage duration variable, it will get allocated in the .data section of your program.

Is this safer? Isn't it possible to tell that these are invalid pointers? Shouldn't be a better option to implement a lot of real dummy functions?

Those pointers must be pointers to valid functions, or your program will crash and burn. Similarly, your program will crash and burn if you call a function pointer pointing at address 0. So no, it isn't safer, either is equally unsafe. Indeed, the only solution which won't cause a crash, is to implement dummy functions.

Overall, I really don't see why you need an array of function pointers. Just use a plain lookup table, an array of integers, and compare the CRC against those.

2 Comments

after comparing the crc against the plain lookup table wouldn't I end up with a conditional jump which is very easy to bypass?
@franz1 The "PC security" aspect is something else to consider certainly, if PC stuff is what you are working with. But you'll have to start by writing a stable program that makes sense. Your program isn't secure if it crashes all the time...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.