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

dotnet update: emit enclosing class information for nested classes #1913

Merged
merged 50 commits into from
Jan 5, 2024
Merged
Changes from 3 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
3f488f3
Update helpers.py
bkojusner Dec 20, 2023
94346e4
Update helpers.py
bkojusner Dec 20, 2023
8049bdc
TypeRef correction in helpers.py
bkojusner Dec 20, 2023
46103b5
Fixed TypeRef to proper functionality
bkojusner Dec 20, 2023
b2621c7
Accounts for TypeRef updated tuple
bkojusner Dec 20, 2023
94a8b65
Corrected TypeDef tuple creation in helpers.py
bkojusner Dec 20, 2023
eefdfcf
Update types.py
bkojusner Dec 21, 2023
36110d5
Update types.py
bkojusner Dec 21, 2023
73c8db7
Create helpers_draft.py
bkojusner Dec 23, 2023
bfcbb0d
Update capa/features/extractors/dnfile/helpers.py
bkojusner Dec 23, 2023
30267c0
Update helper functions, variables, and draft further implementations
bkojusner Dec 23, 2023
4f05fc6
Update helpers.py
bkojusner Dec 26, 2023
43e972a
Update types.py
bkojusner Dec 26, 2023
7381a1c
Directly access TypeDef and TypeRef tables
bkojusner Dec 27, 2023
b943ebb
Update helpers.py
bkojusner Dec 27, 2023
931cd84
Update helpers.py
bkojusner Dec 27, 2023
a1ea3f8
Delete capa/features/extractors/dnfile/helpers_draft.py
bkojusner Dec 27, 2023
0150b17
Update types.py
bkojusner Dec 27, 2023
9966ca3
Update dotnetfile.py
bkojusner Dec 27, 2023
8f16a57
Update types.py comment
bkojusner Jan 2, 2024
6257203
Clean extract_file_class_features in dotnetfile.py
bkojusner Jan 2, 2024
74abe41
Cleaned up callers, var names, and other small items
bkojusner Jan 2, 2024
66f01c0
Update dotnetfile.py
bkojusner Jan 2, 2024
f8a97cf
Clean up caller logic in dotnetfile.py
bkojusner Jan 3, 2024
bb381e5
Clean up callers and update helper logic in helpers.py
bkojusner Jan 3, 2024
bda8727
Linter corrections for types.py
bkojusner Jan 3, 2024
8679964
Linter corrections for dotnetfile.py
bkojusner Jan 3, 2024
531a35e
Linter corrections and caller functions cleanup for helpers.py
bkojusner Jan 3, 2024
b0c90de
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
ba0ecbd
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
f97f7f5
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
807fc1f
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
abccf7d
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
a1b9319
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
d9800b7
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
9ccdd01
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
d84f2b1
Update capa/features/extractors/dnfile/helpers.py
bkojusner Jan 4, 2024
62533f7
Update helpers.py
bkojusner Jan 4, 2024
1dd923a
Update dotnetfile.py
bkojusner Jan 4, 2024
b71c8ea
Update tuple type in types.py
bkojusner Jan 4, 2024
500ded3
Update dotnetfile.py
bkojusner Jan 4, 2024
465cb35
Update return value annotations in helpers.py
bkojusner Jan 4, 2024
c3b8e26
Linting update types.py
bkojusner Jan 4, 2024
89e7878
Linting update dotnetfile.py
bkojusner Jan 4, 2024
ee6f745
Added unit tests to fixtures.py
bkojusner Jan 4, 2024
3194caa
Update types.py
bkojusner Jan 5, 2024
aff5a13
Linting fix for types.py
bkojusner Jan 5, 2024
38ee13d
Update CHANGELOG.md
bkojusner Jan 5, 2024
edbd336
Merge branch 'master' into master
bkojusner Jan 5, 2024
3c6c82d
Small changes to return types in helpers.py
bkojusner Jan 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 97 additions & 3 deletions capa/features/extractors/dnfile/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ def get_dotnet_managed_imports(pe: dnfile.dnPE) -> Iterator[DnType]:
TypeName (index into String heap)
TypeNamespace (index into String heap)
"""
#typeref_table = get_typeref_table(pe)
#typeref_class_names = []
#typeref_assembled_class_names = {}

for rid, member_ref in iter_dotnet_table(pe, dnfile.mdtable.MemberRef.number):
assert isinstance(member_ref, dnfile.mdtable.MemberRefRow)

Expand All @@ -131,6 +135,9 @@ def get_dotnet_managed_imports(pe: dnfile.dnPE) -> Iterator[DnType]:
# remove get_/set_ from MemberRef name
member_ref_name = member_ref_name[4:]

#typeref_class_names.append((member_ref.Class.row.TypeName, member_ref.Class.row.TypeNamespace))
#member_ref.Class.row.TypeNamespace, member_ref.Class.row.TypeName, typeref_assembled_class_names = is_nested_helper(rid, typeref_table, typeref_class_names, member_ref.Class.row, typeref_assembled_class_names, False)

yield DnType(
token,
member_ref.Class.row.TypeName,
Expand Down Expand Up @@ -188,6 +195,10 @@ def get_dotnet_managed_methods(pe: dnfile.dnPE) -> Iterator[DnType]:
TypeNamespace (index into String heap)
MethodList (index into MethodDef table; it marks the first of a contiguous run of Methods owned by this Type)
"""
#nested_class_table = get_nested_class_table(pe)
#typedef_class_names = []
#typedef_assembled_class_names = {}

accessor_map: Dict[int, str] = {}
for methoddef, methoddef_access in get_dotnet_methoddef_property_accessors(pe):
accessor_map[methoddef] = methoddef_access
Expand All @@ -211,6 +222,9 @@ def get_dotnet_managed_methods(pe: dnfile.dnPE) -> Iterator[DnType]:
# remove get_/set_
method_name = method_name[4:]

#typedef_class_names.append((method_name, typedef.TypeNamespace))
#typedef.TypeNamespace, typedef.TypeName, typedef_assembled_class_names = is_nested_helper(idx, nested_class_table, typedef_class_names, typedef, typedef_assembled_class_names, True)

yield DnType(token, typedef.TypeName, namespace=typedef.TypeNamespace, member=method_name, access=access)


Expand Down Expand Up @@ -299,22 +313,102 @@ def get_dotnet_unmanaged_imports(pe: dnfile.dnPE) -> Iterator[DnUnmanagedMethod]
# like kernel32.CreateFileA
yield DnUnmanagedMethod(token, module, method)

def get_nested_class_table(pe):
bkojusner marked this conversation as resolved.
Show resolved Hide resolved
nested_class_table = {}

# Used to find nested classes in typedef
bkojusner marked this conversation as resolved.
Show resolved Hide resolved
for rid, nestedclass in iter_dotnet_table(pe, dnfile.mdtable.NestedClass.number):
assert isinstance(nestedclass, dnfile.mdtable.NestedClassRow)
nested_class_table[nestedclass.NestedClass.row_index] = nestedclass.EnclosingClass.row_index

return nested_class_table

def get_typeref_table(pe):
typeref_table = []

# Used to track values in typeref table
for rid, typeref in iter_dotnet_table(pe, dnfile.mdtable.TypeRef.number):
assert isinstance(typeref, dnfile.mdtable.TypeRefRow)
typeref_table.append((typeref.TypeName, typeref.TypeNamespace, typeref.struct.ResolutionScope_CodedIndex))

return typeref_table

def is_nested_helper(rid, table, class_names, typeX, assembled_class_names, is_typedef):
bkojusner marked this conversation as resolved.
Show resolved Hide resolved
if is_typedef:
name = typeX.TypeName
space = typeX.TypeNamespace
nested_classes = table

if rid in nested_classes:
space = class_names[nested_classes[rid]-1][1]

enclosing_class = class_names[nested_classes[rid]-1][0]
nested_class = class_names[rid-1][0]

if enclosing_class in assembled_class_names:
enclosing_class = f"{assembled_class_names[enclosing_class]}"
assembled_class_names[nested_class] = enclosing_class

for i in class_names:
if i[0] == enclosing_class.split('/')[0]:
space = i[1]

name = (enclosing_class, nested_class)
assembled_class_names[name[1]] = f"{name[0]}/{name[1]}"

else:
name = typeX.TypeName.split('`')[0] if '`' in typeX.TypeName else typeX.TypeName
space = typeX.TypeNamespace
typeref_table = table

if typeX.struct.ResolutionScope_CodedIndex <= len(typeref_table):
space = typeref_table[typeX.struct.ResolutionScope_CodedIndex-1][1]

enclosing_class = typeref_table[typeX.struct.ResolutionScope_CodedIndex-1][0]
nested_class = name

if enclosing_class in assembled_class_names:
enclosing_class = f"{assembled_class_names[enclosing_class]}"
assembled_class_names[nested_class] = enclosing_class

for i in class_names:
if i[0] == enclosing_class.split('/')[0]:
space = i[1]

name = (enclosing_class, nested_class)
assembled_class_names[name[1]] = f"{name[0]}/{name[1]}"

return space, name, assembled_class_names

def get_dotnet_types(pe: dnfile.dnPE) -> Iterator[DnType]:
"""get .NET types from TypeDef and TypeRef tables"""
nested_class_table = get_nested_class_table(pe)
typedef_class_names = []
typedef_assembled_class_names = {}

for rid, typedef in iter_dotnet_table(pe, dnfile.mdtable.TypeDef.number):
assert isinstance(typedef, dnfile.mdtable.TypeDefRow)

typedef_class_names.append((typedef.TypeName, typedef.TypeNamespace))
typedef.TypeNamespace, typedef.TypeName, typedef_assembled_class_names = is_nested_helper(rid, nested_class_table, typedef_class_names, typedef, typedef_assembled_class_names, True)

typedef_token: int = calculate_dotnet_token_value(dnfile.mdtable.TypeDef.number, rid)
yield DnType(typedef_token, typedef.TypeName, namespace=typedef.TypeNamespace)


typeref_table = get_typeref_table(pe)
bkojusner marked this conversation as resolved.
Show resolved Hide resolved
typeref_class_names = []
typeref_assembled_class_names = {}

for rid, typeref in iter_dotnet_table(pe, dnfile.mdtable.TypeRef.number):
assert isinstance(typeref, dnfile.mdtable.TypeRefRow)


typeref_class_names.append((typeref.TypeName, typeref.TypeNamespace))
typeref.TypeNamespace, typeref.TypeName, typeref_assembled_class_names = is_nested_helper(rid, typeref_table, typeref_class_names, typeref, typeref_assembled_class_names, False)

typeref_token: int = calculate_dotnet_token_value(dnfile.mdtable.TypeRef.number, rid)
yield DnType(typeref_token, typeref.TypeName, namespace=typeref.TypeNamespace)



def calculate_dotnet_token_value(table: int, rid: int) -> int:
return ((table & 0xFF) << Token.TABLE_SHIFT) | (rid & Token.RID_MASK)

Expand Down
Loading