Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signature not applied correctly through writeOverride, but applied correctly manually #7322

Open
yodaxtah opened this issue Dec 27, 2024 · 0 comments

Comments

@yodaxtah
Copy link

yodaxtah commented Dec 27, 2024

Describe the bug

Programmatic signature overwrites don't work when calling writeOverride with a signature object. Manual signature overwrites work perfectly when inserting the string representing that object.

To Reproduce

I'm working in Ghidratron and give here my minimal example to what I tried. (The code should also work in the Python Window of version 2.7, just with the commented small changes.)

>>> program = getCurrentProgram()
>>> function_manager = program.getFunctionManager()
>>> call_site_address = toAddr(int("00266924", 16)) # address of the function call to sprintf
>>> override_function_address = toAddr(int("0010de98", 16)) # address of sprintf, the function being called
>>> override_function = function_manager.getFunctionAt(override_function_address)
>>> override_signature_string = "void __stdcall dt_b7404d73(char * str, const_char * format, const_char * , const_char * )"
>>> service_provider = state().getTool() # or state.getTool if python 2.7
>>> from ghidra.app.util.cparser.C import CParserUtils
>>> override_signature = CParserUtils.parseSignature(service_provider, program, override_signature_string)
>>> str(override_signature)
'void __stdcall dt_b7404d73(char * str, const_char * format, const_char * , const_char * )'
>>> from ghidra.program.model.pcode import HighFunctionDBUtil
>>> transaction = program.startTransaction("Apply Function Signature Override")
>>> HighFunctionDBUtil.writeOverride(override_function, call_site_address, override_signature)
>>> program.endTransaction(transaction, True)

After the write operation, the symbol prt_266924_b7404d73 becomes sprintf::override::prt_266924_1c72fef3. However, looking at the CodeBrowser, I don't see any changes.

  1. Go to the CodeBrowser.
  2. Right click the function call.
  3. Click 'Override Signature'

This will be the original unmodified string. If I however manually override the signature, it will work.

  1. Insert the content of str(override_signature).replace(" __stdcall", "") into the open dialog.
  2. Press 'Okay'.

It is unclear why the programmatic approach doesn't work and the manual does. I suspect it's a bug, as I don't see the point of a symbol being renamed, without the code browser reflecting that change.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots

Here is a screenshot of the gui, before doing either the programmatic or the manual operation.

image

Attachments

Sadly, I cannot upload the binary I'm working on.

Environment (please complete the following information):

  • OS: Windows 10 Home, 22H2, 19045.5247 (OS Build)
  • Java Version: openjdk 17.0.11 2024-04-16
  • Ghidra Version: 11.1 (2024-Jun-07 1416 EDT)
  • Ghidra Origin: official GitHub distro (but not 100% sure)

Additional context

I further searched for possible causes; removing __stdcall (because I couldn't insert it manually with that in it), and changing the signature's name (dt_b7404d73) to the function's name (sprintf). (I have not tried this in the Python Window, but the try-catch will be a problem already.)

Removing __stdcall:

>>> from ghidra.program.model.data import GenericCallingConvention
>>> override_signature.setGenericCallingConvention(GenericCallingConvention.unknown)
>>> str(override_signature)
'void  dt_b7404d73(char * str, const_char * format, const_char * , const_char * )'
>>> try:
>>>   transaction = program.startTransaction("Apply Function Signature Override")
>>>   HighFunctionDBUtil.writeOverride(override_function, call_site_address, override_signature)
>>>   print("Function signature override applied successfully.")
>>> except Exception as e:
>>>   print(f"Error applying function signature override: {str(e)}")
>>> finally:
...   program.endTransaction(transaction, True)
... 
Function signature override applied successfully.

Replacing dt_b7404d73:

>>> override_signature.getName()
'dt_b7404d73'
>>> override_signature.setName("sprintf")
>>> str(override_signature)
'void  sprintf(char * str, const_char * format, const_char * , const_char * )'
>>> try:
>>>   transaction = program.startTransaction("Apply Function Signature Override")
>>>   HighFunctionDBUtil.writeOverride(override_function, call_site_address, override_signature)
>>>   print("Function signature override applied successfully.")
>>> except Exception as e:
>>>   print(f"Error applying function signature override: {str(e)}")
>>> finally:
...   program.endTransaction(transaction, True)
... 
Function signature override applied successfully.

Neither of the above had a change in behavior.

I also wondered what would happen if I first manually changed the signature and then applied it programmatically. So I tried that. As expected, the correct (manually inserted) signature was replaced by the initial default signature upon executing the code. This makes it clear that the writeOverride takes effect, and it is immediately visible.

Also, it appears getGenericCallingConvention is not available, even though it is a documented function in the API docs. (I didn't test this issue in the Python Window.)

>>> str(override_signature.getGenericCallingConvention())
Traceback (most recent call last):
  File "C:\Users\User\AppData\Roaming\ghidra\ghidra_11.1_PUBLIC\Extensions\Ghidrathon\data\python\jepeval.py", line 74, in jepeval
    more_input_needed = _jepeval(line)
  File "C:\Users\User\AppData\Roaming\ghidra\ghidra_11.1_PUBLIC\Extensions\Ghidrathon\data\python\jepeval.py", line 49, in _jepeval
    exec(compile(line, "<string>", "single"), globals(), globals())
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
AttributeError: 'FunctionDefinitionDataType' object has no attribute 'getGenericCallingConvention'. Did you mean: 'setGenericCallingConvention'?
>>> str(override_signature.GenericCallingConvention)
Traceback (most recent call last):
  File "C:\Users\User\AppData\Roaming\ghidra\ghidra_11.1_PUBLIC\Extensions\Ghidrathon\data\python\jepeval.py", line 74, in jepeval
    more_input_needed = _jepeval(line)
  File "C:\Users\User\AppData\Roaming\ghidra\ghidra_11.1_PUBLIC\Extensions\Ghidrathon\data\python\jepeval.py", line 49, in _jepeval
    exec(compile(line, "<string>", "single"), globals(), globals())
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
AttributeError: 'FunctionDefinitionDataType' object has no attribute 'GenericCallingConvention'. Did you mean: 'setGenericCallingConvention'?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant