NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
50.64k stars 5.79k forks source link

Why ghidra 9.1.1 change the loading path of PDB file, when comparing ghidra 9.0.4? #1534

Closed bahuwang closed 4 years ago

bahuwang commented 4 years ago

When I decompile the java.exe(jdk 13) with ghidra 9.0.4 and ghidra 9.1.1, it's showing very strangely different results.

  1. ghidra 9.1.1 showes WARNING:PDB signature does not match, but ghidra
    9.0.4 is fine. I am pretty sure that the PDB signature match.
  2. I do not find the main function in ghidra 9.1.1, and comparing the same position with main function in ghidra 9.0.4 it is the Java_java_security_AccessController_getProtectionDomain function.
  3. The Symbol Tree > Functions show very difference.
astrelsky commented 4 years ago

What java distribution is the java.exe from? I'd like to reproduce this.

bahuwang commented 4 years ago

Thanks. https://github.com/bahuwang/debugreport. The two screenshots show some difference and there has java.exe with java.pdb.

ghizard commented 4 years ago

Your java.exe indicates that the PDB should have GUID=c19971c4-3cd4-4b80-a78a-784723db1984 and AGE=1 Your java.pdb has GUID=FB36EAAC-86E8-4ABF-90B2-E84C697C6A3E and AGE=1. In order for symbols to be laid down on your program correctly, these need to match.

Since the PDB does not match, it is almost a certainty that symbols will not line up with the addresses in the non-matched java.exe.

It is possible that you have the correct PDB somewhere else on your system, but it will likely try to use the one you have in the same folder as the java.exe file. You can specify a symbol folder to search in the PDB Analyzer options. Maybe that folder is specified in your Ghidra 9.0.4, but you have a different folder specified in 9.1.1.

ghizard commented 4 years ago

I went to openjdk download site: https://github.com/ojdkbuild/ojdkbuild/releases.

There are two 13.0.2.8-1 releases there, but no 13.0.2.8 at this point. java-13-openjdk-debug-13.0.2.8-1 has java.exe and java.pdb.

java-13-openjdk-13.0.2.8-1 has a debug package (with java.pdb) that is separate from the main download that has the java.exe.

For each of these packages, the GUID of java.pdb and that specified by java.exe do not match. I wanted to assure myself that we did not introduce a bug in Ghidra, so I checked the GUIDs as specified by Ghidra 9.0.4, and they agree with Ghidra 9.1.1, and indicate that the PDB and executable do not match. I'd also hate to believe that openjdk was not providing the correct PDB with their build, so I also downloaded this package as well: java-11-openjdk-debug-11.0.6.10-1. It also shows has a java.pdb whose GUID does not match what is specified in java.exe.

I cannot, at this time, explain what is going on.

bahuwang commented 4 years ago

Thank you. At the beginning, I do not think about the difference of GUID and suppose they are the same, beacuse I build them. The reason java.pdb do not match java.exe is that there has a some filename java.dll. The java.dll compile before the java.exe, and the GUID of java.dll match the java.dll. It is not a bug for Ghidra 9.1.1, but I think Ghidra 9.0.4 may be a better fault tolerance or cleverer. Even if the GUID is not match, Ghidra 9.0.4 can load the PDB that map the exe file.

Now I do not know which is better, tightened inspection of Ghidra 9.1.1 or easy use of Ghidra 9.0.4.

astrelsky commented 4 years ago

Thank you. At the beginning, I do not think about the difference of GUID and suppose they are the same, beacuse I build them. The reason java.pdb do not match java.exe is that there has a some filename java.dll. The java.dll compile before the java.exe, and the GUID of java.dll match the java.dll. It is not a bug for Ghidra 9.1.1, but I think Ghidra 9.0.4 may be a better fault tolerance or cleverer. Even if the GUID is not match, Ghidra 9.0.4 can load the PDB that map the exe file.

Now I do not know which is better, tightened inspection of Ghidra 9.1.1 or easy use of Ghidra 9.0.4.

You can manually load the pdb file. To do so, in the code browser go to File->Load PDB... it should load it even if the signature doesn't match.

ghizard commented 4 years ago

Certainly, by inspection, I can see that your java.pdb matches the java.dll and not the java.exe. GUID=FB36EAAC-86E8-4ABF-90B2-E84C697C6A3E AGE=1

bahuwang commented 4 years ago

Now I think Ghidra 9.1.1 has a wrong loading path comparing Ghidra 9.0.4. For example when I analysis java.exe, its Program Information show the PDB File. But after my test, it first loads the same path of java.pdb with the java.exe, not the path of PDB File. If there not has the file java.pdb at the same path, when analysising, it shows: Unable to locate PDB file"e:\VSrepos\ojdkbuild\build\zip_debug\openjdk\support\native\java.base\java_objs\java.pdb" with matching GUID. If there has the file java.pdb at the same path not matching the GUID, when analysising, it shows: WARNING: PDB signature does not match. It can test through https://github.com/bahuwang/debugreport.

ghizard commented 4 years ago

One thing that changed in Ghidra 9.1 was the addition of the PDB analysis option to “not” search the PDB path that is specified in the PE header. See Issue #277. The “default” of this option is different than how 9.0.4 worked, which used to allow Ghidra to reach out to a location that the user might not trust without the user having the ability to prevent it—it could be on an untrusted system. The option now prevents this, but allows the user to allow it anyways. This option was added as a quick solution providing safety, but could have been implemented in a more sophisticated fashion to only prevent UNC paths, but we would be presuming that all non-UNC paths are safe.

Since you built the target program and it’s PDB, then you would presumably trust them and the path locations in which they exist... thus you could change the option to allow the path to be searched.

To see the location that would be included in the search, you can, from the Project Manager, right click on java.exe and select About... alternatively, you can do Help->About... in the Program Listing. With this view, you can locate where the PE header has indicated the PDB location.

There is one other thing I can think of that could be happening... the current mechanism for finding and verifying a PDB locates a putative match based on file names and paths... it only grabs the first possible one of these... and then it tries to validate it based on GUID and age. If those do not match, no other PDBs that could have been found in that combination of file names and paths are checked. (I have a newer mechanism that keeps and checks a list of these, instead of just one, but that code is not yet incorporated, and might get replaced with something even better before incorporation.). Note, too, that there is another PDB Analyzer option that could help Ghidra find the file. It is the one that allows you to specify the symbols path. I don’t have it up in front of me at the moment to give you the exact name, but it is there.

ghizard commented 4 years ago

I cannot recall if the path that is preferred first is the one that contains the executable. If that is the case, then another solution would be for you to temporarily move or rename the java.pdb file that is in the folder with the java.exe (but actually belongs to java.dll).

bahuwang commented 4 years ago

Image 072