在Objective-C中模糊返回值

时间:2012-10-12 19:39:33

标签: objective-c ios

我正在编写一个应用程序,出于安全考虑,我想混淆静态方法返回的值。调用ClassA中的静态方法的结果应该是BOOL,但我想尽可能让攻击者尽可能地获得返回的真实值(即我不想要要返回一个BOOL,我想返回一些看似随机但有些意义的垃圾。

// in ClassA
returnValue = [ClassB staticMethod];
BOOL actaulReturnValue = // some magic to de-obfuscate returnValue

例如:返回1024位大多数随机垃圾,但某处是一个有意义的数字(每次可能是一个不同的位)。

另一个例子:返回10个左右看似随机的数字,但如果这些10个数字出现在pi的前1000个数字中,则实际值为TRUE(接受10,000,000,000假数中将有1个数字的事实积极率)。

这是我能想到的两个例子,但我将它留给stackoverflow社区来帮助思考其他(可能更好)的方法。如果您还可以提供代码,则可获得奖励积分。

编辑:更难以进行逆向工程。如果我可以运行cycript并确定游戏结束的秘密 编辑2:即使攻击者知道我如何模糊返回值,仍然很难(如果不是不可能)找出真实值(这也是我的第二个例子的问题)< / p>

编辑3:我预先制作iOS应用的笔测试。我理解记忆中的任何东西都可以被阅读,因为我每天都会为客户做这件事。我也不是要暗示混淆和安全是一回事。话虽如此,我试图找出一种方法来阻止攻击者修补单个API调用以始终返回FALSE。

谢谢!

2 个答案:

答案 0 :(得分:5)

我会诚实地对你说:不要打扰。原因如下:

在某些时候,您需要将未加密的值加载到内存中

假设您制作方法来模糊其返回值 - 当您实际需要使用该值时会发生什么?你将它取消混淆并将其加载到存储在内存中的变量中。然后你的攻击者只需要检查那个内存位置,这个位置在越狱设备和一些额外的工具上是微不足道的。

你永远不会克服这个问题。做你想做的事绝对没有意义。你基本上注定要失败。如果您有兴趣让我的应用更加安全there's a great book published by O'Reilly,我发现它非常有用。

答案 1 :(得分:0)

您可以对结果执行一些棘手的按位操作以获取一些位索引,并检查该索引处的位以查看它是否已设置,例如。

在以下示例中:

  • 然后给出32位隐秘结果,我计算你的神秘结果的第2和第4个字节的XOR,然后再用较低的4位对高4位进行异或。这给了我一个4位结果,可以解释为0到15之间的index
  • 然后我使用这个索引知道我需要在剩余的2个字节中检查哪个位:我将第3个字节和第1个字节连接成16位字,并检查index - 位该单词是否已设置。

这是我测试的解码功能:

-(BOOL)decodeCrypticResult:(long)crypticResult
{
  u_int8_t* bytes = (u_int8_t*)&crypticResult;

  u_int8_t xor = bytes[1] ^ bytes[3];
  u_int8_t idx = ((xor>>4)&0xF) ^ (xor&0xF); // value in range [0..15]
  u_int16_t word = ((bytes[2]<<8) & 0xFF00) | bytes[0]; // bytes 2 and 0 concatenated into a 16-bit word
  BOOL res = (word >> idx) & 1; // check the idx-th bit of this word
  return res;
}

要生成您神秘的结果,要从图书馆的YES返回一个神秘的NOstaticMethod,这很容易:

  • 生成随机的32位数字
  • 从此随机数的表示
  • 计算上述位索引
  • 在返回之前设置或取消设置(取决于您需要返回的BOOL)随机数的第1个或第3个字节中的相应位

所以这给出了以下代码:

-(long)returnCrypticBoolValue:(BOOL)boolValue
{
  u_int32_t crypticResult = arc4random();
  u_int8_t* bytes = (u_int8_t*)&crypticResult;

  u_int8_t xor = bytes[1] ^ bytes[3];
  u_int8_t idx = ((xor>>4)&0xF) ^ (xor&0xF); // value in range [0..15]
  if (boolValue) {
    // set the idx-th bit of byte 2 or 0
    bytes[ (idx&8)?2:0 ] |=  (1 << (idx&7));
  } else {
    // unset the idx-th bit of byte 2 or 0
    bytes[ (idx&8)?2:0 ] &= ~(1 << (idx&7));
  }
  return crypticResult;
}