原创文章,转载请注明: 转载自All-iPad.net 本文链接地址: 如何用gdb找到Android so文件中的加密key
来自XDA developer的一篇文章,作者详细描述了如何使用gdb + ida找到Angry Birds RIO Android版中lua文件的加密key,虽然目前还不会反向工程,不过说不定哪一天会用上,先记录下来。
Well… I have attached a debugger to native code, set breakpoints, analyzed registers, memory, etc. It wasn’t that easy though. It took me several days to start debugging and get first key, but I got second one in about 1 hour.
Actually I don’t really need that key, I can’t even play Angry Birds Rio on my old G1, but it was challenging and I love challenges Plus I have learnt a LOT about gdb, assembler, ARM architecture, etc.
So I want to thank you, Goddchen, for giving me an opportunity to learn & play
Ok, let’s move on…
First, I have disassembled libangrybirds.so using IDA Pro 5.5 . I was able to examine code and attach IDA to gdbserver on a device, but unfortunately it wasn’t working properly. IDA was thinking that libangrybirds.so is a main binary of a process it attached to, but it should look into loaded shared libs instead. Weird, but I didn’t find a way to attach it properly. And this is pity, because IDA is a great tool and it would make debugging a pleasure, but I had to use gdb instead.
Second, Android has problems with debugging multi-threaded native code. MT support was added in NDK r5 and because of some bug it’s not possible on a system older than Gingerbread.
Third, you could attach gdb manually, but ndk-gdb script does great work for you. You will have to do some tricks to use it with 3rd party app though.
Fourth, it seems libangrybirds.so is a Java code compiled to native or something like that. There are objects like FileInputStream, ByteOutputStream, etc., but there are also some API differencies. We’ll see String and Array
Steps to start native code debugging:
Ok, let’s find a key for levels lua files:
(gdb) br _ZN7GameLua9loadLevelEN4lang6StringE Breakpoint 1 at 0x80468e4c
(gdb) c Continuing. [New Thread 5857] [Switching to Thread 5857] Breakpoint 1, 0x80468e4c in GameLua::loadLevel () from /home/brutall/t-angrybirds/com.rovio.angrybirdsrio-1/obj/local/armeabi/libangrybirds.so
(gdb) x/4x $r1 0x4395e66c: 0x00a405f0 0x00153b28 0x804ec778 0x00000000 (gdb) x/s 0x00a405f0 0xa405f0: "levels/warehouse/Level190"
Yey, finally we see something
(gdb) advance _ZN4lang7AESUtil7decryptERKNS_5ArrayIhEES4_RS2_ 0x80539894 in lang::AESUtil::decrypt () from /home/brutall/t-angrybirds/com.rovio.angrybirdsrio-1/obj/local/armeabi/libangrybirds.so
(gdb) x/4x $r1 0x1592b0: 0x00159528 0x00000020 0x00000020 0x7b206e65
0×00000020 = 32 – yes, length of AES key First 4 bytes of an Array object is a pointer to raw char[] and second 4 bytes contain length of an array. Now we could read contents of an Array:
(gdb) x/s 0x00159528 0x159528: "USCaPQpA4TSNVxMI1v9SK9UC0yZuAnb2a"
As you can see there are 33 chars instead of 32. This is because Array stores its length, so char[] isn’t null-terminated. Ignore last “a” char.
(gdb) x/4x $r2 0x4395d6f4: 0x009ca248 0x000004a0 0x000004a0 0x00000378 (gdb) x/4x 0x009ca248 0x9ca248: 0x3347b5dc 0x26048446 0x1a0c1231 0x35d3f99c
First 16 bytes are the same, length of data is also ok.
As you can see there is AES::BlockMode passed to AES:ecrypt(). It would be quite hard to interpret it without headers, so I was trying various block modes and I found that CBC with empty initial vector decodes to string starting with ’7z’. For me that meant: mission successfull
Ok, highscores.lua and settings.lua files now. Technique is very similar, but there are some differences:
Maybe there is a better solution to last problem, but I’ve decided to add some Thread.sleep() call just after System.loadLibrary(), so gdb will attach before highscores.lua loading.
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V const-wide/16 v0, 5000 invoke-static {v0, v1}, Ljava/lang/Thread;->sleep(J)V
(gdb) br _ZN7GameLua18loadPersistentFileERKN4lang6StringE Breakpoint 1 at 0x80457030 (gdb) c Continuing. [New Thread 6735] [Switching to Thread 6735] Breakpoint 1, 0x80457030 in GameLua::loadPersistentFile () from /home/brutall/t-angrybirds/com.rovio.angrybirdsrio-1/obj/local/armeabi/libangrybirds.so (gdb) x/s $r2 0x4395e3b8: "highscores.lua"
I’m not sure why it’s R2, not R1 and why there is no lang::String, but char[] directly. I think this isn’t a pointer to String, but String itself, passed to method in registers, so its char[] is in R2.
(gdb) advance _ZN4lang7AESUtil7decryptERKNS_5ArrayIhEES4_RS2_ 0x80539894 in lang::AESUtil::decrypt () from /home/brutall/t-angrybirds/com.rovio.angrybirdsrio-1/obj/local/armeabi/libangrybirds.so (gdb) x/4x $r1 0x159294: 0x00159620 0x00000020 0x00000020 0x00159518 (gdb) x/s 0x00159620 0x159620: "44iUY5aTrlaYoet9lapRlaK1Ehlec5i0"
(gdb) x/4x $r2 0x4395ddc4: 0x0015bc00 0x00000040 0x00000040 0x00000001 (gdb) x/16x 0x0015bc00 0x15bc00: 0x2271b777 0xe6f19f4c 0x2489a316 0xfae1aee2 0x15bc10: 0x82e0ef38 0xe84fc25d 0xb196adac 0xbf030439 0x15bc20: 0xb6b9bade 0x3046af12 0xe8eeeb0d 0x20e8037c 0x15bc30: 0x1a405edf 0xc218f7f6 0xc29209e2 0x9ad03e8c
Yeah, this is my highscores.lua file.
Now we have got everything we want
Ahh, not exactly everything… I would be really happy to know, how to properly attach IDA for debugging – it would be much easier, even if gdb interface is also very good.
哦,忘了说一下这篇文章的作者,Brut.all,看到这个名字你应该就能够联想到,如果你有一台Android智能手机的话。没错,这位就是Brut Google Maps的作者,我的手机上就有他的App,另外他还发布了ApkTool,在Google Code上的开源工具,专门用来对apk做反向工程,当然现在也还用不着。
原创文章,转载请注明: 转载自All-iPad.net
本文链接地址: 如何用gdb找到Android so文件中的加密key