strcpy()/strncpy() crashes on structure member with extra space when optimization is turned on on Unix?

前端 未结 6 1525
再見小時候
再見小時候 2021-02-06 23:34

When writing a project, I ran into a strange issue.

This is the minimal code I managed to write to recreate the issue. I am intentionally storing an actual string in the

6条回答
  •  南方客
    南方客 (楼主)
    2021-02-06 23:50

    I reproduced this issue on my Ubuntu 16.10 and I found something interesting.

    When compiled with gcc -O3 -o ./test ./test.c, the program will crash if the input is longer than 8 bytes.

    After some reversing I found that GCC replaced strcpy with memcpy_chk, see this.

    // decompile from IDA
    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      int *v3; // rbx
      int v4; // edx
      unsigned int v5; // eax
      signed __int64 v6; // rbx
      char *v7; // rax
      void *v8; // r12
      const char *v9; // rax
      __int64 _0; // [rsp+0h] [rbp+0h]
      unsigned __int64 vars408; // [rsp+408h] [rbp+408h]
    
      vars408 = __readfsqword(0x28u);
      v3 = (int *)&_0;
      gets(&_0, argv, envp);
      do
      {
        v4 = *v3;
        ++v3;
        v5 = ~v4 & (v4 - 16843009) & 0x80808080;
      }
      while ( !v5 );
      if ( !((unsigned __int16)~(_WORD)v4 & (unsigned __int16)(v4 - 257) & 0x8080) )
        v5 >>= 16;
      if ( !((unsigned __int16)~(_WORD)v4 & (unsigned __int16)(v4 - 257) & 0x8080) )
        v3 = (int *)((char *)v3 + 2);
      v6 = (char *)v3 - __CFADD__((_BYTE)v5, (_BYTE)v5) - 3 - (char *)&_0; // strlen
      v7 = (char *)malloc(v6 + 9);
      v8 = v7;
      v9 = (const char *)_memcpy_chk(v7 + 8, &_0, v6 + 1, 8LL); // Forth argument is 8!!
      puts(v9);
      free(v8);
      return 0;
    }
    

    Your struct pack makes GCC believe that the element c is exactly 8 bytes long.

    And memcpy_chk will fail if the copying length is larger than the forth argument!

    So there are 2 solutions:

    • Modify your structure

    • Using compile options -D_FORTIFY_SOURCE=0(likes gcc test.c -O3 -D_FORTIFY_SOURCE=0 -o ./test) to turn off fortify functions.

      Caution: This will fully disable buffer overflow checking in the whole program!!

提交回复
热议问题