3

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

3
4

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

4
  • Thanks for explaining :)
    – charlie
    Feb 22 '20 at 15:27
  • But I can't add -fstack-protecter to compiler options, they simply failed to compile
    – charlie
    Feb 22 '20 at 15:42
  • added a screenshot
    – blabb
    Feb 22 '20 at 18:23
  • I see, I set option as -fstack-protecter instead of -fstack-protector, my bad
    – charlie
    Feb 22 '20 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.