M1_Read 0x00 Daily Shell Check 无壳64位
0x01 DFA
Refer: https://blog.csdn.net/fenfei331/article/details/126385120
属于是知识盲区,不过去年好像听谁提过一句 DFA 攻击,在 AES-128 中其实就是在第九轮的列混合之前的时候修改一个字节 ,而第九轮就是最后一次列混合了,第十轮是没有列混合的。
于是会导致这样出来的密文与原密文有四个字节不一样,经过多次修改就会有多组错误密文,然后通过正确密文和错误密文就可以推算出第10轮的密钥,继而推出原始密钥。
所以在实际应用中,就需要找准列混合的函数位置,在他之前修改数据。
而在实际样本分析中,如果 结果全部不同 说明时机太早了,只有一个不同 说明时机太晚了。
Frida Hook 那么现在就是去 hook 程序中的轮密钥加的位置了,在一堆函数中翻翻翻配合 fincrypt 可以猜测 sub_140004BF0 是 AES 加密
于是 hook 的思路
hook 进入加密 do while 循环前的一个地址计数,第九轮的时候修改值
主动调用该函数,多次获取密文,即可拿到错误数据
写出脚本
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 import fridaimport syssession = frida.attach("m1_read.exe" ) script = session.create_script(""" var baseAddr = Module.findBaseAddress("m1_read.exe"); var whiteAES = new NativeFunction(baseAddr.add(0x4BF0), 'pointer', ['pointer', 'pointer']) var count = 9; Interceptor.attach(baseAddr.add(0x4C2C), { onEnter: function(args) { count++; if(count == 9) { // console.log(Math.floor(Math.random() * 16)).writeU8(Math.floor(Math.random() * 256)); this.context.rdi.add(Math.floor(Math.random() * 16)).writeU8(Math.floor(Math.random() * 256)); } }, onLeave: (retval) => { } }) for (let index = 0; index < 32; index++) { var l = Memory.allocAnsiString("1234567890abcdef"); var b = Memory.alloc(16); whiteAES(l, b); console.log(b.readByteArray(16)); count = 0; } """ )script.load()
(学习了 sink 师傅的 frida 脚本)
这样子就可以拿到多组的结果了,随后利用该工具来获取最后一轮的 key
https://github.com/SideChannelMarvels/JeanGrey
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 data = """ ca 42 9f dc 6b fa 9b 5e 54 0c 8f 14 b0 3b ae 88 .B..k..^T....;.. ca 3a 9f dc 1d fa 9b 5e 54 0c 8f 87 b0 3b 6e 88 .:.....^T....;n. ca 69 9f dc 9f fa 9b 5e 54 0c 8f 11 b0 3b f5 88 .i.....^T....;.. ca d4 9f dc bd fa 9b 5e 54 0c 8f a5 b0 3b 3f 88 .......^T....;?. ca 42 44 dc 6b 17 9b 5e f3 0c 8f 14 b0 3b ae e0 .BD.k..^.....;.. ca c3 9f dc a3 fa 9b 5e 54 0c 8f 6f b0 3b d6 88 .......^T..o.;.. ca 42 9f 9b 6b fa 3d 5e 54 44 8f 14 6f 3b ae 88 .B..k.=^TD..o;.. ca 42 6b dc 6b ba 9b 5e 56 0c 8f 14 b0 3b ae e8 .Bk.k..^V....;.. ca 42 6c dc 6b 55 9b 5e e3 0c 8f 14 b0 3b ae 6e .Bl.kU.^.....;.n ca 42 9f ea 6b fa 45 5e 54 d4 8f 14 61 3b ae 88 .B..k.E^T...a;.. ca 42 f3 dc 6b 09 9b 5e bf 0c 8f 14 b0 3b ae 69 .B..k..^.....;.i ca 42 9f 93 6b fa 61 5e 54 c3 8f 14 fe 3b ae 88 .B..k.a^T....;.. ca f3 9f dc 8d fa 9b 5e 54 0c 8f 84 b0 3b 21 88 .......^T....;!. ca d6 9f dc b2 fa 9b 5e 54 0c 8f f9 b0 3b e2 88 .......^T....;.. ca 42 9f fd 6b fa b9 5e 54 f7 8f 14 a6 3b ae 88 .B..k..^T....;.. ca 40 9f dc cf fa 9b 5e 54 0c 8f e4 b0 3b 96 88 .@.....^T....;.. """ arr_data = "" for t in data.split('\n' ): tmp = bytearray .fromhex(t[:47 ]) if tmp != b'' : arr_data += tmp.hex () + '\n' print (arr_data)import phoenixAESwith open ("tracefile" , "wb" ) as t: t.write(""" ca429fdc6bfa9b5e540c8f14b03bae88 ca3a9fdc1dfa9b5e540c8f87b03b6e88 ca699fdc9ffa9b5e540c8f11b03bf588 cad49fdcbdfa9b5e540c8fa5b03b3f88 ca4244dc6b179b5ef30c8f14b03baee0 cac39fdca3fa9b5e540c8f6fb03bd688 ca429f9b6bfa3d5e54448f146f3bae88 ca426bdc6bba9b5e560c8f14b03baee8 ca426cdc6b559b5ee30c8f14b03bae6e ca429fea6bfa455e54d48f14613bae88 ca42f3dc6b099b5ebf0c8f14b03bae69 ca429f936bfa615e54c38f14fe3bae88 caf39fdc8dfa9b5e540c8f84b03b2188 cad69fdcb2fa9b5e540c8ff9b03be288 ca429ffd6bfab95e54f78f14a63bae88 ca409fdccffa9b5e540c8fe4b03b9688 ca42a0dc6bf59b5e450c8f14b03baefe ca42dedc6b039b5e2b0c8f14b03baeed 91429fdc6bfa9bb9540c3514b0fcae88 ca2a9fdc77fa9b5e540c8ff7b03bd388 ca429fbf6bfa7c5e547c8f14823bae88 ca429f086bfafc5e54a08f14143bae88 caf89fdc25fa9b5e540c8f65b03b6888 a0429fdc6bfa9bda540c5e14b015ae88 ca42c6dc6bf59b5e620c8f14b03bae72 ca009fdc01fa9b5e540c8ff0b03b1288 ca429f306bfa345e54b78f14dc3bae88 ca429f2b6bfa665e547b8f14793bae88 ca42f8dc6ba19b5e590c8f14b03baeb5 cac89fdcfafa9b5e540c8f63b03b0488 ca429fe76bfa755e54b18f146b3bae88 ca429fd66bfa485e541a8f14a43bae88 ca4270dc6b369b5ee10c8f14b03bae6a caf39fdc8dfa9b5e540c8f84b03b2188 ca429f9e6bfa885e548c8f14623bae88 ca429f9f6bfa635e540f8f14d13bae88 ca429f666bfa795e54928f14ed3bae88 ca1e9fdce1fa9b5e540c8ff8b03b0288 ca42e4dc6be79b5e0b0c8f14b03bae68 ca423bdc6bb19b5e010c8f14b03bae3e ca429f146bfa365e54958f14783bae88 2d429fdc6bfa9b6a540cb414b0ecae88 95429fdc6bfa9be8540c2a14b03dae88 ca42b5dc6b659b5e030c8f14b03baedb ca429f0f6bfad85e54208f145c3bae88 ca4268dc6b439b5e020c8f14b03baea7 ca569fdc65fa9b5e540c8f39b03b9c88 ca4d9fdc58fa9b5e540c8f9db03be988 caff9fdc2cfa9b5e540c8f33b03b7b88 ca429f5f6bfa905e549d8f14043bae88 """ .encode('utf8' ))phoenixAES.crack_file('tracefile' , verbose=0 )
(注意尾巴还有一个异或0x66,最后一轮Key获得之后要异或该值,或将多组密文都异或0x66也可获取)
有了最后一轮 key 就可以还原出最原先的 key
https://github.com/SideChannelMarvels/Stark
0x02 Get Flag 那么有了 key,直接解密 out.bin 里的数据即可
1 2 3 4 5 6 7 8 9 10 from Crypto.Cipher import AESkey = bytes .fromhex("00000000000000000000000000000000" ) cipher = AES.new(key, AES.MODE_ECB) enc = bytearray .fromhex("0B987EF5D94DD679592C4D2FADD4EB89" ) for i in range (16 ): enc[i] ^= 0x66 print (cipher.decrypt(enc))
Get Flag!