Sangfor华东天勇战队:某咖啡还原密钥 您所在的位置:网站首页 云南是华南吗还是华北 Sangfor华东天勇战队:某咖啡还原密钥

Sangfor华东天勇战队:某咖啡还原密钥

2023-06-29 13:13| 来源: 网络整理| 查看: 265

最近学习了密钥还原,复现下并记录思路

function wbaes_encrypt_ecb(){ var module_base = Module.findBaseAddress("libcryptoDD.so") var func_base = module_base.add(0x17BD4+1) Interceptor.attach(func_base,{ onEnter:function (args){ console.log("Enter wbaes_encrypt_ecb....") } }) }

双进程保护 在这里插入图片描述 然后我们查看进程在这里插入图片描述 绕过双进程保护方式,使用spwan方法来进行frida hook 在这里插入图片描述 可以看到成功绕过,我们看看我们写的函数经过吗 在这里插入图片描述 发现frida15.2.2存在bug,就是上面这样,不能执行函数,我们换成12.8.0来试试 在这里插入图片描述 可以看到成功打印,说明经过此函数 然后我们看看它的参数和返回值 在这里插入图片描述 发现有四个参数,分别是in、in_len 、out 、mode ,然后我们打印来看看

function wbaes_encrypt_ecb(){ var module_base = Module.findBaseAddress("libcryptoDD.so") var func_base = module_base.add(0x17BD4+1) Interceptor.attach(func_base,{ onEnter:function (args){ this.in = args[0] this.in_len = args[1].toInt32() //将指针转换成int32 this.out = args[2] this.mode = args[3].toInt32() console.log("Input && len:",this.in_len," && mode:",this.mode) //打印输入 console.log(hexdump(this.in,{length:this.in_len})) } }) }

在这里插入图片描述 然后来打印下返回值

function wbaes_encrypt_ecb(){ var module_base = Module.findBaseAddress("libcryptoDD.so") var func_base = module_base.add(0x17BD4+1) Interceptor.attach(func_base,{ onEnter:function (args){ this.in = args[0] this.in_len = args[1].toInt32() //将指针转换成int32 this.out = args[2] this.mode = args[3].toInt32() console.log("Input && len:",this.in_len," && mode:",this.mode) //打印输入 console.log(hexdump(this.in,{length:this.in_len})) }, onLeave:function(){ console.log("Output ....") console.log(hexdump(this.out,{length:this.in_len})) } }) }

在这里插入图片描述 单独拿出这一段看

Input && len: 96 && mode: 0 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF f589c740 7b 22 70 61 67 65 54 79 70 65 22 3a 22 32 22 2c {"pageType":"2", f589c750 22 74 61 67 49 6e 64 65 78 22 3a 22 22 2c 22 61 "tagIndex":"","a f589c760 70 70 76 65 72 73 69 6f 6e 22 3a 22 34 39 33 30 ppversion":"4930 f589c770 22 2c 22 70 61 67 65 22 3a 31 2c 22 72 6f 77 73 ","page":1,"rows f589c780 22 3a 31 36 2c 22 62 72 61 6e 64 43 6f 64 65 22 ":16,"brandCode" f589c790 3a 22 4c 4b 30 30 31 22 7d 07 07 07 07 07 07 07 :"LK001"}....... Output .... 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF f589ca40 53 bd 58 25 98 ba ac 09 40 1e 71 fb ae 66 07 44 S.X%[email protected] f589ca50 8e d3 43 5e 8c f1 5d cd 36 2e f2 6f 81 6a 79 1f ..C^..].6..o.jy. f589ca60 91 39 c0 3e 99 0d 0a d7 fe 4a 1f dd c7 0f 08 a6 .9.>.....J...... f589ca70 50 b4 81 a1 7e 6c 21 c2 f8 cd 30 68 7a 53 ab 8c P...~l!...0hzS.. f589ca80 f8 e8 a7 a0 95 e1 c1 4c db 92 c1 a8 d8 04 43 30 .......L......C0 f589ca90 9f 35 a4 a5 58 92 e6 3c 29 17 0e 30 11 8d c5 e8 .5..X.. // onEnter:function (args){ // this.in = args[0] // this.in_len = args[1].toInt32() //将指针转换成int32 // this.out = args[2] // this.mode = args[3].toInt32() // console.log("Input && len:",this.in_len," && mode:",this.mode) //打印输入 // console.log(hexdump(this.in,{length:this.in_len})) // }, // onLeave:function(){ // console.log("Output ....") // console.log(hexdump(this.out,{length:this.in_len})) // } // }) // } function hexToBytes(hex){ //十六进制转字节 for (var bytes = [],c=0;c var module_base = Module.findBaseAddress("libcryptoDD.so") var func_base = module_base.add(0x17BD4+1) var wb_aes_ecb_native = new NativeFunction(func_base,"int",["pointer","int","pointer","int"]) //参考frida api,第一个参数地址,第二个返回值,第三个参数 var inputPtr = Memory.alloc(0x60) //输入内存大小正好0x60 var inputData = hexToBytes(data) //输入的数据 Memory.writeByteArray(inputPtr,inputData) //数据写入地址 var outputPtr = Memory.alloc(0x60) //输出内存大小正好0x60 wb_aes_ecb_native(inputPtr,0x60,outputPtr,0) //wb_aes_ecb_native函数调用,参数对应 console.log(hexdump(outputPtr,{length:0x60})) //打印输出值 } function call_wb_aes(){ var data1 = "7b227061676554797065223a2232222c22746167496e646578223a22222c2261707076657273696f6e223a2234393330222c2270616765223a312c22726f7773223a31362c226272616e64436f6465223a224c4b303031227d07070707070707" invoke_wb_aes_ecb(data1) //调用 } f589c740 7b 22 70 61 67 65 54 79 70 65 22 3a 22 32 22 2c {"pageType":"2", f589c750 22 74 61 67 49 6e 64 65 78 22 3a 22 22 2c 22 61 "tagIndex":"","a f589c760 70 70 76 65 72 73 69 6f 6e 22 3a 22 34 39 33 30 ppversion":"4930 f589c770 22 2c 22 70 61 67 65 22 3a 31 2c 22 72 6f 77 73 ","page":1,"rows f589c780 22 3a 31 36 2c 22 62 72 61 6e 64 43 6f 64 65 22 ":16,"brandCode" f589c790 3a 22 4c 4b 30 30 31 22 7d 07 07 07 07 07 07 07 :"LK001"}.......

输入这段转成hex,如下,要先from hexdump然后to hex 在这里插入图片描述 然后放到代码中 frida运行此脚本 在这里插入图片描述 可以看到得到的结果和刚才输出的结果一样,如下 在这里插入图片描述 如果数据量很大不好一个个看,就用md5去比较,如下这样去比较 在这里插入图片描述 在这里插入图片描述 可以看到相等

那么接下来可以DFA了, 先找到轮,注入时机,状态矩阵

轮的寻找方法:先看子函数 在wbaes_encrypt_ecb下找子函数, 在这里插入图片描述 在这里插入图片描述 有很多子函数,我们先来看aes128_enc_wb_coff,aes128_enc_wb_xlc看看有没有走这里,老样子,还是先Interceptor.attach看看 然后写一个调用的函数process_web_aes()

// function wbaes_encrypt_ecb(){ // var module_base = Module.findBaseAddress("libcryptoDD.so") // var func_base = module_base.add(0x17BD4+1) // Interceptor.attach(func_base,{ // onEnter:function (args){ // this.in = args[0] // this.in_len = args[1].toInt32() //将指针转换成int32 // this.out = args[2] // this.mode = args[3].toInt32() // console.log("Input && len:",this.in_len," && mode:",this.mode) //打印输入 // console.log(hexdump(this.in,{length:this.in_len})) // }, // onLeave:function(){ // console.log("Output ....") // console.log(hexdump(this.out,{length:this.in_len})) // } // }) // } function hexToBytes(hex){ //十六进制转字节 for (var bytes = [],c=0;c var module_base = Module.findBaseAddress("libcryptoDD.so") var func_base = module_base.add(0x17BD4+1) var wb_aes_ecb_native = new NativeFunction(func_base,"int",["pointer","int","pointer","int"]) //参考frida api,第一个参数地址,第二个返回值,第三个参数 var inputPtr = Memory.alloc(0x60) //输入内存大小正好0x60 var inputData = hexToBytes(data) //输入的数据 Memory.writeByteArray(inputPtr,inputData) //数据写入地址 var outputPtr = Memory.alloc(0x60) //输出内存大小正好0x60 wb_aes_ecb_native(inputPtr,0x60,outputPtr,0) //wb_aes_ecb_native函数调用,参数对应 console.log(hexdump(outputPtr,{length:0x60})) //打印输出值 } function call_wb_aes(){ var data1 = "7b227061676554797065223a2232222c22746167496e646578223a22222c2261707076657273696f6e223a2234393330222c2270616765223a312c22726f7773223a31362c226272616e64436f6465223a224c4b303031227d07070707070707" invoke_wb_aes_ecb(data1) //调用 } //aes128_enc_wb_coff function aes128_enc_wb_coff(){ var baseAddr = Module.findBaseAddress("libcryptoDD.so") var func_addr = baseAddr.add(0x15320+1) Interceptor.attach(func_addr,{ onEnter:function (args){ console.log("Enter aes128_enc_wb_coff") } }) } //aes128_enc_wb_xlc function aes128_enc_wb_xlc(){ var baseAddr = Module.findBaseAddress("libcryptoDD.so") var func_addr = baseAddr.add(0x15C8C + 1) // thumb Interceptor.attach(func_addr,{ onEnter:function(args){ console.log("Enter aes128_enc_wb_xlc") } }) } function process_wb_aes(){ aes128_enc_wb_coff() aes128_enc_wb_xlc() call_wb_aes() }

在这里插入图片描述 可以看到总共两个子函数,只经过aes128_enc_wb_coff 那么我们进入aes128_enc_wb_coff看看 在这里插入图片描述 可以看到有Tyboxes和Txor说明是表查询部分,且进行异或运算

这里我们先要验证模式,虽然它写的是ecb命名,很有可能是欺骗我们 这里要介绍一段数字30313233343536373839616263646566 在这里插入图片描述 这串数字用来验证AES模块 因为AES是一个块加密,我们拿两块进行验证,结果一致是ecb,不一致就是别的模式

function invoke_wb_aes_ecb(data,len){ var module_base = Module.findBaseAddress("libcryptoDD.so") var func_base = module_base.add(0x17BD4+1) var wb_aes_ecb_native = new NativeFunction(func_base,"int",["pointer","int","pointer","int"]) //参考frida api,第一个参数地址,第二个返回值,第三个参数 var inputPtr = Memory.alloc(len) //输入内存大小正好0x60 var inputData = hexToBytes(data) //输入的数据 Memory.writeByteArray(inputPtr,inputData) //数据写入地址 var outputPtr = Memory.alloc(len) //输出内存大小正好0x60 wb_aes_ecb_native(inputPtr,len,outputPtr,0) //wb_aes_ecb_native函数调用,参数对应 console.log(hexdump(outputPtr,{length:len})) //打印输出值 } function call_wb_aes(){ var data1 = "7b227061676554797065223a2232222c22746167496e646578223a22222c2261707076657273696f6e223a2234393330222c2270616765223a312c22726f7773223a31362c226272616e64436f6465223a224c4b303031227d07070707070707" var data2 = "3031323334353637383961626364656630313233343536373839616263646566" var data3 = "30313233343536373839616263646566" invoke_wb_aes_ecb(data2,0x20) //调用 }

这里是两个块,所以长度写0x20 在这里插入图片描述 可以看到两个块加密后结果一样,说明是ecb模式 模式确认好之后,开始找轮 在这里插入图片描述 这是行位移的一个明显函数wbShiftRows(),传入的参数out就是我们的输出值,是我们要的状态矩阵 那么我们打印下,看看有几轮 修改: 将如下块改为1块,长度改为0x10 在这里插入图片描述 加入如下代码 在这里插入图片描述 效果如下 在这里插入图片描述 可以看到总共运行了十轮,那么说明是AES128

同时也看到正常的密文 e5af8b10 b0 f5 9c 0d 48 c1 45 91 5f c8 f6 a8 42 c4 d5 eb …H.E._…B…

然后进行DFA攻击 原理:需要在倒数后两轮找的一个区间内,找的一个完整的地方插入,也就是第9轮,找的一个子函数,也就是wbShiftRows()进行故障的注入

function wbShiftRows(){ var count = 0 var baseAddr = Module.findBaseAddress("libcryptoDD.so") var func_addr = baseAddr.add(0x14F98 + 1) // thumb Interceptor.attach(func_addr,{ onEnter:function(args){ count += 1 console.log("current count => ", count) if(count === 9){ args[0].writeS8(0x0) // args[0].add(randomNum(0,15)).writeS8(randomNum(0,0xff)) } } }) }

在这里插入图片描述 db8f45b0 2d f5 9c 0d 48 c1 45 eb 5f c8 c0 a8 42 78 d5 eb -…H.E._…Bx… 对比以下 在这里插入图片描述 可以看到不一样,并且四个字节不一样,符合DFA差分故障分析的一个结果

接下来批量注入,一般20次就出来了,我们这里注入200次,批量注入注意要随机注入,通过crack_aes_key.py脚本进行还原

// function wbaes_encrypt_ecb(){ // var module_base = Module.findBaseAddress("libcryptoDD.so") // var func_base = module_base.add(0x17BD4+1) // Interceptor.attach(func_base,{ // onEnter:function (args){ // this.in = args[0] // this.in_len = args[1].toInt32() //将指针转换成int32 // this.out = args[2] // this.mode = args[3].toInt32() // console.log("Input && len:",this.in_len," && mode:",this.mode) //打印输入 // console.log(hexdump(this.in,{length:this.in_len})) // }, // onLeave:function(){ // console.log("Output ....") // console.log(hexdump(this.out,{length:this.in_len})) // } // }) // } function hexToBytes(hex){ //十六进制转字节 for (var bytes = [],c=0;c var module_base = Module.findBaseAddress("libcryptoDD.so") var func_base = module_base.add(0x17BD4+1) var wb_aes_ecb_native = new NativeFunction(func_base,"int",["pointer","int","pointer","int"]) //参考frida api,第一个参数地址,第二个返回值,第三个参数 var inputPtr = Memory.alloc(len) //输入内存大小正好0x60 var inputData = hexToBytes(data) //输入的数据 Memory.writeByteArray(inputPtr,inputData) //数据写入地址 var outputPtr = Memory.alloc(len) //输出内存大小正好0x60 wb_aes_ecb_native(inputPtr,len,outputPtr,0) //wb_aes_ecb_native函数调用,参数对应 console.log(hexdump(outputPtr,{length:len})) //打印输出值 // var output = Memory.readByteArray(outputPtr,0x10) // console.log(bufferToHex(output)) } function call_wb_aes(){ var data1 = "7b227061676554797065223a2232222c22746167496e646578223a22222c2261707076657273696f6e223a2234393330222c2270616765223a312c22726f7773223a31362c226272616e64436f6465223a224c4b303031227d07070707070707" var data2 = "3031323334353637383961626364656630313233343536373839616263646566" var data3 = "30313233343536373839616263646566" invoke_wb_aes_ecb(data3,0x10) //调用 } //aes128_enc_wb_coff function aes128_enc_wb_coff(){ var baseAddr = Module.findBaseAddress("libcryptoDD.so") var func_addr = baseAddr.add(0x15320+1) Interceptor.attach(func_addr,{ onEnter:function (args){ console.log("Enter aes128_enc_wb_coff") } }) } //aes128_enc_wb_xlc function aes128_enc_wb_xlc(){ var baseAddr = Module.findBaseAddress("libcryptoDD.so") var func_addr = baseAddr.add(0x15C8C + 1) // thumb Interceptor.attach(func_addr,{ onEnter:function(args){ console.log("Enter aes128_enc_wb_xlc") } }) } function process_wb_aes(){ // wbShiftRows() // aes128_enc_wb_coff() // aes128_enc_wb_xlc() // call_wb_aes() // DFA crack wbShiftRows() for(var i=0;i if (arguments.length === 1) { return parseInt(Math.random() * minNum + 1, 10); } else if (arguments.length === 2) { return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10); } else { return 0; } } function wbShiftRows(){ var count = 0 var baseAddr = Module.findBaseAddress("libcryptoDD.so") var func_addr = baseAddr.add(0x14F98 + 1) // thumb Interceptor.attach(func_addr,{ onEnter:function(args){ count += 1 // console.log("current count => ", count) if(count%9 === 0){ // args[0].writeS8(0x0) args[0].add(randomNum(0,15)).writeS8(randomNum(0,0xff)) } } }) } function sleep(time) { var timeStamp = new Date().getTime(); var endTime = timeStamp + time; while (true) { if (new Date().getTime() > endTime) { return; } } }

在这里插入图片描述 在这里插入图片描述 这里费劲了,本来注释的这一块bufferToHex函数是可以用的,我这里用不了,报语法错,那么我hexdump下来之后手动整理如上图右侧notepad++ 然后将总共200行粘贴进来crack_aes_key.py 注意4行的b0f59c0d48c145915fc8f6a842c4d5eb是固定的,所以只要粘贴到红框那里就行,很整齐 在这里插入图片描述 在这里插入图片描述

在这里插入图片描述 在这里插入图片描述 可以看到出来了869D92BBB700D0D25BD9FD3E224B5DF2

还需要一部,因为我们得到的是第十轮的结果,需要给他倒推 在这里插入图片描述

那么就是K00了,64开头的是我们的结果

然后我们来验证 在这里插入图片描述 在这里插入图片描述 多出来一块内容,前面是一样的,后面的是多出来的,pkcs7,前面填满了就会填充后面,填充进去会计算,那么我们还原的密钥是正确的

还原密钥key完结

写在最后,小技巧 在这里插入图片描述

这里有个WBAES.c,很明显AES的特征 接下来看导出这边 PKCS5Padding一般是使用了DES和AES中,基本定位到了算法的区间



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有