日系卡牌游戏都很热啊,这货下载量据说有500w+了
而且……日本的工程师似乎写代码的时候连类的名字都会取得差不多,非常方便。因此写篇文章,也许会对以后的或现有的(?)游戏破解带来一点灵感。
no bullshit let’s begin XD
JAVA层
dex2jar搞一下,得到一个jar,jd-gui浏览jar可以定位加密类位于jp.colopl/util/Crypto.class中,代码片段如下:
以及
从一个native method返回了SecretKeySpec对象。看来东西都在so里了
native层
IDA静态分析libcryptograph.so和libgetlockey.so,getlockey里没有JNI_load入口,跳过;在cryptograph里发现了名为Java_jp_colopl_util_Crypto_getKeySpec的导出@0x00000BD8 。就是它了XD,粘贴如下(没有arm汇编高亮残念了- -)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
.text:00000BD8 EXPORT Java_jp_colopl_util_Crypto_getKeySpec .text:00000BD8 Java_jp_colopl_util_Crypto_getKeySpec .text:00000BD8 .text:00000BD8 var_28 = -0x28 .text:00000BD8 var_1C = -0x1C .text:00000BD8 .text:00000BD8 PUSH {R4-R7,LR} .text:00000BDA LDR R2, [R0] .text:00000BDC LDR R1, =(unk_21FC - 0xBEA) .text:00000BDE MOVS R3, 0x29C .text:00000BE2 SUB SP, SP, #0x14 .text:00000BE4 LDR R3, [R2,R3] .text:00000BE6 ADD R1, PC .text:00000BE8 MOVS R5, R0 .text:00000BEA BLX R3 .text:00000BEC MOVS R2, R0 .text:00000BEE STR R0, [SP,#0x28+var_1C] .text:00000BF0 CMP R0, #0 .text:00000BF2 BEQ loc_CD8 .text:00000BF4 LDR R2, [R5] .text:00000BF6 MOVS R3, 0x2C0 .text:00000BFA LDR R3, [R2,R3] .text:00000BFC MOVS R0, R5 .text:00000BFE MOVS R1, #0x20 .text:00000C00 BLX R3 .text:00000C02 MOVS R2, R0 .text:00000C04 SUBS R7, R0, #0 .text:00000C06 BEQ loc_CD8 .text:00000C08 LDR R1, [R5] .text:00000C0A MOVS R3, 0x2E0 .text:00000C0E LDR R3, [R1,R3] .text:00000C10 MOVS R0, R5 .text:00000C12 MOVS R1, R2 .text:00000C14 MOVS R2, #0 .text:00000C16 BLX R3 .text:00000C18 SUBS R2, R0, #0 .text:00000C1A BEQ loc_CD8 .text:00000C1C MOVS R3, #0x30 .text:00000C1E STRB R3, [R2] .text:00000C20 MOVS R3, #0x6C .text:00000C22 STRB R3, [R2,#1] .text:00000C24 MOVS R3, #0x71 .text:00000C26 STRB R3, [R2,#2] .text:00000C28 MOVS R1, #0x66 .text:00000C2A MOVS R3, #0x47 .text:00000C2C STRB R3, [R2,#3] .text:00000C2E STRB R1, [R2,#6] .text:00000C30 MOVS R3, #0x54 .text:00000C32 MOVS R1, #0x4B .text:00000C34 STRB R3, [R2,#4] .text:00000C36 STRB R1, [R2,#8] .text:00000C38 MOVS R3, #0x79 .text:00000C3A MOVS R1, #0x39 .text:00000C3C STRB R3, [R2,#5] .text:00000C3E STRB R3, [R2,#7] .text:00000C40 STRB R1, [R2,#9] .text:00000C42 STRB R3, [R2,#0x17] .text:00000C44 MOVS R1, #0x49 .text:00000C46 MOVS R3, #0x77 .text:00000C48 STRB R1, [R2,#0xA] .text:00000C4A STRB R3, [R2,#0x18] .text:00000C4C MOVS R1, #0x32 .text:00000C4E MOVS R3, #0x48 .text:00000C50 STRB R1, [R2,#0xB] .text:00000C52 STRB R3, [R2,#0x19] .text:00000C54 MOVS R1, #0x6B .text:00000C56 MOVS R3, #0x4C .text:00000C58 STRB R1, [R2,#0xC] .text:00000C5A STRB R3, [R2,#0x1A] .text:00000C5C MOVS R1, #0x76 .text:00000C5E MOVS R3, #0x62 .text:00000C60 MOVS R0, #0x35 .text:00000C62 MOVS R4, #0x57 .text:00000C64 STRB R1, [R2,#0xD] .text:00000C66 STRB R0, [R2,#0xE] .text:00000C68 STRB R4, [R2,#0x11] .text:00000C6A STRB R1, [R2,#0x15] .text:00000C6C STRB R3, [R2,#0x1B] .text:00000C6E STRB R3, [R2,#0x1D] .text:00000C70 MOVS R0, #0x2E .text:00000C72 MOVS R4, #0x6E .text:00000C74 MOVS R1, #0x63 .text:00000C76 MOVS R3, #0x7A .text:00000C78 STRB R0, [R2,#0xF] .text:00000C7A STRB R4, [R2,#0x12] .text:00000C7C STRB R1, [R2,#0x16] .text:00000C7E STRB R3, [R2,#0x1E] .text:00000C80 MOVS R0, #0x59 .text:00000C82 MOVS R4, #0x53 .text:00000C84 MOVS R1, #0x5A .text:00000C86 MOVS R3, #0x4A .text:00000C88 STRB R0, [R2,#0x10] .text:00000C8A STRB R0, [R2,#0x14] .text:00000C8C STRB R3, [R2,#0x1F] .text:00000C8E STRB R4, [R2,#0x13] .text:00000C90 STRB R1, [R2,#0x1C] .text:00000C92 LDR R1, [R5] .text:00000C94 MOVS R3, 0x300 .text:00000C98 LDR R4, [R1,R3] .text:00000C9A MOVS R0, R5 .text:00000C9C MOVS R1, R7 .text:00000C9E MOVS R3, #0 .text:00000CA0 BLX R4 .text:00000CA2 LDR R3, [R5] .text:00000CA4 LDR R1, =(aJavaxCryptoSpe - 0xCAE) .text:00000CA6 MOVS R0, R5 .text:00000CA8 LDR R3, [R3,#0x18] .text:00000CAA ADD R1, PC ; "javax/crypto/spec/SecretKeySpec" .text:00000CAC BLX R3 .text:00000CAE LDR R1, [R5] .text:00000CB0 LDR R2, =(aInit - 0xCBE) .text:00000CB2 LDR R3, =(aBljavaLangStri - 0xCC0) .text:00000CB4 MOVS R6, R0 .text:00000CB6 ADDS R1, #8 .text:00000CB8 LDR R4, [R1,#0x7C] .text:00000CBA ADD R2, PC ; "<init>" .text:00000CBC ADD R3, PC ; "([BLjava/lang/String;)V" .text:00000CBE MOVS R1, R6 .text:00000CC0 MOVS R0, R5 .text:00000CC2 BLX R4 .text:00000CC4 LDR R1, [SP,#0x28+var_1C] .text:00000CC6 LDR R3, [R5] .text:00000CC8 MOVS R2, R0 .text:00000CCA STR R1, [SP,#0x28+var_28] .text:00000CCC LDR R4, [R3,#0x70] .text:00000CCE MOVS R0, R5 .text:00000CD0 MOVS R1, R6 .text:00000CD2 MOVS R3, R7 .text:00000CD4 BLX R4 .text:00000CD6 ADDS R2, R0, #0 .text:00000CD8 .text:00000CD8 loc_CD8 ; CODE XREF: Java_jp_colopl_util_Crypto_getKeySpec+1Aj .text:00000CD8 ; Java_jp_colopl_util_Crypto_getKeySpec+2Ej ... .text:00000CD8 ADD SP, SP, #0x14 .text:00000CDA MOVS R0, R2 .text:00000CDC POP {R4-R7,PC} .text:00000CDC ; End of function Java_jp_colopl_util_Crypto_getKeySpec |
掰弯xx王的制作团队你们好好看看啊,这才像点样啊好么,把AES密钥明文存储在so里面和没加密有个毛线差别啊摔!
(╯‵□′)╯︵┻━┻
浏览了下这段代码之后发现,大概是在这里调用了javax.crypto.spec.SecretKeySpec构造方法返回了SecretKeySpec对象。由于AES密钥长度只能是16的整数倍,于是找到0x00000C8C 处的
1 |
.text:00000C8C STRB R3, [R2,#0x1F] |
1Fh=32d,想到这可能是生成一个32位key的过程,往上找,应该就是00000C1E到00000C90 这部分的代码了;主要逻辑是,
1 2 |
.text:00000C24 MOVS R3, #0x71 ;R3赋值asc码为0x71的字符,即'q' .text:00000C26 STRB R3, [R2,#2] ;'q'放到R2的第三位 |
python脚本多快好省
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import sys _this = sys.modules[__name__] lines=asm.split('\n') #asm即上面那一坨汇编伪代码 aeskey=[[]]*32#R2 for l in lines: print l l=l[31:].split(' ') cmd,opt,dst=l[0],l[-2],l[-1] if cmd=='MOVS': setattr(_this,opt,chr(int(dst[3:],16))) if cmd=='STRB': if ',' not in dst: off=0 else: off=dst[1:-1].split(',')[1] off=int(off[1:],16) aeskey[off]=getattr(_this,opt) print ''.join(aeskey) |
得到0lqGTyfyK9I2kv5.YWnSYvcywHLbZbzJ,没试过,不知道对不对
done
然后……?
试了一下抓包然后解密,但似乎没有padding,嘛,不管了,反正对这个游戏不是很感兴趣,霓虹语略捉急ww
(不过所有问题的题干和答案都会在遇到妖怪的时候一起下载好,要做外挂的话应该很方便呢233
PS
java中使用>16字节(>128bit)的AES key会被认为是欠抽的做法,从这里下载安装无限密钥长度策略并覆盖原JAVA_HOME/lib/security下的文件即可
po主技术逆天啊,汇编完全不懂……敢问po主大学主修?
嘛……通信
顺便学习下arm指令集arm
from: 白猫Project/白猫プロジェクト ; 论野生技术&二次元