import-to-ida: use existing result document json parser

This commit is contained in:
Willi Ballenthin
2023-07-05 18:21:03 +02:00
parent 169b3d60a8
commit 19a5ef8a64

View File

@@ -29,13 +29,16 @@ Unless required by applicable law or agreed to in writing, software distributed
See the License for the specific language governing permissions and limitations under the License. See the License for the specific language governing permissions and limitations under the License.
""" """
import binascii import binascii
import json
import logging import logging
import ida_nalt import ida_nalt
import ida_funcs import ida_funcs
import ida_kernwin import ida_kernwin
import capa.rules
import capa.features.freeze
import capa.render.result_document
logger = logging.getLogger("capa") logger = logging.getLogger("capa")
@@ -65,40 +68,37 @@ def main():
if not path: if not path:
return 0 return 0
with open(path, "rb") as f: result_doc = capa.render.result_document.ResultDocument.parse_file(path)
doc = json.loads(f.read().decode("utf-8")) meta, capabilities = result_doc.to_capa()
if "meta" not in doc or "rules" not in doc:
logger.error("doesn't appear to be a capa report")
return -1
# in IDA 7.4, the MD5 hash may be truncated, for example: # in IDA 7.4, the MD5 hash may be truncated, for example:
# wanted: 84882c9d43e23d63b82004fae74ebb61 # wanted: 84882c9d43e23d63b82004fae74ebb61
# found: b'84882C9D43E23D63B82004FAE74EBB6\x00' # found: b'84882C9D43E23D63B82004FAE74EBB6\x00'
# #
# see: https://github.com/idapython/bin/issues/11 # see: https://github.com/idapython/bin/issues/11
a = doc["meta"]["sample"]["md5"].lower() a = meta["sample"]["md5"].lower()
b = binascii.hexlify(ida_nalt.retrieve_input_file_md5()).decode("ascii").lower() b = binascii.hexlify(ida_nalt.retrieve_input_file_md5()).decode("ascii").lower()
if not a.startswith(b): if not a.startswith(b):
logger.error("sample mismatch") logger.error("sample mismatch")
return -2 return -2
rows = [] rows = []
for rule in doc["rules"].values(): for name in capabilities.keys():
if rule["meta"].get("lib"): rule = result_doc.rules[name]
if rule.meta.lib:
continue continue
if rule["meta"].get("capa/subscope"): if rule.meta.is_subscope_rule:
continue continue
if rule["meta"]["scope"] != "function": if rule.meta.scope != capa.rules.Scope.FUNCTION:
continue continue
name = rule["meta"]["name"] ns = rule.meta.namespace
ns = rule["meta"].get("namespace", "")
for address, match in rule["matches"]: for address, _ in rule.matches:
if address["type"] != "absolute": if address.type != capa.features.freeze.AddressType.ABSOLUTE:
continue continue
va = address["value"] va = address.value
rows.append((ns, name, va)) rows.append((ns, name, va))
# order by (namespace, name) so that like things show up together # order by (namespace, name) so that like things show up together