hws_winter2022-re
一.Babyre
程序入口处调用了一个check函数,但这个是假的检验
跟进去发现做了一些简单操作,尝试了几次但逆不出来,就到别的文件里看了看,结果发现还有一段解密
读取了enc文件,并且进行解密,替换class.dex
将enc文件从apk中解压出来,然后解密
package software; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; public class Activity { public static void main(String[] args)throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { try { InputStream open = new FileInputStream("C:\\Users\\Lenovo\\Desktop\\enc"); byte[] bArr = new byte[open.available()]; open.read(bArr); for (int i = 0; i < bArr.length; i++) { bArr[i] = (byte) (bArr[i] ^ 52); } File dir = new File("C:\\Users\\Lenovo\\Desktop"); File file = new File(dir.getAbsolutePath() + File.separator + "classes.dex"); if (!file.exists()) { file.createNewFile(); } FileOutputStream fileOutputStream = new FileOutputStream(file); fileOutputStream.write(bArr); fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
解密完发现是AES+base64加密,直接使用在线网站解密
二.Easyre
ida进入main函数,发现把输入分成了四部分,每部分进行相同的处理
跟进fun函数,发现是改的xtea,修改了delta和sum的运算
找到key和data解密即可
#include <stdio.h> #include <stdint.h> void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0=v[0], v1=v[1], delta=0x61C88647, sum=0; for(i = 0;i < 32;i++) { sum -= 0x61C88647; } for (i=0; i < num_rounds; i++) { v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); sum += delta; v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); } v[0]=v0; v[1]=v1; } int main() { //0x34,0x9b,0xb2,0xc0,0x6a,0xaf,0x30,0xef, //0x38,0xb2,0xcc,0x98,0x95,0xf1,0xb6,0x85, //0x85,0x6,0x48,0xa2,0x59,0x9b,0x3d,0xa6, //0x1e,0xc7,0x91,0xf1,0x7b,0x76,0x90,0x67 uint32_t v[2]={0xc0b29b34,0xef30af6a}; uint32_t v1[2]={0x98ccb238,0x85b6f195}; uint32_t v2[2]={0xa2480685,0xa63d9b59}; uint32_t v3[2]={0xf191c71e,0x6790767b}; uint32_t const k[4]={0x29,0x4823,0x18be,0x6784}; unsigned int r=32;//num_rounds建议取值为32 // v为要加密的数据是两个32位无符号整数 // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位 printf("解密前的数据:%x %x\n",v[0],v[1]); decipher(r, v, k); printf("解密后的数据:%x %x\n",v[0],v[1]); printf("解密前的数据:%x %x\n",v1[0],v1[1]); decipher(r, v1, k); printf("解密后的数据:%x %x\n",v1[0],v1[1]); printf("解密前的数据:%x %x\n",v2[0],v2[1]); decipher(r, v2, k); printf("解密后的数据:%x %x\n",v2[0],v2[1]); printf("解密前的数据:%x %x\n",v3[0],v3[1]); decipher(r, v3, k); printf("解密后的数据:%x %x\n",v3[0],v3[1]); uint32_t flag[32] = {0x39,0x63,0x33,0x32,0x30,0x36,0x61,0x33,0x39,0x34,0x32,0x65,0x30,0x38,0x33,0x35,0x64,0x61,0x62,0x61,0x61,0x31,0x38,0x32,0x31,0x32,0x38,0x64,0x36,0x30,0x62,0x63}; for(int i = 0;i < 32;i++) { printf("%c",flag[i]); } return 0; }
三.repy
主流程分为三部分,第一部分是解密一个10位数字,第二部分是解密一个字符串,第三部分解密py文件,前两部分都加了ollvm混淆,第三部分解密的秘钥要用到第二部分解的结果,尝试用平坦化程序,但是失败了,后来又试了D810和OPBP,但是因为环境问题都失败了,所以前两部分是硬调的,花了很多时间
第一部分的校验,对十位数每一位的个数和这个十位数进行比较,爆破不出来,最后是猜出来的,也可以用从第二部分逆推
s = [0]*10 s1 = [0]*10 def check(i): tmp = i for j in range(0,10): x = (tmp+10) % 10 s[x] += 1 s1[9 - j] = x tmp = int(tmp/10) print(s) print(s1) x = 0 for k in range(0,10): if (s[k] == s1[k]): x += 1 else: x = 0 if (x == 10): print(i) print(check(6210001000))
第二部分的校验,其实直接找到最后一处md5校验即可,这个md5值在有些网站可以直接解出来,正常做尝试用z3解出来,但是也没解出来
from z3 import * import hashlib s = Solver() input_0,input_1,input_2,input_3,input_4,input_5,input_6,input_7,input_8,input_9,input_10,input_11,input_12,input_13,input_14,input_15 = Ints('input_0 input_1 input_2 input_3 input_4 input_5 input_6 input_7 input_8 input_9 input_10 input_11 input_12 input_13 input_14 input_15') s.add(Distinct(input_0,input_1,input_2,input_3,input_4,input_5,input_6,input_7,input_8,input_9,input_10,input_11,input_12,input_13,input_14,input_15)) s.add(input_0+input_1+input_2+input_3+input_4+input_5+input_6+input_7+input_8+input_9+input_10+input_11+input_12+input_13+input_14+input_15==120) s.add((input_0+input_1+input_2+input_3)==(input_4+input_5+input_6+input_7)) s.add((input_4+input_5+input_6+input_7)==(input_8+input_9+input_10+input_11)) s.add((input_8+input_9+input_10+input_11)==(input_12+input_13+input_14+input_15)) s.add(input_0+input_4+input_8+input_12==30) s.add(input_0+input_5+input_10+input_15==30) s.add(input_0+input_5+input_10+input_15==input_3+input_6+input_9+input_12) s.add(input_0>=0) s.add(input_1>=0) s.add(input_2>=0) s.add(input_3>=0) s.add(input_4>=0) s.add(input_5>=0) s.add(input_6>=0) s.add(input_7>=0) s.add(input_8>=0) s.add(input_9>=0) s.add(input_10>=0) s.add(input_11>=0) s.add(input_12>=0) s.add(input_13>=0) s.add(input_14>=0) s.add(input_15>=0) s.add(input_0+input_3+input_12+input_15==30) s.add(input_5+input_6+input_9+input_10==30) s.add(input_1+input_2+input_13+input_14==30) s.add(input_4+input_8+input_7+input_11==30) s.add(input_0+input_2+input_8+input_10==30) s.add(input_5+input_7+input_13+input_15==30) s.add(input_0+input_1+input_4+input_5==30) s.add(input_2+input_3+input_6+input_7==30) s.add(input_8+input_9+input_12+input_13==30) s.add(input_10+input_11+input_14+input_15==30) while s.check() == sat: arr=[0]*16 model = s.model() #print(model) s.add(Or([d() != model[d] for d in model])) for d in model: #print(str(d),":",model[d],end=',') if (str(d) == "input_0"): arr[0] = model[d].as_long() elif (str(d) == "input_1"): arr[1] = model[d].as_long() elif (str(d) == "input_2"): arr[2] = model[d].as_long() elif (str(d) == "input_3"): arr[3] = model[d].as_long() elif (str(d) == "input_4"): arr[4] = model[d].as_long() elif (str(d) == "input_5"): arr[5] = model[d].as_long() elif (str(d) == "input_6"): arr[6] = model[d].as_long() elif (str(d) == "input_7"): arr[7] = model[d].as_long() elif (str(d) == "input_8"): arr[8] = model[d].as_long() elif (str(d) == "input_9"): arr[9] = model[d].as_long() elif (str(d) == "input_10"): arr[10] = model[d].as_long() elif (str(d) == "input_11"): arr[11] = model[d].as_long() elif (str(d) == "input_12"): arr[12] = model[d].as_long() elif (str(d) == "input_13"): arr[13] = model[d].as_long() elif (str(d) == "input_14"): arr[14] = model[d].as_long() elif (str(d) == "input_15"): arr[15] = model[d].as_long() array_40 = [0x63,0x74,0x55,0x33,0x4f,0x67,0x64,0x6f,0x40,0x34,0x72,0x61,0x30,0x79,0x44,0x6e] s1 = "" for i in arr: s1 += chr(array_40[i]) s1+=chr(0) m = hashlib.md5() #yOUar3g0oD@tc4nd m.update(s1.encode('utf-8')) if (s1 == "yOUar3g0oD@tc4nd"): print(s1) if (m.hexdigest().upper() == "E324486F7B08234DEAFFAFCD1DFA0371"): print(s1)
第三部分,这里直接参考的别的师傅平坦化完的结果,对secret.bin进行了AES解密
然后得到一个不完整的pyc文件,根据题目的提示,得知pyc的版本为3.8,先给pyc文件添加magic number,然后修改花指令6e 24,改为6e 00,最后修改花指令后面的36字节为nop(0x09),之后就可以用python的dis模块进行反汇编,但是卡在这里了,后面也没法做了