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

Sark Instruction incorrect parsing of phrase registers. #3

Closed
tmr232 opened this issue Jun 25, 2015 · 5 comments · Fixed by #12
Closed

Sark Instruction incorrect parsing of phrase registers. #3

tmr232 opened this issue Jun 25, 2015 · 5 comments · Fixed by #12

Comments

@tmr232
Copy link
Owner

tmr232 commented Jun 25, 2015

In IDA's SDK, all instruction fields are pre-defined and documented asside for phrase values, which can be used in whatever way the processor module writer deems fit.
While this makes a lot of sense for IDA, it does make it harder to parse. So getting the registers for an operand that looks like [eax + ebx + 4] (or any phrase with 2 registers) does not currently work.
This will probably be resolved soon, but be aware.

@tmr232 tmr232 self-assigned this Jun 25, 2015
@tmr232 tmr232 removed their assignment Aug 13, 2015
@arizvisa
Copy link

Awesome project! I have a similar project that does pretty much the same things. IDA's API is pretty painful, right?

Anyways, I had spent some time understanding how o_phrase works and so would like to share it so you don't have to dick around with it also.

So, there's 2 operand types that we care about. o_phrase, and o_displ. (gas syntax encodes them as (offset,basereg,indexreg,scale) as does intel). IDA stores these into a 2,3,3 bitfield at Operand[x].specval2. Then .specval1 appears to be used to select the phrase type. The register numbers can then be grabbed out of idaapi.ph.regnames by index. Maybe it's actually the modr/m, but I only looked for a few instructions to compare against. ;)

offset(base,index,scale) == [base+index*scale+offset]

To calculate the scale:

    res = op.specflag2 & 0xc0
    if res == 0x00:     # 00
        scale = 1
    elif res == 0x40:   # 01
        scale = 2
    elif res == 0x80:   # 10
        scale = 4
    elif res == 0xc0:   # 11
        scale = 8

For o_displ:

    if op.specflag1 == 0:
        index = None
        base = op.reg
        offset = op.addr
    elif op.specflag1 == 1:
        index = (op.specflag2&0x07) >> 0
        base = None
        offset = op.addr
    else:
        raise TypeError, "o_displ : Not implemented yet : %x"% os.specflag1

For o_phrase:

    if op.specflag1 == 0:
        index = None
        base  = op.reg
    elif op.specflag1 == 1:
        index = (op.specflag2&0x38) >> 3
        base =  (op.specflag2&0x07) >> 0
    else:
        raise TypeError, "o_phrase : Not implemented yet: %x"% os.specflag1
    offset = op.value

So then, convert index and base to a register, and use scale and offset as their immediate values.

@tmr232
Copy link
Owner Author

tmr232 commented Aug 27, 2015

Thanks a lot! This looks great!
I'll incorporate this into Sark as soon as I can!

@tmr232
Copy link
Owner Author

tmr232 commented Oct 6, 2015

Finally got to start on this... I had to change your code a bit. Can you see if my version works for you as well?

MemPhrase = namedtuple('MemPhrase', 'base index scale offset')

def parse_op_phrase(op):
    specflag1 = op.op_t.specflag1
    specflag2 = op.op_t.specflag2
    scale = 1 << ((specflag2 & 0xC0) >> 6)
    index = None
    base_ = None
    offset = 0

    if op.type.is_displ:
        if specflag1 == 0:
            index = None
            base_ = op.op_t.reg
            offset = op.op_t.addr
        elif specflag1 == 1:

            # This part os different from the provided sample. <------------------HERE
            index = (specflag2 & 0x38) >> 3
            base_ = (specflag2 & 0x07) >> 0
            offset = op.op_t.addr
        else:
            raise TypeError, "o_displ : Not implemented yet : %x" % specflag1

    elif op.type.is_phrase:
        if specflag1 == 0:
            index = None
            base_ = op.op_t.reg
        elif specflag1 == 1:
            index = (specflag2 & 0x38) >> 3
            base_ = (specflag2 & 0x07) >> 0
        else:
            raise TypeError, "o_phrase : Not implemented yet: %x" % specflag1

        offset = op.op_t.addr

    return MemPhrase(base=base_, index=index, scale=scale, offset=offset)

@tmr232
Copy link
Owner Author

tmr232 commented Oct 7, 2015

So... This code works for x86. Any pointers for x64?

@tmr232
Copy link
Owner Author

tmr232 commented Oct 8, 2015

Added support for x64 - 735ba5e

Sadly, it seems that [esp+X] is handled a bit weird in IDA. Will probably need to add a specific exception.

@tmr232 tmr232 mentioned this issue Oct 29, 2015
tmr232 added a commit that referenced this issue Oct 29, 2015
This is a rather large update to Sark. It includes the following:

1. CodeBlocks API
 1. The `CodeBlock` and `FlowChart` constructors has been improved to match the `Line` constructor. They can now accept `ea` to create on, or be called without arguments to use current `ea`. Usage should change from `get_flowchart(ea)` to `FlowChart(ea)`, and from `get_codeblock(ea)` to `CodeBlock(ea)`.
 1. `CodeBlock.color` now changes the color of the node in the graph overview, as well as the lines of the block.

1. Phrase Operands
 1. Support for phrase operands (`[eax + ebx * 10 + 20]`) was added to the instruction parsing.
 1. Basic testing has been done on x64 and x86 platforms. Other platforms should not be affected.
 1. Access is through the `base`, `index`, `scale` and `offset` (`[base + index * scale + offset]`) fields of the operand object.


1. New Plugins
 1. The `ptvsd.py` plugin from the debugging tutorial was added.
 1. A plugin to highlight `call` lines was added. It only works on IDA6.7 and higher.

1. Support for pre-6.7 versions of IDA was improved. This includes changes in the UI of some plugins, as well as some internal APIs.

1. Bug Fixes
 1. `get_native_size()` now works for 64 bit.


As this is a big update, bugs may arise. I will attempt to close new issues as soon as possible.

Closes #3 .
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

Successfully merging a pull request may close this issue.

2 participants