# IDAPython scripting

Additionally to the plugin's graphical interface you can use python bindings.

## Command line examples

This will match the current binary against a short pattern:

>     import pygrap
>     m=pygrap.ida_quick_match("sub->xor")

Options are:

- print_matches: print found matches (default: True)
- getids: print matched instructions (default: True)
- print_pattern: print full pattern inferred from string (default: False)
- pattern_name: name of the quick pattern (default: quick_pattern)

The following line outputs a full pattern from a more complex quick pattern:

>     pygrap.quick_pattern("opcode is push->opcode is push and arg1 is esi->opcode is call and arg1 is edi->opcode is mov and arg2 is eax", pattern_name="getprocaddress_resolve")

## Script examples

### Color matching instructions

This script colors in red matching instructions for two small patterns ("sub->xor" and "ror->mov").

>     import pygrap

>     pattern1 = pygrap.quick_pattern("sub->xor", pattern_name="sub_xor")
>     pattern2 = pygrap.quick_pattern("ror->mov", pattern_name="ror_mov")
>     matches = pygrap.ida_match([pattern1, pattern2], print_matches=False)

>     for pattern_name in matches:
>         for match in matches[pattern_name]:
>             print("Coloring", pattern_name, "match at address", hex(match["1"][0].info.address))
>             for getid in match:
>                 for inst in match[getid]:
>                     addr = inst.info.address
>                     set_color(addr, CIC_ITEM, 0x7280fa)

### Rename variables where functions imported with getProcAddress are stored

This example renames functions imported with getProcAddress in binaries created with PyInstaller (for instance: 53854221c6c1fa513d6ecf83385518dbd8b0afefd9661f6ad831a5acf33c0f8e in function sub_402830). We have the following assembly pattern (disassembled by IDA) that resolves a dynamic import with getProcAddress:

- mov edi, ds:GetProcAddress
- push offset ProcName ; "Py_DontWriteBytecodeFlag"
- push esi
- call edi ; GetProcAddress
- mov dword_138D84C, eax

For reference, the following is the same assembly code disassembled by Capstone, so this is what you can match with grap:

- mov edi, dword [0x138100c]
- push 0x1384638
- push esi
- call edi
- mov dword [0x138d84c], eax

We want to rename the variable (dword_138D84C) where the address of the imported function ("Py_DontWriteBytecodeFlag") is stored.

>     import pygrap

>     pattern = """
>         digraph getprocaddress_resolve {
>         "1" [cond="opcode is 'push'", getid="push1"]
>         "2" [cond="opcode is 'push' and arg1 is 'esi'", getid="push2"]
>         "3" [cond="opcode is 'call' and arg1 is 'edi'", getid="call"]
>         "4" [cond="opcode is 'mov' and arg2 is 'eax'", getid="mov"]

>         "1" -> "2" [childnumber=1]
>         "2" -> "3" [childnumber=1]
>         "3" -> "4" [childnumber=1]
>         }
>     """

>     matches = pygrap.ida_match(pattern, print_matches=False)
>     if "getprocaddress_resolve" in matches:
>         for m in matches["getprocaddress_resolve"]:
>             push1_arg_str = m["push1"][0].info.arg1
>             push1_arg_int = pygrap.parse_first_immediate(push1_arg_str)
>             func_name = get_strlit_contents(push1_arg_int).decode("utf-8")
>             mov_arg1 = m["mov"][0].info.arg1
>             var_addr = pygrap.parse_first_indirect(mov_arg1)
>             set_name(var_addr, func_name)
>             print("Function", func_name, "imported to", hex(var_addr), "- variable renamed.")

A few remarks:

- Instructions and arguments (..info.arg1 for instance) are stored as string
- Functions pygrap.parse_first_immediate and pygrap.parse_first_indirect are helpers:
  - pygrap.parse_first_immediate("byte 0x11") returns integer 17
  - pygrap.parse_first_indirect("dword [0x138100c]") returns integer 20451340
  - pygrap.parse_first_immediate("eax+0x11") returns None
  - pygrap.parse_first_immediate("[esi+0x138500]") returns None
  - You might still need to manually parse the strings in other situations
- There is no way in grap to match an imported function such as GetProcAddress by its name