How can I hook method and mutate argument which is __NSFrozenDictionaryM

Hi guys!

I would like to hook a method, which takes an argument of type __NSFrozenDictionaryM.
My goal is to be able to change the value of this argument just before running %orig.

It would look something like :

%hook myClass 
- void myMethod: (id) frozenDict {
  [frozenDict setValue: @"something" forKey: @"notWorking"];
  %orig;
}

Of course, this snippet crashes because __NSFrozenDictionaryM is immutable.

Important: I could do something as follow but that does not solve my issue because I need to modify the argument itself and not the copy:

%hook myClass 
// not solving my problem!
- void myMethod: (id) frozenDict {
  NSMutableDictionnary *mutableCopy = [frozenDict mutableCopy];
  [mutableCopy setValue: @"something" forKey: @"notWorking"];
  %orig;
}

I’ve also tried to create a recursive function, as follow, which does not work as well.

%hook myClass 
// not solving my problem!
- void myMethod: (id) frozenDict {
  BOOL isFrozen = [frozenDict class] == [NSClassFromString(@"__NSFrozenDictionaryM") class];
  if (isFrozen) {
    return [self myMethod:  [frozenDict mutableCopy]];
  }
  %orig;
}

Do you have any solution allowing my to change this argument dictionnary ITSELF and not its copy?

Thanks and happy hacking :wink:

Shouldn’t it be

%hook myClass 
- void myMethod: (id) frozenDict {
  NSMutableDictionnary *mutableCopy = [frozenDict mutableCopy];
  [mutableCopy setValue: @"something" forKey: @"notWorking"];
  %orig(mutableCopy);
}

?

nice ,so beautiful ,lao tie 666

Thanks for your fast answer :slight_smile:

Unfortunately that does not work in my case because I need to change the argument value for all the app state.

Let’s imagine something like that in pseudo code:

char* a = "something";

void doSomethingWithA(char *a) {
    a = "somethingElse";
}

void doAnotherthingWithA(char *a) {
  NSLog(a);
}

int main(void) {
   char *a = "LOL";
   doSomethingWithA(a);
   doAnotherthingWithA(a); // outputs somethingElse
}

I need this argument change for all functions using the same pointer.

Got you, so your purpose is to change one argument for all methods that use it as a param, correct?

Yes exactly :slight_smile:

If so you should reverse the method until you track the origin of the argument and figure out how it is generated, then do some hacks at that points. Now you are in the middle of the chain.

Thanks for your help. The problem is that it’s very difficult to track the origin of this chain, but I’ll definitely try.

I’ve also thought about another solution: it consists in hooking the init method of the class corresponding to my argument type and when it corresponds to the desired pattern, change the behavior of init in order to initialize it with my own content.

Something like (pseudo code):

%hook NSDictionnary
- id initWithValue: id value {
  if (matchesPattern) {
    return %orig(@{ desiredValue: true });
  }
  return %orig;
}
%end

The above solution is in my case horrible, but it could help someone I hope.

Thanks :slight_smile: