且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何避免硬编码加密密钥(目标C)?

更新时间:2022-12-22 15:12:15

我写过解决此问题的挑战,但是我想用你的 UAObfuscatedString 想法进行一些演示,因为我认为这是大多数人都在寻找的解决方案,但是比没什么好。重要的是要注意:我并不是特别擅长这一点。我不是一名经验丰富的逆向工程师,商业系统超出了我的技能水平。我只是一个有 Hopper 的人,还有五分钟的逆向工程(我跑了一个计时器; 5:35s ,包括升级Hopper,因为我几个月没有运行它。)

I've written about the challenges of solving this problem before, but I wanted to demonstrate a little bit using your UAObfuscatedString idea, since I think this is the kind of solution most people are looking for, but is worse than nothing. It's important to note: I'm not particularly good at this. I'm not a seasoned reverse engineer and commercial systems are way beyond my skillset. I'm just a guy with Hopper and literally five minutes of reverse engineering work (I ran a timer; 5:35s, including upgrading Hopper because I hadn't run it in a few months).

所以,我用 UAObfuscatedString写了一个iOS程序。我使用Swift是因为Swift通常比ObjC更难逆向工程。 ObjC是逆向工程师的梦想。

So, I wrote an iOS program with UAObfuscatedString. I used Swift because Swift is generally a little harder to reverse engineer than ObjC. ObjC is a reverse engineer's dream.

let identifier = "c".o.m.dot.u.r.b.a.n.a.p.p.s.dot.e.x.a.m.p.l.e

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    print(identifier)
    return true
}

然后我将其存档,所以它是优化的代码等等,就像你发送到App Store一样。然后我将其加载到Hopper并查看应用程序委托的 init 。这是常量初始化的地方,基于大多数人将这些东西粘贴在他们的app委托中的假设。显然,如果我看到一个名为 KeyStorage SecretStuffHelper 的类,我会先看一下....

I then archived it, so it's optimized code, etc. etc. just like you'd send to the App Store. I then loaded it up in to Hopper and looked at the app delegate's init. That's where constants are initialized, based on the assumption that most people stick this stuff in their app delegate. Obviously if I see a class named KeyStorage or SecretStuffHelper, I'd look there first....

void * -[_TtC13ObfuscateTest11AppDelegate init](void * self, void * _cmd) {
    *(r31 + 0xffffffffffffffe0) = r20;
    *(0xfffffffffffffff0 + r31) = r19;
    *(r31 + 0xfffffffffffffff0) = r29;
    *(r31 + 0x0) = r30;
    r0 = sub_100005e14();
    return r0;
}

嗯,它调用这个匿名函数 sub_100005e14() 。让我们看看它是做什么的。

Hmm, it calls this anonymous function sub_100005e14(). Let's see what that does.

...
0000000100005e38         adr        x0, #0x100006859                            ; "c"
...
0000000100005e48         bl         imp___stubs___T0SS18UAObfuscatedStringE1oSSfg
...
0000000100005e50         bl         imp___stubs___T0SS18UAObfuscatedStringE1mSSfg
...
0000000100005e74         bl         imp___stubs___T0SS18UAObfuscatedStringE3dotSSfg
...
0000000100005e98         bl         imp___stubs___T0SS18UAObfuscatedStringE1uSSfg
...
0000000100005ebc         bl         imp___stubs___T0SS18UAObfuscatedStringE1rSSfg
...
0000000100005ee0         bl         imp___stubs___T0SS18UAObfuscatedStringE1bSSfg
...
0000000100005f04         bl         imp___stubs___T0SS18UAObfuscatedStringE1aSSfg
...
0000000100005f28         bl         imp___stubs___T0SS18UAObfuscatedStringE1nSSfg
...
0000000100005f4c         bl         imp___stubs___T0SS18UAObfuscatedStringE1aSSfg
...
0000000100005f70         bl         imp___stubs___T0SS18UAObfuscatedStringE1pSSfg
...
0000000100005f94         bl         imp___stubs___T0SS18UAObfuscatedStringE1pSSfg
...
0000000100005fb8         bl         imp___stubs___T0SS18UAObfuscatedStringE1sSSfg
...
0000000100005fdc         bl         imp___stubs___T0SS18UAObfuscatedStringE3dotSSfg
...
0000000100006000         bl         imp___stubs___T0SS18UAObfuscatedStringE1eSSfg
...
0000000100006024         bl         imp___stubs___T0SS18UAObfuscatedStringE1xSSfg
...
0000000100006048         bl         imp___stubs___T0SS18UAObfuscatedStringE1aSSfg
...
000000010000606c         bl         imp___stubs___T0SS18UAObfuscatedStringE1mSSfg
...
0000000100006090         bl         imp___stubs___T0SS18UAObfuscatedStringE1pSSfg
...
00000001000060b4         bl         imp___stubs___T0SS18UAObfuscatedStringE1lSSfg
...
00000001000060d8          bl         imp___stubs___T0SS18UAObfuscatedStringE1eSSfg

我不确定为什么Swift会消失r在这里不起作用,但无论如何,我们可以很容易地看到模式:

I'm not sure why the Swift demangler isn't working here, but anyway, we can easily see the pattern:

_T0SS18UAObfuscatedStringE1oSSfg => o
_T0SS18UAObfuscatedStringE1mSSfg => m
_T0SS18UAObfuscatedStringE3dotSSfg => dot => .
_T0SS18UAObfuscatedStringE1uSSfg => u
...

实现这些 USObfuscatedString 方法,我搜索它并在应用程序中找到使用混淆字符串的所有地方。如果我愿意花一点时间玩我的游戏并花一天时间玩它,我可能会编写一个工具来自动提取每个 UAObfuscatedString 只需使用 otool 和二进制文件。

Realizing there are these USObfuscatedString methods, I search for that and find everywhere in the app that uses obfuscated strings. If I was willing to up my game a little and spend a day or so playing with it, I could probably write a tool to automatically extract every UAObfuscatedString just using otool and the binary.

这是深刻的教训。您刚刚标记了要隐藏的所有字符串。一旦我意识到 UAObfuscatedString 是一件事,你就让我更容易让我找到你的敏感信息。它实际上比没有任何东西更糟糕。你唯一的希望是攻击者不知道这存在。这就是混淆的问题,以及混淆与安全的区别。

And this is the deep lesson. You've just labeled all the strings you want to hide. Once I realize that UAObfuscatedString is a thing, you just made it easier for me to find your sensitive information. It is literally worse than nothing. Your only hope here is that the attacker doesn't know this exists. That's the problem with obfuscation, and what separates obfuscation from security.

我还要强调我花了5分35秒攻击这个程序。是的,我基本上知道我在寻找什么样的东西,但我也没有这方面的技能。如果 UAObfuscatedString 变得流行,我向你保证自动检测/去混淆工具将成为每个script-kiddie工具箱的一部分(script-kiddie是什么安全人员称攻击者不知道他们在做什么,只使用其他人编写的自动化工具。

I want also to emphasize that I spent 5 minutes and 35 seconds attacking this program. Yes, I knew basically what kind of thing I was looking for, but I also have no skills at this. If UAObfuscatedString were to become popular, I assure you that the auto-detect/de-obfuscate tool would become part of every script-kiddie's toolbox ("script-kiddie" is what security folks call attackers who do not know what they're doing, and just use automated tools that others have written).

这里的教训是,如果你想混淆,你***自己制定一些随机的方法。它不会有效,但它可能不会像大多数FOSS解决方案那样对您的目标产生积极影响。 免费和开源对安全性非常有利,但对于默默无闻是最糟糕的事情。

The lesson here is that if you want to obfuscate, you're better off making up some random approach yourself. It won't be effective, but it probably won't be actively harmful to your goal in the way that most FOSS solutions are. "Free and open source" can be very good for security, but are the worst possible thing for obscurity.

如果隐藏信息对您的商业计划非常重要,那么您可以不要改变你的商业计划,那么你应该花费很多钱来解决这个问题,聘请一支致力于不断发展你的混淆系统的团队,以保持领先于适应你所建立的任何人的攻击者。

If hiding information is really important to your business plan and you can't change your business plan, then you should expect to spend a lot of money on this problem and hire a team of people dedicated to constantly evolving your obfuscation system to keep ahead of attackers who will adapt to whatever you build.