Finding main from __libc_start_main

edited October 16 in Off-topic

I'm working on reversing a stripped binary and currently trying to find the location of main. I dropped into the entry point and printed the first 15 instructions from the $rip and found this:

=> 0x4006a0:    xor    ebp,ebp
   0x4006a2:    mov    r9,rdx
   0x4006a5:    pop    rsi
   0x4006a6:    mov    rdx,rsp
   0x4006a9:    and    rsp,0xfffffffffffffff0
   0x4006ad:    push   rax
   0x4006ae:    push   rsp
   0x4006af:    mov    r8,0x400a50
   0x4006b6:    mov    rcx,0x4009e0
   0x4006bd:    mov    rdi,0x40085d
   0x4006c4:    call   0x400610 <[email protected]>
   0x4006c9:    hlt    
   0x4006ca:    nop    WORD PTR [rax+rax*1+0x0]
   0x4006d0:    mov    eax,0x60107f
   0x4006d5:    push   rbp

Great, yay we see the call to libc_main_start. Reading this article here: https://medium.com/@tr0id/working-with-stripped-binaries-in-gdb-cacacd7d5a33 it seems so suggest the address for main is always specified in the instruction directly above the function call.

Why is that? Should it not be within the function call, and if it is then where is it? Stepping into the call shows:

→   0x4006c4                  call   0x400610 <[email protected]>                                                      
   ↳    0x400610 <[email protected]+0> jmp    QWORD PTR [rip+0x200a12]        # 0x601028 <[email protected]>    
        0x400616 <[email protected]+6> push   0x2                                                                       
        0x40061b <[email protected]+11> jmp    0x4005e0                                                                 
        0x400620 <[email protected]+0>    jmp    QWORD PTR [rip+0x200a0a]        # 0x601030 <[email protected]>                         
        0x400626 <[email protected]+6>    push   0x3                  
        0x40062b <[email protected]+11>   jmp    0x4005e0 

With no mention to the address at $rdi

LMAY75
Always happy to help, DM me if you need anything!
Link to Profile

Comments

  • As discussed, I am not sure I am the best person to answer this - hopefully bumping it will draw a bit more attention though.

    So just to check, rdi normally contains the first argument - have I remembered that correctly?

    Why would the address in rdi be in main?

    TazWake

    Happy to help people but PLEASE explain your problem in as much detail as possible!

    Also: https://www.nohello.com/

  • edited October 16

    Type your comment> @TazWake said:

    As discussed, I am not sure I am the best person to answer this - hopefully bumping it will draw a bit more attention though.

    So just to check, rdi normally contains the first argument - have I remembered that correctly?

    Why would the address in rdi be in main?

    Okay so the address for main is being stored into $rdi. Setting 0x40085d as a breakpoint and continuing drops you into main.

    Edit: ohh so rdi contains the first arg? I didnt know that but it would make sense and answer my question. Thanks!

    LMAY75
    Always happy to help, DM me if you need anything!
    Link to Profile

  • edited October 16

    @LMAY75 said:

    @TazWake said:

    As discussed, I am not sure I am the best person to answer this - hopefully bumping it will draw a bit more attention though.

    So just to check, rdi normally contains the first argument - have I remembered that correctly?

    Why would the address in rdi be in main?

    Okay so the address for main is being stored into $rdi. Setting 0x40085d as a breakpoint and continuing drops you into main.

    Edit: ohh so rdi contains the first arg? I didnt know that but it would make sense and answer my question. Thanks!

    Indeed. The calling convention (aka ABI) on x64 Linux is as follows (for "integer arguments"):

    function($rdi, $rsi, $rdx, $rcx, $r8, $r9)
    

    In cases where you need more parameters, they will be pushed to the stack.

    And __libc_start_main is defined as:

    int __libc_start_main(int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end));
    

    Hack The Box
    GREM | OSCE | GASF | eJPT

  • Type your comment> @HomeSen said:
    > @LMAY75 said:
    >
    > (Quote)
    > Indeed. The calling convention (aka ABI) on x64 Linux is as follows (for "integer arguments"):
    >
    > function($rdi, $rsi, $rdx, $rcx, $r8, $r9)
    >
    > In cases where you need more parameters, they will be pushed to the stack.
    >
    > And __libc_start_main is defined as:
    >
    > int __libc_start_main(int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end));

    Fantastic, thanks this helped a lot!

    LMAY75
    Always happy to help, DM me if you need anything!
    Link to Profile

Sign In to comment.