NO

Author Topic: How to get the size of function body?  (Read 8092 times)

Offline bitcoin

  • Member
  • *
  • Posts: 179
How to get the size of function body?
« on: January 25, 2020, 04:54:53 PM »
May be you know about it..

I try to get size of function body, to compute crc32 of this (protection of crackers / debugers). I found some macroses, like:

Code: [Select]
#define start(f) __declspec(naked) void start_##f(void) {};
#define end(f) __declspec(naked) void end_##f(void) {};
#define calc_size(f) (uint8_t*)end_##f - (uint8_t*)start_##f

Usage:
Code: [Select]
start(some_func);
int some_func(int a,int b)
{
int x = 2;
int y = 3;
int z = x+y;
y = a * 5;
x = b + 12;
z = x + y;

return z;
}
end(some_func);
....
int func_size = calc_size(some_func);
But it only works with compiler options -Os -Ob1 (min size), i have 18 bytes size of function. If I use another compiler option optimization, the result are diffences. Example - in Ida dizasembler I see that func size is X byte, buf macros tell me another value. Why? And what is the rigth way to calculate function body size?

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: How to get the size of function body?
« Reply #1 on: January 25, 2020, 06:10:29 PM »
There is no standard way to know the size in bytes of a function.
The method you used is based on the, wrong, assumption that the functions are linked in the executable in the exact same order in which they are defined in source code.
With almost all decent linkers this isn't true.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline bitcoin

  • Member
  • *
  • Posts: 179
Re: How to get the size of function body?
« Reply #2 on: January 25, 2020, 06:23:18 PM »
Quote
The method you used is based on the, wrong, assumption that the functions are linked in the executable in the exact same order in which they are defined in source code
But isn’t there some linker key , that defines this behavior (order linking functions) ?

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: How to get the size of function body?
« Reply #3 on: January 25, 2020, 09:18:32 PM »
Quote
The method you used is based on the, wrong, assumption that the functions are linked in the executable in the exact same order in which they are defined in source code
But isn’t there some linker key , that defines this behavior (order linking functions) ?
Short answer: No
Consider also that future versions of linkers and compilers may behave differently, and also what apparently works using  -Os -Ob1 switch could not work anymore.
See this.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: How to get the size of function body?
« Reply #4 on: January 26, 2020, 10:50:22 AM »
Not an universal method but it's possible to search for the RET instruction in the epilogue code of a function. 32-bit code demo :

Code: [Select]
#include <stdio.h>

int testfunc(int x,int y,int *pSize)
{
    int temp;
    int result;

    __asm{
            mov edx,OFFSET label1
            dec edx
l1:
            inc edx
           
// Search for the RET ( 0xC3 ) instruction

            cmp BYTE PTR [edx],0xC3
            jne l1

            mov temp,edx
}

    result=x;
    result+=y;

    *pSize=1+(int)temp-(int)testfunc;
   
label1:

return result;
}

int main(void)
{
    int fSize;

    testfunc(10,20,&fSize);

    printf("Size of the function testfunc = %d bytes\n",fSize);

    return 0;

}
Code it... That's all...

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: How to get the size of function body?
« Reply #5 on: January 26, 2020, 02:00:36 PM »
Not an universal method but it's possible to search for the RET instruction in the epilogue code of a function. 32-bit code demo :

Code: [Select]
#include <stdio.h>

int testfunc(int x,int y,int *pSize)
{
    int temp;
    int result;

    __asm{
            mov edx,OFFSET label1
            dec edx
l1:
            inc edx
           
// Search for the RET ( 0xC3 ) instruction

            cmp BYTE PTR [edx],0xC3
            jne l1

            mov temp,edx
}

    result=x;
    result+=y;

    *pSize=1+(int)temp-(int)testfunc;
   
label1:

return result;
}

int main(void)
{
    int fSize;

    testfunc(10,20,&fSize);

    printf("Size of the function testfunc = %d bytes\n",fSize);

    return 0;

}
Nice  :)
But 64bits compiler doesn't allows inline assembler...
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline bitcoin

  • Member
  • *
  • Posts: 179
Re: How to get the size of function body?
« Reply #6 on: January 26, 2020, 02:02:24 PM »
frankie ok thank you.. But why C compiler don't give me full control of my code, such as Masm32 ?

Vortex , this is very interesting idea. I think - I want to protect program from crackers/ debuggers (only Proof of concept, I dont sale anything). And so - can I get the offset of start of function, and test every byte to see breakpoints ? Or this is imposible? Another way - crc32 of body function and test it with original.
And you test edx with opcode C3, but some my programs have C2 08 (ret 8) and other.

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: How to get the size of function body?
« Reply #7 on: January 26, 2020, 03:49:09 PM »
frankie ok thank you.. But why C compiler don't give me full control of my code, such as Masm32 ?
For the same reason that assemblers exists.
If you need such control use assembler.  :)
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: How to get the size of function body?
« Reply #8 on: January 26, 2020, 08:04:26 PM »
Hi frankie,

True, the 64-bit version of Pelles C does not support inline assembly. I have to find another way.
Code it... That's all...

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: How to get the size of function body?
« Reply #9 on: January 26, 2020, 08:12:40 PM »
Hi bitcoin,

Quote
And so - can I get the offset of start of function, and test every byte to see breakpoints ?

Getting the address of a function is easy:

Code: [Select]
*pSize=1+(int)temp-(int)testfunc
The name of the function is testfunc and the statement (int)testfunc gives you the address.

I guess you are looking for the int 3 instructions. You need to be careful at this point as testing every byte means coding a kind of disassembler. The reason why I am searching for the ret instruction after label1 is to avoid similar complex cases.

Quote
And you test edx with opcode C3, but some my programs have C2 08 (ret 8) and other.

No problem. Just insert a label before the return command as I did in my code. Detecting the sequence C2 08 is then easy.
Code it... That's all...

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: How to get the size of function body?
« Reply #10 on: January 27, 2020, 07:56:28 PM »
Here is an attempt for the 64-bit version :

Code: [Select]
#include <stdio.h>

int FindFuncTerm();

int testfunc(int x,int y,int *EndOfFunc)
{
    int result;

    result=x;
    result+=y;

*EndOfFunc=FindFuncTerm();

return result;
}

int __cdecl main(void)
{
    int EndFunc;

    testfunc(10,20,&EndFunc);

    printf("Size of the function testfunc = %d bytes\n",EndFunc-(int)testfunc);

    return 0;

}

FindFuncTerm.asm :

Code: [Select]
.code

FindFuncTerm PROC

    mov     rax,QWORD PTR [rsp]
    dec     rax
@@:
    inc     rax
    cmp     BYTE PTR [rax],195 ; =0xC3
    jne     @b
    inc     rax
    ret

FindFuncTerm ENDP
Code it... That's all...

Grincheux

  • Guest
Re: How to get the size of function body?
« Reply #11 on: January 27, 2020, 09:05:38 PM »
0xC3 is the code for "RET". In C there is a no return case. That case, the "RET" ins the best way to measure the function size, I thought that it was possible to use the NOP, but there are too many other bytes used for alignment.