7

This is the part of the picoCTF 2019 problem "Investigative Reversing 0". I've encountered the following code when using Ghidra:

  if (lVar1 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }

Although I've completed the challenge using this as a guide: https://github.com/Dvd848/CTFs/blob/master/2019_picoCTF/Investigative_Reversing_0.md

I still don't understand this part of the code and what it does.After a few more detailed search I found two datatype assigned to the code:

long in_FS_OFFSET;
long lVar1;

I did research combining the code with ‘in_FS_OFFSET’ and ‘__stack_chk_fail()’ and most of them turned up as solution writeups on various CTF problems.Only a minority of them are something else.Such as this: https://hackaday.io/project/164346-andxor-dc27-badge/log/164366-reverse-engineering-with-ghidra-simtaco-floppy-challenge

The site have very similar de-compiled results, so I'm thinking this part of the code had something to do in protecting the program from stack-overflow.I looked at the source code of the program in the bottom of the site and searched all the c library included, but I found no useful hints. I returned to Ghidra and found this undefined function:

void UndefinedFunction_00101036(void)

{
                    /* WARNING: Treating indirect jump as call */
  (*(code *)(undefined *)0x0)();
  return;
}

Does this undefined function have anything to do with my question? If so, what might be the original code be? Thanks in advance for any answers.

Edit: disassembly part of the code

00101380  64 48 33        XOR        sVar2,qword ptr FS:[0x28]
          04 25 28 
          00 00 00
00101389  74 05           JZ         LAB_00101390
0010138b  e8 d0 fc        CALL       __stack_chk_fail       undefined __stack_chk_fail()
          ff ff
                             -- Flow Override: CALL_RETURN (CALL_TERMINATOR)

and the function:

                        //
                        // .plt 
                        // SHT_PROGBITS  [0x1020 - 0x109f]
                        // ram: 00101020-0010109f
                        //
                        LAB_00101020            XREF[9]:     0010103b(j), 0010104b(j), 
                                                0010105b(j), 0010106b(j), 
                                                0010107b(j), 0010108b(j), 
                                                0010109b(j), 001020b4, 
                                                _elfSectionHeaders::00000310(*)  
        00101020 ff 35 6a        PUSH       qword ptr [PTR_00103f90]            = 00000000
                 2f 00 00
        00101026 ff 25 6c        JMP        qword ptr [PTR_00103f98]
                 2f 00 00

charlie
  • 71
  • 1
  • 3

1 Answers1

8

fs:0x28 is stack_cookie or stack_canary

_stk_check_fail() is function that aborts execution

the compiler places a cookie in the stack and after returning from a function that manipulates stack it checks and compares.

if the cookie is corrupted then instead of proceding further the execution is simply terminated

this is a hardening technique against buffer overflows especially stack smashing

go to compiler explorer

paste this code select language as c
leave the compiler version as latest
add -fstack-protector to compiler options
and look at the disassembly produced to see how stack_canary @ fs:0x28 is used

#include <stdio.h>
#include <string.h>
void foo (char *str) {
    char buff[16];
    strcpy(buff,str);
}
int main(void){
    printf("test for __stack_chk_fail\n");
    foo("small str");
    printf("success\n");
    foo("A Big String is Copied to a Small Buffer");
    printf("i wont reach here if stack_chk_fail worked ");
}

disassembly of above code

foo:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 48
        mov     QWORD PTR [rbp-40], rdi
        mov     rax, QWORD PTR fs:40
        mov     QWORD PTR [rbp-8], rax
        xor     eax, eax
        mov     rdx, QWORD PTR [rbp-40]
        lea     rax, [rbp-32]
        mov     rsi, rdx
        mov     rdi, rax
        call    strcpy
        nop
        mov     rax, QWORD PTR [rbp-8]
        xor     rax, QWORD PTR fs:40   <<<<(40=0x28)
        je      .L2
        call    __stack_chk_fail
.L2:
        leave
        ret

a screenshot showing what is said above to address the comment

enter image description here

blabb
  • 16,376
  • 1
  • 15
  • 30