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

An item with the same key has already been added #67

Open
milenkowski opened this issue Jan 20, 2023 · 5 comments
Open

An item with the same key has already been added #67

milenkowski opened this issue Jan 20, 2023 · 5 comments
Labels
bug Something isn't working

Comments

@milenkowski
Copy link

milenkowski commented Jan 20, 2023

Describe the bug

Adding to a previous bug report on the same topic:

OldRod adds different values to dictionaries, related to constants and opcodes specifically, under previously used keys. This causes an exception to be thrown.

In the context of the sample provided below, this behavior can first be seen in the OldRodPipeline.ConstantsResolutions.ConstantResolutionStage.AutoDetectConstants function, where OldRod adds values to the constants.* dictionaries.

If the above function is modified to skip attempts to add values under a previously used key, the issue reappears in OldRodPipeline.OpCodeResolution.OpCodeResolutionStage.MatchOpCodeTypes function where OldRod works with the mapping1, mapping2, and opcodes dictionaries.

To Reproduce
OldRod.exe 0onfirm.exe

The sample is part of a malware, so please exercise caution.

Attached sample (assembly):

Expected behavior
No use of previously used keys when working with dictionaries for constant and opcode mapping.

Thank you for considering this issue.

Screenshots
screenshot

Additional context
/

@milenkowski milenkowski added the bug Something isn't working label Jan 20, 2023
@Washi1337
Copy link
Owner

Washi1337 commented Jan 20, 2023

This is a direct result of a modification and/or extra obfuscation that is applied on top of vanilla KoiVM, which is something that OldRod does not support out-of-the-box.

OldRod's current system for detecting opcode mappings is rather rudimentary. It searches for the method responsible for the initialization of the virtual machine. In vanilla KoiVM, this comprises a bunch of assignments to constant fields of type byte (see ConstantsResolutionStage.cs#L60 and ConstantsResolutionStage.cs#L190) . In your case this initialization is located in method SQLSTRING939AF857::.cctor() (metadata token 0x06000252). When you open this method in a decompiler, you can clearly see an extra layer of obfuscation is applied. Since oldrod is not a deobfuscator, you will need to clean those first, or else provide a config.json yourself that maps the byte values to their representative opcodes (see example-config.json for an example).

@milenkowski
Copy link
Author

Thank you for your fast response, much appreciated.

Just wondering: If SQLSTRING939AF857::.cctor() is modified such that it contains only concrete byte assignments, will OldRod detect those operations as opcode mappings (as part of the tool's search for the method responsible) and process accordingly?

@Washi1337
Copy link
Owner

Yes, OldRod's auto-detector assumes this method comprises only assignments to these fields. Thus, if you turn them into patterns similar to the following CIL sequence:

ldnull
ldc.i4 <value>
stfld field

then it should be able to automatically map all opcodes.

@milenkowski
Copy link
Author

milenkowski commented Jan 20, 2023

Thank you for your informative response.

I have (via dnSpy) transformed the obfuscated assignments to sequences of static assignments:

ldc.i4 <value>
stsfld field

However, the issue still persists and it triggers at the very same place (i.e., when resolving register mappings).

Wondering whether there are other obfuscated assignments that I may be missing, or whether the issue is with the code of Old Rod (since you pointed out to SQLSTRING939AF857::.cctor() in particular for the issue at hand).

Attaching the modified executable for reference.

EDIT: After closer look, I believe there is an added obfuscation by messing up the order of the constant groups (REG_, FL_, OP_, etc.), which may result in duplicate values per enum.

Thank you.

@Washi1337
Copy link
Owner

Yes this indeed seems to be the case.

Unfortunately, there is not really a way for OldRod to map opcodes automatically to their proper opcode handlers without this order being preserved. You will have to either write some detection mechanisms yourself and modify OldRod, or manually infer which fields correspond to what semantics and construct a manual mapping in a config.json file.

Not a great answer unfortunately, but the only one I have right now for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants