Ghidra: Rename or retype variables causing other variables to disappear.

Created on 27 Apr 2019  路  2Comments  路  Source: NationalSecurityAgency/ghidra

Variables disappear after renaming or retyping other variables.

Ghidra Binary Information

Project File Name:  a.out
Last Modified:  Sat Apr 27 18:09:50 EET 2019
Readonly:   false
Program Name:   a.out
Language ID:    x86:LE:64:default (2.8)
Compiler ID:    gcc
Processor:  x86
Endian: Little
Address Size:   64
Minimum Address:    00100000
Maximum Address:    _elfSectionHeaders::0000077f
# of Bytes: 7955
# of Memory Blocks: 32
# of Instructions:  248
# of Defined Data:  178
# of Functions: 31
# of Symbols:   120
# of Data Types:    46
# of Data Type Categories:  3
Analyzed:   true
Created With Ghidra Version:    9.0.2
Date Created:   Sat Apr 27 18:09:46 EET 2019
ELF File Type:  shared object
ELF Required Library [   0]:    libc.so.6
ELF Source File [   0]: crtstuff.c
ELF Source File [   1]: NeverSayTheNword.c
ELF Source File [   2]: crtstuff.c
Executable Format:  Executable and Linking Format (ELF)
Executable Location:    /home/rebellion/Desktop/ReversingBad/a.out
Executable MD5: 2edad14c432141c4388686791083e9e0
FSRL:   file:///home/rebellion/Desktop/ReversingBad/a.out?MD5=2edad14c432141c4388686791083e9e0
Firmware Path:  
Relocatable:    true

Sample Source Code
Compiled using gcc file.c

#include <stdio.h>

int main(int argc, char *argv[]){
   unsigned char str[18];
   int num[18] = {99,152,183,208,179,221,26,137,190,76,173,74,196,68,219,214,161,147};
   printf("Say My Name : ");
   scanf("%s", str);
   str[0]  = (str[8]  + 5) + (str[1]  - 4);
   str[17] = (str[1]  - 8) + (str[13] + 2);
   str[16] = (str[12] + 1) + (str[7]  - 3);
   str[5]  = (str[4]  - 7) + (str[0]  + 6);
   str[12] = (str[17] + 2) + (str[10] - 4);
   str[10] = (str[9]  - 2) + (str[3]  + 2);
   str[3]  = (str[3]  + 5) + (str[17] - 1);
   str[6]  = (str[11] - 1) + (str[16] + 8);
   str[8]  = (str[16] + 6) + (str[6]  - 3);
   str[13] = (str[18] - 3) + (str[2]  + 7);
   str[4]  = (str[2]  + 4) + (str[9]  - 5);
   str[2]  = (str[13] - 2) + (str[15] + 1);
   str[7]  = (str[10] + 8) + (str[5]  - 9);
   str[11] = (str[6]  - 6) + (str[14] + 5);
   str[14] = (str[17] + 1) + (str[11] - 3);
   str[1]  = (str[5]  - 5) + (str[8]  + 2);
   str[15] = (str[14] + 2) + (str[18] - 7);
   str[9]  = (str[7]  + 1) + (str[12] - 2);
   for(int i = 0; i < 18; i++){
     if(num[i] != str[i]){
          printf("Who are you talking to right now?\n");
          return(1);
     }
   }
   printf("You're goddamn right\n");
   return(0);
}

Screenshots

Screenshot at 2019-04-27 18-14-15

Screenshot at 2019-04-27 18-14-40

Screenshot at 2019-04-27 18-15-19

Screenshot at 2019-04-27 18-15-34

Environment

  • OS: Linux rebellion 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64 GNU/Linux

    • Java Version: 11.0.2

    • Ghidra Version: 9.0.2

Bug

Most helpful comment

The master branch addresses this problem, and the fixes will be in the 9.2 release. Both types of user annotations on local_28 were considered "forcing" on the decompiler, forcing the decompiler to treat what is really a single array location as a distinct variable. This caused the decompiler to think that the indirect array references in the final loop could not be aliases of anything on the stack after local_28 (alias blocking), and the writes to other array locations were getting eliminated as dead code.

With the new code, the renaming action no longer switches an annotation to "forcing" if it wasn't already, and the retyping action, although it is forcing, won't trigger the alias blocking for atomic data-types like "byte" and "char".

All 2 comments

Not a surprise, but this also happens on Windows, Ghidra Version: 9.0.4, Java Version: 11.0.2
It's a pretty weird and annoying bug.

The master branch addresses this problem, and the fixes will be in the 9.2 release. Both types of user annotations on local_28 were considered "forcing" on the decompiler, forcing the decompiler to treat what is really a single array location as a distinct variable. This caused the decompiler to think that the indirect array references in the final loop could not be aliases of anything on the stack after local_28 (alias blocking), and the writes to other array locations were getting eliminated as dead code.

With the new code, the renaming action no longer switches an annotation to "forcing" if it wasn't already, and the retyping action, although it is forcing, won't trigger the alias blocking for atomic data-types like "byte" and "char".

Was this page helpful?
0 / 5 - 0 ratings

Related issues

toor-de-force picture toor-de-force  路  3Comments

Kerilk picture Kerilk  路  3Comments

forkoz picture forkoz  路  3Comments

gemini00 picture gemini00  路  3Comments

loudinthecloud picture loudinthecloud  路  3Comments