Skip to content

Commit

Permalink
32bit shit
Browse files Browse the repository at this point in the history
SpaghettDev committed Jun 5, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 1c4de93 commit 2b20809
Showing 16 changed files with 8,827 additions and 103 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/.vscode
/__pycache__
/**/__pycache__
/codegen.txt
/jupyter
/broma_ida/types/codegen.hpp
5 changes: 3 additions & 2 deletions BromaIDA.py
Original file line number Diff line number Diff line change
@@ -28,7 +28,8 @@ def bida_main():
"""BromaIDA main entrypoint"""
import_export_prompt = popup(
"Import", "Export", "",
"Import or Export Broma file?"
"Import or Export Broma file?\n"
"(Please make sure Extras.bro is in the same directory)"
)

if import_export_prompt == ASKBTN_BTN1:
@@ -86,7 +87,7 @@ class BromaIDAPlugin(ida_plugin_t):
"""BromaIDA Plugin"""
flags = PLUGIN_PROC | PLUGIN_HIDE
comment = "Broma support for IDA."
help = "Ctrl-Shift-I to start the importing/exporting."
help = f"{PLUGIN_HOTKEY} to start the importing/exporting."
wanted_name = PLUGIN_NAME
wanted_hotkey = PLUGIN_HOTKEY

7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -10,6 +10,13 @@ Parses a Broma file and exports the bindings into a Broma file/imports the bindi

- IDA 7.0 or higher
- IDAPython Python v3.0.0 support
- If you want to be able to import types:
- IDAClang
- MSVC

## Features

TODO

## Installation

289 changes: 289 additions & 0 deletions broma_ida/broma/argtype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
from typing import cast, overload, Union, Optional, TypedDict, Literal

from re import split, match, sub


class BaseArgType(TypedDict):
"""A type. Has a register, a name and an actual type."""
name: str
type: str
reg: Optional[str]


class BaseShortArgType(TypedDict):
"""A type. Has an (optional) register, a name and an actual type."""
name: str
type: str


BASE_EXPANDED_STL_TYPES = {
"std::vector": "<{}, std::allocator<{}>>",
"std::map":
"<{0}, {1}, std::less<{0}>, std::allocator<std::pair<const {0}, {1}>>>", # noqa: E501
"std::unordered_map":
"<{0}, {1}, std::hash<{0}>, std::equal_to<{0}>, std::allocator<std::pair<const {0}, {1}>>>", # noqa: E501
"std::set": "<{}, std::less<{}>, std::allocator<{}>>",
"std::unordered_set":
"<{}, std::hash<{}>, std::equal_to<{}>, std::allocator<{}>>"
}

EXPANDED_STL_TYPES = {
"std::string":
"std::basic_string<char, std::char_traits<char>, std::allocator<char>>"
}


class ArgType:
"""An argument type"""
btype: BaseArgType

def _expand_stl_type(self, t: str) -> str:
"""Expands STL types because IDA is retarded and likes to expand them
Args:
t (str): _description_
Returns:
str: _description_
"""
# IDA likes spaces after types
format_pointer = lambda pt: sub(r"([^ ])\*", r"\1 *", pt) # noqa: E731

if "std::" not in t:
return t

if t == "std::string":
return t

if t.startswith("std::vector"):
split_type = match(r"std::vector<(.*)>", t)

assert split_type is not None, "impossible"

if split_type.group(1) in EXPANDED_STL_TYPES:
return format_pointer(f"""std::vector{
BASE_EXPANDED_STL_TYPES["std::vector"]
}""".replace(
"{}",
EXPANDED_STL_TYPES[split_type.group(1)] # type: ignore
))

# this should never happen, but it causes the below code
# to go ham
if "std::allocator" in t:
return t

# "it just works"
# credit to henrysck075 i couldnt figure out this shit :D
ret = t
vec_to_contained = [[ret, ret]]
while True:
try:
ret = match(r"std::vector<(.+)>", ret)

if ret is None:
break

ret = ret.group(1)
except IndexError:
break
vec_to_contained.append([ret, ret])

split_type = vec_to_contained[-1][0]
vec_to_contained[-2][1] = vec_to_contained[-2][1].replace(
f"<{split_type}>",
BASE_EXPANDED_STL_TYPES["std::vector"].replace(
"{}", split_type
)
)

for i in reversed(range(len(vec_to_contained) - 2)):
expanded_vec = vec_to_contained[i+1][1]
vec_to_contained[i][1] = vec_to_contained[i][1].replace(
f"<{vec_to_contained[i+1][0]}>",
BASE_EXPANDED_STL_TYPES["std::vector"].replace(
"{}", expanded_vec
)
)

return format_pointer(vec_to_contained[0][1])

if t.startswith("std::map"):
split_type = split(r"std::map<(.*), (.*)>", t)
map_key_type = ""
map_value_type = ""

# key or value is an STL type that has 2 template args
if "," in split_type[1] and split_type[2].endswith(">"):
map_key_type = split_type[1][:split_type[1].index(" ") - 1]
map_value_type = f"""{
split_type[1][split_type[1].index(" ") + 1:]
}, {
split_type[2]
}"""
else:
map_key_type = split_type[1]
map_value_type = split_type[2]

if map_key_type in EXPANDED_STL_TYPES or \
map_value_type in EXPANDED_STL_TYPES:
key_is_stl = map_key_type in EXPANDED_STL_TYPES
value_is_stl = map_value_type in EXPANDED_STL_TYPES

return format_pointer(f"""std::map{
BASE_EXPANDED_STL_TYPES["std::map"]
}""".replace(
"{0}",
EXPANDED_STL_TYPES[map_key_type]
if key_is_stl else map_key_type
).replace(
"{1}",
EXPANDED_STL_TYPES[map_value_type]
if value_is_stl else map_value_type
))

# std::map is never used as key
if any([
x in map_value_type for x in BASE_EXPANDED_STL_TYPES.keys()
]):
return format_pointer(f"""std::map{
BASE_EXPANDED_STL_TYPES["std::map"]
}""".replace(
"{0}", map_key_type
).replace(
"{1}", self._expand_stl_type(map_value_type)
))

return format_pointer(f"""std::map{
BASE_EXPANDED_STL_TYPES["std::map"]
}""".replace(
"{0}", map_key_type
).replace(
"{1}", map_value_type
))

if t.startswith("std::unordered_map"):
split_type = split(r"std::unordered_map<(.*), (.*)>", t)
map_key_type = ""
map_value_type = ""

if "," in split_type[1] and split_type[2].endswith(">"):
map_key_type = split_type[1][:split_type[1].index(" ") - 1]
map_value_type = f"""{
split_type[1][split_type[1].index(" ") + 1:]
}, {
split_type[2]
}"""
else:
map_key_type = split_type[1]
map_value_type = split_type[2]

if map_key_type in EXPANDED_STL_TYPES or \
map_value_type in EXPANDED_STL_TYPES:
key_is_stl = map_key_type in EXPANDED_STL_TYPES
value_is_stl = map_value_type in EXPANDED_STL_TYPES

return format_pointer(f"""std::unordered_map{
BASE_EXPANDED_STL_TYPES["std::unordered_map"]
}""".replace(
"{0}",
EXPANDED_STL_TYPES[map_key_type]
if key_is_stl else map_key_type
).replace(
"{1}",
EXPANDED_STL_TYPES[map_value_type]
if value_is_stl else map_value_type
))

# std::unordered_map is never used as key
if any([
x in map_value_type for x in BASE_EXPANDED_STL_TYPES.keys()
]):
return format_pointer(f"""std::unordered_map{
BASE_EXPANDED_STL_TYPES["std::unordered_map"]
}""".replace(
"{0}", map_key_type
).replace(
"{1}", self._expand_stl_type(map_value_type)
))

return format_pointer(f"""std::unordered_map{
BASE_EXPANDED_STL_TYPES["std::unordered_map"]
}""".replace(
"{0}", map_key_type
).replace(
"{1}", map_value_type
))

if t.startswith("std::set"):
contained = match("std::set<(.*)>", t)

assert contained is not None, "impossible"

return format_pointer(f"""std::set{
BASE_EXPANDED_STL_TYPES["std::set"]
}""".replace(
"{}", contained.group(1)
))

if t.startswith("std::unordered_set"):
contained = match("std::unordered_set<(.*)>", t)

assert contained is not None, "impossible"

return format_pointer(f"""std::unordered_set{
BASE_EXPANDED_STL_TYPES["std::unordered_set"]
}""".replace(
"{}", contained.group(1)
))

raise BaseException(f"[!] Couldn't expand STL type: {t}")

def __init__(self, btype: Union[BaseArgType, BaseShortArgType]):
if btype.get("reg"):
self.btype = cast(BaseArgType, btype)
else:
self.btype = {
"name": btype["name"],
"type": btype["type"],
"reg": None
}

self.btype["type"] = self._expand_stl_type(self.btype["type"])

def __str__(self) -> str:
if self.btype["name"] == "":
return self.btype["type"]

return f"""{self.btype["type"]} {self.btype["name"]}{
f"@<{self.btype['reg']}>" if self.btype["reg"] is not None else ""
}"""

def __eq__(self, key: object) -> bool:
if isinstance(key, str):
return self.btype["type"] == key

return False

@overload
def __getitem__(
self,
key: Literal[
"name", "type"
]
) -> str:
...

@overload
def __getitem__(self, key: Literal["reg"]) -> Optional[str]:
...

def __getitem__(self, key):
return self.btype.__getitem__(key)

def __setitem__(self, key, value):
self.btype[key] = value


class RetType(ArgType):
"""A return type"""
Loading

0 comments on commit 2b20809

Please sign in to comment.