0

I've used Hex-rays IDA to find the bytes of code I need changed in a windows executable. I would like to write a python script that will programmatically edit those bytes.

I know the address (as given in hex-rays IDA) and I know the hexadecimal I wish to overwrite it with. How do I do this in python? I'm sure there is a simple answer, but I can't find it.

(For example: address = 0x00436411, and new hexadecimal = 0xFA)

1 Answer 1

5

You just need to open the executable as a file, for writing, in binary mode; then seek to the position you want to write; then write. So:

with open(path, 'r+b') as f:
    f.seek(position)
    f.write(new_bytes)

If you're going to be changing a lot of bytes, you may find it simpler to use mmap, which lets you treat the file as a giant list:

with open(path, 'r+b') as f:
    with contextlib.closing(mmap.mmap(f.fileno(), access=mmap.ACCESS_WRITE)) as m:
        m[first_position] = first_new_byte
        m[other_position] = other_new_byte
        # ...

If you're trying to write multi-byte values (e.g., a 32-bit int), you probably want to use the struct module.


If what you know is an address in memory at runtime, rather than a file position, you have to be able to map that to the right place in the executable file. That may not even be possible (e.g., a memory-mapped region). But if it is, you should be able to find out from the debugger where it's mapped. From inside a debugger, this is easy; from outside, you need to parse the PE header structures and do a lot of complicated logic, and there is no reason to do that.

I believe when using hex-ray IDA as a static disassembler, with all the default settings, the addresses it gives you are the addresses where the code and data segments will be mapped into memory if they aren't forced to relocate. Those are, obviously, not offsets into the file.

Sign up to request clarification or add additional context in comments.

8 Comments

wb will overwrite the whole file, won't it?
@mtrw: What made you feel the need to add a comment that said the same thing as a previous comment, and had already been fixed 2 minutes before you got here, and then add three exclamation points?
To step back for a moment: Good people with a lot of hard-earned knowledge give very freely of their time to help others. It should be abundantly clear that anybody asking questions on this site needs to thoroughly understand any code samples they get here before putting them into production use. And if that is not clear, then be careful or you just might copy-paste your way into a hard-learned lesson.
I tried the first solution, and I don't know what I'm doing wrong: f.seek(0x00436411),print(':'.join(x.encode('hex') for x in f.read(2))) gives me ce:89 wheras hex-rays is giving me 3d:c8 for the same two bytes?
@Jeff: Is hex-rays showing you the values 0x00436411 bytes into the file, or the values that will be mapped to memory address 0x00436411 at runtime? As I explained in the answer, those are not the same thing. If you don't know, just see what hex-rays says it at 0x00000000, and compare that to the first two bytes in the file. (Also, you did remember to open the file in binary mode, right?)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.