0

I am trying to understand scanf function a have 3 question regarding it. this is c file:

#include <stdio.h>
#include <stdlib.h>

int main(){
    int x;
    printf("Enter X:\n");
    scanf("%i",&x);
    printf("You entered %d...\n",x);
    return  0;
}

and here is gas:

.text
    .section    .rodata
.LC0:
    .string "Enter X:"
.LC1:
    .string "%i"
.LC2:
    .string "You entered %d...\n"
    .text
    .globl  main
    .type   main, @function
main:
    pushq   %rbp    #
    movq    %rsp, %rbp  #,
    subq    $16, %rsp   #,
# a.c:5:    printf("Enter X:\n");
    leaq    .LC0(%rip), %rdi    #,
    call    puts@PLT    #
# a.c:6:    scanf("%i",&x);
    leaq    -4(%rbp), %rax  #, tmp90
    movq    %rax, %rsi  # tmp90,
    leaq    .LC1(%rip), %rdi    #,
    movl    $0, %eax    #,
    call    __isoc99_scanf@PLT  #
# a.c:7:    printf("You entered %d...\n",x);
    movl    -4(%rbp), %eax  # x, x.0_1
    movl    %eax, %esi  # x.0_1,
    leaq    .LC2(%rip), %rdi    #,
    movl    $0, %eax    #,
    call    printf@PLT  #
# a.c:8:    return  0;
    movl    $0, %eax    #, _6
# a.c:9: }
    leave   
    ret 
    .size   main, .-main
    .ident  "GCC: (Debian 8.3.0-6) 8.3.0"
    .section    .note.GNU-stack,"",@progbits

1) The rsi should take address of x int, but it takes the address from -4(%rbp), where there is nothing, in time of execution. Because the initialization of x variable comes from the stdin as scanf waits for input to init the variable. But the what is in -4(%rbp) in the time of instruction leaq -4(%rbp), %rax? It looks like garbage, not address of x, which value should be initialized from stdin.

2)according to this Integer describing number of floating point arguments in xmm registers not passed to rax, the movl $0, %eax is to zero FP registers in al, but that is the same convention for printf. So my question is, to which functions from glibc or other libraries apply this convetion? (So I have to zero %al in printf, scanf, ....?). I assume to every, that has va_list or variable argument?

3) where in the gas source is stack canary in that should protect scanf buffer from overflow? according to this: https://reverseengineering.stackexchange.com/questions/10823/how-does-scanf-interact-with-my-code-in-assembly, this should set canary (in masm):

0x080484c5 <+6>: mov    eax,gs:0x14
   0x080484cb <+12>:    mov    DWORD PTR [ebp-0xc],eax
   0x080484ce <+15>:    xor    eax,eax

But I see nothing similar to this in my gas source, which is also output from gcc, which should set it by itself (unless there is some checking in the the scanf function itself which is not visible in my source). So where is it?

autistic456
  • 183
  • 1
  • 10
  • 1) `lea` **is** the address-of operator. It doesn't care what is in the memory location. It's like `&foo` in C. 2) yes, to all varargs functions (with the `...`) 3) this code does not trigger that protection. You can use `-fstack-protector-all` if you want to force the protector even in cases where the compiler doesn't think it's needed. – Jester Jun 11 '20 at 19:06
  • @Jester I know lea is address-of operator, but how does it wait for the `stdin` upon which relate the `scanf`? 2) `compiler doesn't think it's needed`, can you please explain how compiler "think" (you words). When does compiler decide to put canary? `scanf` is not enought? to allow user to put arbitrary long buffer from the stdin? – autistic456 Jun 11 '20 at 19:09
  • 1) it doesn't wait. `&foo` doesn't wait either. `scanf` waits. 2) To quote the [manual](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fstack-protector): _"functions that call alloca, and functions with buffers larger than or equal to 8 bytes"_ – Jester Jun 11 '20 at 21:07

0 Answers0