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

More flexible tracing output #66

Open
NewAccount777 opened this issue Mar 18, 2023 · 14 comments · May be fixed by #79
Open

More flexible tracing output #66

NewAccount777 opened this issue Mar 18, 2023 · 14 comments · May be fixed by #79
Labels
feature New feature or request good first issue Good for newcomers

Comments

@NewAccount777
Copy link

image
Something like that like put the module name on the side. Hope you implement this thanks.

@mrexodia
Copy link
Owner

This is already implemented?

@NewAccount777
Copy link
Author

NewAccount777 commented Mar 18, 2023

This is already implemented?

Sorry i just saw my bad,
image
take a look at this for example, it does not show useful info like where it will return (ret address) like in the system modules or the user modules (user code). if you can implement what i said above would be nice thanks.
EDIT (Or is this already added, because i cant see)
and something else also you should have like a option where it will only trace the usercode and writes the contents to file. because tracing system stuff is time consuming 😄

@mrexodia mrexodia changed the title Add weather the instructions came from the system module or the user module while tracing More flexible tracing output Mar 18, 2023
@mrexodia
Copy link
Owner

mrexodia commented Mar 18, 2023

Yeah, I guess those things make sense to add. So the complete list for this issue would be:

  • Allow only tracing specific regions
  • Print the return address if a call instruction is encountered

I only implement features I actually need myself, but you are welcome to give it a shot and make a PR if you choose. The trace function is _hook_code.

This is also (somewhat) related to #27.

@mrexodia mrexodia added feature New feature or request good first issue Good for newcomers labels Mar 18, 2023
@regionUser
Copy link
Contributor

regionUser commented Apr 4, 2023

1234.zip - .dmp file Just a simple crackme. for test
Hey, i took time to implement these features. But im having a problem, for right now im just working on to print the ret address if a call is encountered.

def _hook_code(uc: Uc, address, size, dp: Dumpulator):
    code = b""
    try:
        code = dp.read(address, min(size, 15))
        instr = next(dp.cs.disasm(code, address, 1))
    except StopIteration:
        instr = None  # Unsupported instruction
    except IndexError:
        instr = None  # Likely invalid memory
    address_name = dp.exports.get(address, "")

    module = ""
    if dp.last_module and address in dp.last_module:
        # same module again
        pass
    else:
        # new module
        dp.last_module = dp.modules.find(address)
        if dp.last_module:
            module = dp.last_module.name

    if address_name:
        address_name = " " + address_name
    elif module:
        address_name = " " + module

    line = f"{hex(address)}{address_name}|"
    if instr is not None:
        line += instr.mnemonic
        if instr.op_str:
            line += " "
            line += instr.op_str
        for reg in _get_regs(instr):
            line += f"|{reg}={hex(dp.regs.__getattr__(reg))}"
        if instr.mnemonic == "call":
            # print return address
            ret_address_size = 4 //32 bit
            ret_address = dp._uc.mem_read(dp.regs.sp, ret_address_size)
            line += f"|return_address={hex(int.from_bytes(ret_address, byteorder='little'))}"
        if instr.mnemonic in {"syscall", "sysenter"}:
            line += f"|sequence_id=[{dp.sequence_id}]"
    else:
        line += f"??? (code: {code.hex()}, size: {hex(size)})"
    line += "\n"
    dp.trace.write(line)

Error => unicorn.unicorn.UcError: Invalid memory read (UC_ERR_READ_UNMAPPED)
And also the cip is pointing to valid address since i checked it manually. also the cip is 0x9227a7. 32 bit architecture also the target test file. maybe something wrong with mem_read not so sure
sorry if the code is bad. python is not my best language.

@mrexodia
Copy link
Owner

mrexodia commented Apr 4, 2023

The return address if you’re executing a call is the next instruction… so cip + insn.size (or whatever capstone uses)

@regionUser
Copy link
Contributor

regionUser commented Apr 4, 2023

The return address if you’re executing a call is the next instruction… so cip + insn.size (or whatever capstone uses)

image

Ok problem solved thanks for the help. i should consider learning python more extensively. i also made it more cleaner, so i changed from this:
ret_address_size = 4 //32 bit
ret_address = dp._uc.mem_read(dp.regs.sp, ret_address_size)
to this:
ret_address = uc.reg_read(UC_X86_REG_RIP) + instr.size

def _hook_code(uc: Uc, address, size, dp: Dumpulator):
    code = b""
    try:
        code = dp.read(address, min(size, 15))
        instr = next(dp.cs.disasm(code, address, 1))
    except StopIteration:
        instr = None  # Unsupported instruction
    except IndexError:
        instr = None  # Likely invalid memory

    address_name = dp.exports.get(address, "")

    module = ""
    if dp.last_module and address in dp.last_module:
        # same module again
        pass
    else:
        # new module
        dp.last_module = dp.modules.find(address)
        if dp.last_module:
            module = dp.last_module.name

    if address_name:
        address_name = " " + address_name
    elif module:
        address_name = " " + module

    line = f"{hex(address)}{address_name}|"
    if instr is not None:
        line += instr.mnemonic
        if instr.op_str:
            line += " "
            line += instr.op_str
        for reg in _get_regs(instr):
            line += f"|{reg}={hex(dp.regs.__getattr__(reg))}"
        if instr.mnemonic == "call":
            # print return address
            ret_address = address + instr.size
            line += f"|return_address={hex(ret_address)}"
        if instr.mnemonic in {"syscall", "sysenter"}:
            line += f"|sequence_id=[{dp.sequence_id}]"
    else:
        line += f"??? (code: {code.hex()}, size: {hex(size)})"
    line += "\n"
    dp.trace.write(line)

@regionUser
Copy link
Contributor

Man why the format is messed up sorry for that

@mrexodia
Copy link
Owner

mrexodia commented Apr 4, 2023

You can surround your code with 3x backtick (`)

The RIP is already in the instruction and it’s an argument to the function as well, you don’t have to read it again

@regionUser
Copy link
Contributor

My bad, will fix now

@regionUser
Copy link
Contributor

regionUser commented Apr 4, 2023

Phew done, ok so you want me to create a pr request, or will you just add it from this comment the changes ?

@mrexodia
Copy link
Owner

mrexodia commented Apr 4, 2023

A pull request will be better. That will run the tests and give a clearer overview of what actually changed.

@regionUser
Copy link
Contributor

A pull request will be better. That will run the tests and give a clearer overview of what actually changed.

Is there any time frame for when my pull request will be merged? Thank you. Also, could you please provide me with the location of the tracing function, so that I can try to implement tracing for specific regions? Thank you again.

@mrexodia
Copy link
Owner

mrexodia commented Apr 8, 2023

No worries, I’ll get to it. The tracing function is the one you already modified…

@mrexodia
Copy link
Owner

mrexodia commented Apr 9, 2023

I did some initial work on the flexible-tracing branch: bbbc3ca

Currently the idea is that the user derives from the AbstractTrace class and can implement their own logic inside of the step function. The function dp.set_tracing() can be used to enable/disable tracing.

Some thinking is needed about the interface, it would be nice if the user can enable/disable tracing for sequence events (see #27) and also say 'only trace ranges X/Y/Z'.

Unicorn supports tracing specific ranges, but the annoying thing is that the callbacks will be delivered multiple times. This would need some special logic to work as a user might expect.

@mrexodia mrexodia linked a pull request May 6, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants