TransWikia.com

Correct way to understand local_ in ghidra disassembly

Reverse Engineering Asked by Mah35h on December 18, 2020

Attached is the part of a disassembled main from a x86 binary file, generated by ghidra.

                             **************************************************************
                             *                          FUNCTION                          *
                             **************************************************************
                             undefined main(undefined1 param_1)
             undefined         AL:1           <RETURN>                                XREF[1]:     0804835e(W)  
             undefined1        Stack[0x4]:1   param_1                                 XREF[1]:     08048309(*)  
             undefined4        EAX:4          str_in                                  XREF[1]:     0804835e(W)  
             undefined4        Stack[0x0]:4   local_res0                              XREF[1]:     08048310(R)  
             undefined4        Stack[-0x10]:4 local_10                                XREF[6]:     08048358(R), 
                                                                                                   08048363(W), 
                                                                                                   0804836d(R), 
                                                                                                   08048388(R), 
                                                                                                   08048393(W), 
                                                                                                   0804839d(R)  
             undefined4        Stack[-0x14]:4 local_14                                XREF[2]:     0804831a(W), 
                                                                                                   08048366(R)  
             undefined4        Stack[-0x18]:4 local_18                                XREF[2]:     08048321(W), 
                                                                                                   08048396(R)  
             undefined4        Stack[-0x2c]:4 local_2c                                XREF[3]:     08048369(W), 
                                                                                                   08048399(W), 
                                                                                                   080483ac(W)  
             undefined4        Stack[-0x30]:4 local_30                                XREF[12]:    08048328(*), 
                                                                                                   08048334(*), 
                                                                                                   08048340(*), 
                                                                                                   0804834c(*), 
                                                                                                   0804835b(*), 
                                                                                                   08048370(*), 
                                                                                                   0804837c(*), 
                                                                                                   0804838b(*), 
                                                                                                   080483a0(*), 
                                                                                                   080483b4(*), 
                                                                                                   080483c2(*), 
                                                                                                   080483d0(*)  
                             main                                            XREF[2]:     Entry Point(*), 
                                                                                          _start:08048167(*)  
        08048309 8d 4c 24 04     LEA        ECX=>param_1,[ESP + 0x4]
        0804830d 83 e4 f0        AND        ESP,0xfffffff0
        08048310 ff 71 fc        PUSH       dword ptr [ECX + local_res0]
        08048313 55              PUSH       EBP
        08048314 89 e5           MOV        EBP,ESP
        08048316 51              PUSH       ECX
        08048317 83 ec 24        SUB        ESP,0x24
        0804831a c7 45 f4        MOV        dword ptr [EBP + local_14],DAT_080a6b19          = 6Ah    j
                 19 6b 0a 08
        08048321 c7 45 f0        MOV        dword ptr [EBP + local_18],s_the_ripper_080a6b1e = "the ripper"
                 1e 6b 0a 08

Same code from gdb

   0x08048309 <+0>: lea    ecx,[esp+0x4]
   0x0804830d <+4>: and    esp,0xfffffff0
   0x08048310 <+7>: push   DWORD PTR [ecx-0x4]
   0x08048313 <+10>:    push   ebp
   0x08048314 <+11>:    mov    ebp,esp
   0x08048316 <+13>:    push   ecx
   0x08048317 <+14>:    sub    esp,0x24
=> 0x0804831a <+17>:    mov    DWORD PTR [ebp-0xc],0x80a6b19

Why is ghidra changeing [ebp-0xc] to [EBP + local_14].
Similar question I found is Ghidra interpreting stack pointers wrongly but reading the answer, I’m not getting the meaning of [EBP + local_14] Here, is ghidra just renaming -0xc to a easily readable name like local_14? I’m not getting how to make sense of this exactly.

In the function header, it is shown that Stack[-0x10]:4 local_10. I assume it means that local_10 is 4 byte variable at Stack[-0x10], where Stack is the stack pointer upon entry to function. But why is it added to ebp. What’s the meaning of that representation used by ghidra?

One Answer

Since local variables are usually placed on the stack in x86 and esp register can change during function execution, it is more convenient to save the value of esp register on function entry and access data relatively to that value. ebp register is used for this purpose. So you will often see

push ebp
mov ebp, esp

lines at the begining of functions. In the example you have provided it is the case - all local variables are accessed this way, through ebp.

Now, there are two different naming conventions for local variables:

  • first and more natural one: if [ebp - xxx] is accessed, it will be displayed as [ebp + local_xxx]. Here, local_xxx = -xxx, so for instance, local_18 = -0x18.
  • second and less intuitive one makes use of the esp value at the beginning of a function. In your example, two dwords are pushed on the stack before mov ebp, esp line. It means, that if some local variable was called local_xxx in the first convention, in the second one it will be named local_xxx+0x8, for instance local_18 in the first one will be local_20 in the second one, used by Ghidra.

Why do we add 0x8 in the second one? Because two dwords (8 bytes) were pushed onto the stack before esp value was saved into ebp and in x86 architecture stack "grows downwards", which means if you push something onto it, this value will be saved there and esp will be decreased accordingly (in this case, twice, by 4 bytes). So, in your particular example, you have the instruction

mov    DWORD PTR [ebp-0xc],0x80a6b19

which would be displayed as

mov    DWORD PTR [ebp+local_c],0x80a6b19

in the first convention and

mov    DWORD PTR [ebp+local_14],0x80a6b19

in the second one, implemented in Ghidra, since 0xc + 0x8 = 0x14.

Correct answer by bart1e on December 18, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP