NSSCTF Round#18 RE WP 完整复现

1. GenshinWishSimulator

恶搞原神抽卡模拟器

看到软件的界面,大致有三种思路:

  1. 修改石头数量一直抽,如果概率正常肯定能抽到(但是估计设置的概率是0)
  2. 在源码里找flag的数据
  3. 把抽卡概率改成100%直接抽出来

Unity逆向,根据经验应该dnspy查看Assembly-CSharp.dll

上来看到SM4,但是别急

Gacha是抽卡的意思,这里应该是抽卡的主逻辑

Gift内可以看到主要逻辑,以array作为key"NSSCTF_2024_R#18" 为偏移(IV),用SM4/CBC/PKCS7Padding模式加密input数组,最后保存字符串到flag对象里

也就是说如果静态分析直接求flag就是一个SM4_CBC的解密过程,检查一下发现SM4没有经过魔改,应该容易解出

a. 静态分析解密

只要得到SM4解密需要的几个重要参数,再结合在线工具就能得出答案

  • 密文就是input数组

  • 密钥key是array数组,其计算方法很明显

然后找bucket数组,在Check()函数里发现了一堆方程,用于验证bucket数组的值

z3算一下,SM4的密钥长度只有16字节,设置变量类型时用Int,BitVec会因为位数多导致解出结果过大

from z3 import *
from Crypto.Util.number import *
bucket = [Int("bucket[%d]" % i) for i in range(16)]
s = Solver()
s.add(bucket[0] * 40 + bucket[1] * 65 + bucket[2] * -53 + bucket[3] * 70 + bucket[4] * -84 + bucket[5] * -38 + bucket[6] * 94 + bucket[7] * -39 + bucket[8] * -91 + bucket[9] * -35 + bucket[10] * 54 + bucket[11] * 17 + bucket[12] * 45 + bucket[13] * 92 + bucket[14] * -29 + bucket[15] * 61 == 3004)
s.add(bucket[0] * -15 + bucket[1] * 74 + bucket[2] * -89 + bucket[3] * -82 + bucket[4] * -92 + bucket[5] * 27 + bucket[6] * 21 + bucket[7] * -24 + bucket[8] * -82 + bucket[9] * -58 + bucket[10] * -36 + bucket[11] * 64 + bucket[12] * -49 + bucket[13] * -22 + bucket[14] * 59 + bucket[15] * -47 == -674)
s.add(bucket[0] * 67 + bucket[1] * -23 + bucket[2] * 63 + bucket[3] * -38 + bucket[4] * -32 + bucket[5] * 61 + bucket[6] * -71 + bucket[7] * 49 + bucket[8] * 83 + bucket[9] * -92 + bucket[10] * -16 + bucket[11] * 65 + bucket[12] * -22 + bucket[13] * 12 + bucket[14] * -85 + bucket[15] * 74 == 945 )
s.add(bucket[0] * -49 + bucket[1] * 48 + bucket[2] * -11 + bucket[3] * 20 + bucket[4] * -14 + bucket[5] * 92 + bucket[6] * -19 + bucket[7] * 32 + bucket[8] * 64 + bucket[9] * -77 + bucket[10] * 49 + bucket[11] * -19 + bucket[12] * 72 + bucket[13] * -64 + bucket[14] * 85 + bucket[15] * 54 == 1721)
s.add(bucket[0] * 36 + bucket[1] * -21 + bucket[2] * -59 + bucket[3] * -54 + bucket[4] * -96 + bucket[5] * -81 + bucket[6] * -33 + bucket[7] * 31 + bucket[8] * -41 + bucket[9] * -70 + bucket[10] * -27 + bucket[11] * 24 + bucket[12] * 95 + bucket[13] * -61 + bucket[14] * -17 + bucket[15] * -52 == -2198)
s.add(bucket[0] * 78 + bucket[1] * -62 + bucket[2] * 70 + bucket[3] * -69 + bucket[4] * 38 + bucket[5] * 90 + bucket[6] * -52 + bucket[7] * 41 + bucket[8] * 63 + bucket[9] * -65 + bucket[10] * -15 + bucket[11] * 59 + bucket[12] * -31 + bucket[13] * 54 + bucket[14] * 33 + bucket[15] * -57 == -1833)
s.add(bucket[0] * 56 + bucket[1] * 75 + bucket[2] * 71 + bucket[3] * 78 + bucket[4] * -39 + bucket[5] * -84 + bucket[6] * 55 + bucket[7] * 54 + bucket[8] * -12 + bucket[9] * -57 + bucket[10] * 32 + bucket[11] * -19 + bucket[12] * 13 + bucket[13] * -83 + bucket[14] * 11 + bucket[15] * -67 == 829)
s.add(bucket[0] * 10 + bucket[1] * -97 + bucket[2] * 56 + bucket[3] * -61 + bucket[4] * 45 + bucket[5] * -22 + bucket[6] * 33 + bucket[7] * 81 + bucket[8] * 32 + bucket[9] * 49 + bucket[10] * -19 + bucket[11] * -18 + bucket[12] * 80 + bucket[13] * -98 + bucket[14] * 79 + bucket[15] * -36 == -2551)
s.add(bucket[0] * 24 + bucket[1] * -61 + bucket[2] * 91 + bucket[3] * 93 + bucket[4] * 76 + bucket[5] * 54 + bucket[6] * -33 + bucket[7] * -29 + bucket[8] * -72 + bucket[9] * 20 + bucket[10] * 48 + bucket[11] * 79 + bucket[12] * 76 + bucket[13] * 68 + bucket[14] * 51 + bucket[15] * 25 == 2996)
s.add(bucket[0] * -83 + bucket[1] * -77 + bucket[2] * -64 + bucket[3] * -38 + bucket[4] * -13 + bucket[5] * -85 + bucket[6] * 33 + bucket[7] * -76 + bucket[8] * 27 + bucket[9] * 14 + bucket[10] * -79 + bucket[11] * -63 + bucket[12] * -78 + bucket[13] * 53 + bucket[14] * -73 + bucket[15] * 61 == -2315)
s.add(bucket[0] * 84 + bucket[1] * -67 + bucket[2] * 57 + bucket[3] * 26 + bucket[4] * 94 + bucket[5] * 20 + bucket[6] * -71 + bucket[7] * -88 + bucket[8] * -28 + bucket[9] * -13 + bucket[10] * -40 + bucket[11] * 76 + bucket[12] * -14 + bucket[13] * 33 + bucket[14] * 76 + bucket[15] * -75 == -150)
s.add(bucket[0] * -60 + bucket[1] * 88 + bucket[2] * -66 + bucket[3] * -72 + bucket[4] * 41 + bucket[5] * 49 + bucket[6] * 48 + bucket[7] * -77 + bucket[8] * -42 + bucket[9] * 25 + bucket[10] * -50 + bucket[11] * -84 + bucket[12] * 40 + bucket[13] * 50 + bucket[14] * -83 + bucket[15] * -27 == -1919)
s.add(bucket[0] * -16 + bucket[1] * -53 + bucket[2] * -21 + bucket[3] * -44 + bucket[4] * 26 + bucket[5] * -56 + bucket[6] * -90 + bucket[7] * -93 + bucket[8] * -73 + bucket[9] * 48 + bucket[10] * 15 + bucket[11] * -43 + bucket[12] * -61 + bucket[13] * -24 + bucket[14] * 71 + bucket[15] * 67 == -1199)
s.add(bucket[0] * 55 + bucket[1] * -34 + bucket[2] * -22 + bucket[3] * 60 + bucket[4] * 93 + bucket[5] * -95 + bucket[6] * 50 + bucket[7] * 36 + bucket[8] * -48 + bucket[9] * -26 + bucket[10] * -94 + bucket[11] * -35 + bucket[12] * 21 + bucket[13] * -27 + bucket[14] * 91 + bucket[15] * -76 == -1163)
s.add(bucket[0] * 64 + bucket[1] * -50 + bucket[2] * -23 + bucket[3] * -70 + bucket[4] * -78 + bucket[5] * 34 + bucket[6] * 26 + bucket[7] * 64 + bucket[8] * -72 + bucket[9] * 10 + bucket[10] * -96 + bucket[11] * 61 + bucket[12] * -15 + bucket[13] * 31 + bucket[14] * 36 + bucket[15] * 50 == -266)
s.add(bucket[0] * -27 + bucket[1] * 86 + bucket[2] * -61 + bucket[3] * 89 + bucket[4] * -53 + bucket[5] * 10 + bucket[6] * -42 + bucket[7] * 92 + bucket[8] * -48 + bucket[9] * 13 + bucket[10] * 84 + bucket[11] * -71 + bucket[12] * 93 + bucket[13] * 54 + bucket[14] * -69 + bucket[15] * -30 == 892)
if s.check() == sat:s = s.model()
print(s)
'''
[bucket[15] = 16,bucket[13] = 0,bucket[10] = 1,bucket[11] = 17,bucket[14] = 2,bucket[4] = 2,bucket[2] = 1,bucket[1] = 14,bucket[5] = 1,bucket[7] = 0,bucket[12] = 2,bucket[6] = 1,bucket[3] = 17,bucket[8] = 2,bucket[9] = 4,bucket[0] = 1]'''

然后每个+53就可以得到array也就是key了

  • IV很显然是"NSSCTF_2024_R#18"

用脚本转化一下形式使得数据容易套进在线工具里


#genshin wp
enc = [145,118,31,48,103,110,52,82,113,19,83,44,176,130,138,129,115,110,38,10,42,100,193,105,125,61,7,229,230,180,68,133,11,177,210,122,161,60,129,140,16,45,224,83,238,0,213,157,121,193,135,197,87,118,155,110,90,91,30,158,248,44,95,215,166,247,239,43,228,114,227,146,164,137,111,79,143,17,132,14]
print("enc: ")
for i in enc:  print(hex(i), end=' ')
print("\n")
from z3 import *
from Crypto.Util.number import *
bucket = [Int("bucket[%d]" % i) for i in range(16)]
s = Solver()
s.add(bucket[0] * 40 + bucket[1] * 65 + bucket[2] * -53 + bucket[3] * 70 + bucket[4] * -84 + bucket[5] * -38 + bucket[6] * 94 + bucket[7] * -39 + bucket[8] * -91 + bucket[9] * -35 + bucket[10] * 54 + bucket[11] * 17 + bucket[12] * 45 + bucket[13] * 92 + bucket[14] * -29 + bucket[15] * 61 == 3004)
s.add(bucket[0] * -15 + bucket[1] * 74 + bucket[2] * -89 + bucket[3] * -82 + bucket[4] * -92 + bucket[5] * 27 + bucket[6] * 21 + bucket[7] * -24 + bucket[8] * -82 + bucket[9] * -58 + bucket[10] * -36 + bucket[11] * 64 + bucket[12] * -49 + bucket[13] * -22 + bucket[14] * 59 + bucket[15] * -47 == -674)
s.add(bucket[0] * 67 + bucket[1] * -23 + bucket[2] * 63 + bucket[3] * -38 + bucket[4] * -32 + bucket[5] * 61 + bucket[6] * -71 + bucket[7] * 49 + bucket[8] * 83 + bucket[9] * -92 + bucket[10] * -16 + bucket[11] * 65 + bucket[12] * -22 + bucket[13] * 12 + bucket[14] * -85 + bucket[15] * 74 == 945 )
s.add(bucket[0] * -49 + bucket[1] * 48 + bucket[2] * -11 + bucket[3] * 20 + bucket[4] * -14 + bucket[5] * 92 + bucket[6] * -19 + bucket[7] * 32 + bucket[8] * 64 + bucket[9] * -77 + bucket[10] * 49 + bucket[11] * -19 + bucket[12] * 72 + bucket[13] * -64 + bucket[14] * 85 + bucket[15] * 54 == 1721)
s.add(bucket[0] * 36 + bucket[1] * -21 + bucket[2] * -59 + bucket[3] * -54 + bucket[4] * -96 + bucket[5] * -81 + bucket[6] * -33 + bucket[7] * 31 + bucket[8] * -41 + bucket[9] * -70 + bucket[10] * -27 + bucket[11] * 24 + bucket[12] * 95 + bucket[13] * -61 + bucket[14] * -17 + bucket[15] * -52 == -2198)
s.add(bucket[0] * 78 + bucket[1] * -62 + bucket[2] * 70 + bucket[3] * -69 + bucket[4] * 38 + bucket[5] * 90 + bucket[6] * -52 + bucket[7] * 41 + bucket[8] * 63 + bucket[9] * -65 + bucket[10] * -15 + bucket[11] * 59 + bucket[12] * -31 + bucket[13] * 54 + bucket[14] * 33 + bucket[15] * -57 == -1833)
s.add(bucket[0] * 56 + bucket[1] * 75 + bucket[2] * 71 + bucket[3] * 78 + bucket[4] * -39 + bucket[5] * -84 + bucket[6] * 55 + bucket[7] * 54 + bucket[8] * -12 + bucket[9] * -57 + bucket[10] * 32 + bucket[11] * -19 + bucket[12] * 13 + bucket[13] * -83 + bucket[14] * 11 + bucket[15] * -67 == 829)
s.add(bucket[0] * 10 + bucket[1] * -97 + bucket[2] * 56 + bucket[3] * -61 + bucket[4] * 45 + bucket[5] * -22 + bucket[6] * 33 + bucket[7] * 81 + bucket[8] * 32 + bucket[9] * 49 + bucket[10] * -19 + bucket[11] * -18 + bucket[12] * 80 + bucket[13] * -98 + bucket[14] * 79 + bucket[15] * -36 == -2551)
s.add(bucket[0] * 24 + bucket[1] * -61 + bucket[2] * 91 + bucket[3] * 93 + bucket[4] * 76 + bucket[5] * 54 + bucket[6] * -33 + bucket[7] * -29 + bucket[8] * -72 + bucket[9] * 20 + bucket[10] * 48 + bucket[11] * 79 + bucket[12] * 76 + bucket[13] * 68 + bucket[14] * 51 + bucket[15] * 25 == 2996)
s.add(bucket[0] * -83 + bucket[1] * -77 + bucket[2] * -64 + bucket[3] * -38 + bucket[4] * -13 + bucket[5] * -85 + bucket[6] * 33 + bucket[7] * -76 + bucket[8] * 27 + bucket[9] * 14 + bucket[10] * -79 + bucket[11] * -63 + bucket[12] * -78 + bucket[13] * 53 + bucket[14] * -73 + bucket[15] * 61 == -2315)
s.add(bucket[0] * 84 + bucket[1] * -67 + bucket[2] * 57 + bucket[3] * 26 + bucket[4] * 94 + bucket[5] * 20 + bucket[6] * -71 + bucket[7] * -88 + bucket[8] * -28 + bucket[9] * -13 + bucket[10] * -40 + bucket[11] * 76 + bucket[12] * -14 + bucket[13] * 33 + bucket[14] * 76 + bucket[15] * -75 == -150)
s.add(bucket[0] * -60 + bucket[1] * 88 + bucket[2] * -66 + bucket[3] * -72 + bucket[4] * 41 + bucket[5] * 49 + bucket[6] * 48 + bucket[7] * -77 + bucket[8] * -42 + bucket[9] * 25 + bucket[10] * -50 + bucket[11] * -84 + bucket[12] * 40 + bucket[13] * 50 + bucket[14] * -83 + bucket[15] * -27 == -1919)
s.add(bucket[0] * -16 + bucket[1] * -53 + bucket[2] * -21 + bucket[3] * -44 + bucket[4] * 26 + bucket[5] * -56 + bucket[6] * -90 + bucket[7] * -93 + bucket[8] * -73 + bucket[9] * 48 + bucket[10] * 15 + bucket[11] * -43 + bucket[12] * -61 + bucket[13] * -24 + bucket[14] * 71 + bucket[15] * 67 == -1199)
s.add(bucket[0] * 55 + bucket[1] * -34 + bucket[2] * -22 + bucket[3] * 60 + bucket[4] * 93 + bucket[5] * -95 + bucket[6] * 50 + bucket[7] * 36 + bucket[8] * -48 + bucket[9] * -26 + bucket[10] * -94 + bucket[11] * -35 + bucket[12] * 21 + bucket[13] * -27 + bucket[14] * 91 + bucket[15] * -76 == -1163)
s.add(bucket[0] * 64 + bucket[1] * -50 + bucket[2] * -23 + bucket[3] * -70 + bucket[4] * -78 + bucket[5] * 34 + bucket[6] * 26 + bucket[7] * 64 + bucket[8] * -72 + bucket[9] * 10 + bucket[10] * -96 + bucket[11] * 61 + bucket[12] * -15 + bucket[13] * 31 + bucket[14] * 36 + bucket[15] * 50 == -266)
s.add(bucket[0] * -27 + bucket[1] * 86 + bucket[2] * -61 + bucket[3] * 89 + bucket[4] * -53 + bucket[5] * 10 + bucket[6] * -42 + bucket[7] * 92 + bucket[8] * -48 + bucket[9] * 13 + bucket[10] * 84 + bucket[11] * -71 + bucket[12] * 93 + bucket[13] * 54 + bucket[14] * -69 + bucket[15] * -30 == 892)
if s.check() == sat:s = s.model()
print(s)
bucket[15] = 16
bucket[13] = 0
bucket[10] = 1
bucket[11] = 17
bucket[14] = 2
bucket[4] = 2
bucket[2] = 1
bucket[1] = 14
bucket[5] = 1
bucket[7] = 0
bucket[12] = 2
bucket[6] = 1
bucket[3] = 17
bucket[8] = 2
bucket[9] = 4
bucket[0] = 1
array = [0]*16
print(bucket)
for i in range(len(bucket)):array[i] = bucket[i] + 53
key = ''
for i in array:key += chr(i)
print("key:",key)
#iv = "NSSCTF_2024_R#18"  
'''
enc: 
0x91 0x76 0x1f 0x30 0x67 0x6e 0x34 0x52 0x71 0x13 0x53 0x2c 0xb0 0x82 0x8a 0x81 0x73 0x6e 0x26 0xa 0x2a 0x64 0xc1 0x69 0x7d 0x3d 0x7 0xe5 0xe6 0xb4 0x44 0x85 0xb 0xb1 0xd2 0x7a 0xa1 0x3c 0x81 0x8c 0x10 0x2d 0xe0 0x53 0xee 0x0 0xd5 0x9d 0x79 0xc1 0x87 0xc5 0x57 0x76 0x9b 0x6e 0x5a 0x5b 0x1e 0x9e 0xf8 0x2c 0x5f 0xd7 0xa6 0xf7 0xef 0x2b 0xe4 0x72 0xe3 0x92 0xa4 0x89 0x6f 0x4f 0x8f 0x11 0x84 0xe[bucket[15] = 16,bucket[13] = 0,bucket[10] = 1,bucket[11] = 17,bucket[14] = 2,bucket[4] = 2,bucket[2] = 1,bucket[1] = 14,bucket[5] = 1,bucket[7] = 0,bucket[12] = 2,bucket[6] = 1,bucket[3] = 17,bucket[8] = 2,bucket[9] = 4,bucket[0] = 1]
[1, 14, 1, 17, 2, 1, 1, 0, 2, 4, 1, 17, 2, 0, 2, 16]
key: 6C6F7665796F757E
'''

几个参数注意一下就可以了

b. 修改逻辑(动态分析)

但考虑修改抽卡概率的方法可能更方便

尝试在这里下断点但是直接抽卡不运行这一段代码,无法在这里断下来

只能修改代码逻辑

我们找到这个GetRandomItem函数,发现要经过Check才可以出发生成flag的Gift函数

即bucket必须满足上面我们z3解出来的那个值,我们直接把bucket赋值

在GachaHistoryBucket中,修改GetBucket()或者直接修改bucket初始值都可以

修改初始值的话记得选择编辑类,不然编译不通过

抽取的部分也要改一下

我们要的flag在这里,修改一下使得它必然被执行

保存一下运行

OCR提取一下文字,少数几个错字自己改一下

2. NewYearGift

IDA打开来没什么头绪,不过似乎和dll有关

尝试从程序中提取dll文件

这里用静态提取即可

用010Editor打开,搜索PE文件头,开头有一个中间有一个,应该是打包在exe里的dll

复制MZ到结尾的部分

后面可以看到一些相关的字段

新建一个十六进制文件粘贴进去

然后就可以在dnspy分析,主逻辑很清晰

比较简便的方法就是把Program的代码都抠出来,去掉if判断的部分直接编译

3. SenpaiCalc

IDA反编译非常难看,dnspy、ILspy都不行,因为使用了NativeAOT编译

NativeAOT 是 dotnet 新增加的运行模式,自.NET7之后便开始支持。其中,AOT是 Ahead-Of-Time 的缩写,和 JIT 边运行边编译不同,NativeAOT 直接将 IL 代码编译为目标平台的机器码发布,它的文件大小、启动时间和内存占用均比 JIT 低。但与之相对的是,逆向难度也要比以前更加高,以往使用DnSpy、ILSpy等工具在这里通通失效。因此,在没有更好的针对性逆向工具诞生之前,IDA仍然是优选。

不过题目提供了pdb文件,可以恢复符号表

尽管如此,符号表依然是依托答辩

搜一下Main,看一下相邻地址的函数

就可疑的函数名查看,最终锁定SenpaiCalc_Program__Senpai函数

还是一坨,不过只关注if判断部分,只是将高低四位交换

密文在SenpaiCalc__PrivateImplementationDetails____278942435594DEEBEFE7E3ACD891A0F13784E54403702D22BEF1387DEB336845

脚本就很简单了

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{char enc[] = { 0xE4, 0x35, 0x35, 0x34, 0x45, 0x64, 0xB7, 0x63, 0x37, 0xE6,0x76, 0x93, 0x56, 0x96, 0x93, 0xB6, 0x93, 0x93, 0x03, 0x93,0xE6, 0x33, 0x36, 0x17, 0x53, 0xE6, 0x23, 0x27, 0x37, 0xC6,0x76, 0x97, 0x23, 0x33, 0x86, 0x87, 0xB6, 0x63, 0xC6, 0xF6,0x33, 0x86, 0x56, 0xC6, 0x23, 0x03, 0xD6, 0x86, 0xC6, 0x96,0x67, 0x33, 0xE6, 0x07, 0x96, 0x47, 0x23, 0x57, 0x83, 0x97,0x26, 0xB6, 0x43, 0xD7 };char flag[65];int i;for (i = 0; i < 64; i++){flag[i] = (((enc[i] & 0b1111) << 4) | ((enc[i] & 0b11110000) >> 4));}printf("%s", flag);
}
//NSSCTF{6sng9ei9k9909n3cq5n2rslgy23hxk6lo3hel20mhliv3npit2u8ybk4}

4. 炒鸡常见的编码哇

主逻辑如图,类似魔改base64

类似rc4初始化的函数,实际上只是打乱了bin内容

然后用爆破逆向

#swbase wp
enc = [0xE2, 0xF7, 0xD3, 0xE2, 0xC8, 0xB4, 0xD8, 0xC5, 0xCF, 0xB4, 0xE7, 0xEE, 0xE1, 0xD9, 0xF1, 0xEF, 0xCB, 0xEB, 0xD9, 0xC9, 0xCE, 0xC5, 0xD9, 0xE5, 0xCC, 0xB7, 0xD1, 0xED, 0xE0, 0xB4, 0xF1, 0xEE, 0xE0, 0xE7, 0xD2, 0xF6, 0xCB, 0xF3, 0xC9, 0xF3, 0xD3, 0xD5, 0xEF]
map = [0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xAA, 0xAE]v1 = []
for i in enc:v1.append(map.index(i)) #计算索引
print("v1:",v1)bins = []
for i in v1:bins.append(bin(i)[2:].zfill(6)) #十进制转二进制,去掉开头的0b,补齐到6位
print("bins:",bins)res = ""
for i in bins:for j in range(0b111111):tem = list(bin(j)[2:].zfill(6))v3 = 0v4 = 0for k in range(0,256,2):v3 = (k + 1)%256v4 = (v3 + v4 + 1) % 256tem[v3 % 6],tem[v4 % 6] = tem[v4 % 6],tem[v3 % 6]d = "".join(tem)if d == i:res += bin(j)[2:].zfill(6)break
print("res:",res)
#爆破求打乱前的二进制数组binflag = [res[i:i+8] for i in range(0, len(res), 8)]
print("binflag:",binflag)
flag = ''
for i in binflag:flag += chr(int(i,2))
print("flag:",flag)
'''
v1: [28, 49, 19, 28, 8, 57, 24, 5, 15, 57, 33, 40, 27, 25, 43, 41, 11, 37, 25, 9, 14, 5, 25, 31, 12, 60, 17, 39, 26, 57, 43, 40, 26, 33, 18, 48, 11, 45, 9, 45, 19, 21, 41]
bins: ['011100', '110001', '010011', '011100', '001000', '111001', '011000', '000101', '001111', '111001', '100001', '101000', '011011', '011001', '101011', '101001', '001011', '100101', '011001', '001001', '001110', '000101', '011001', '011111', '001100', '111100', '010001', '100111', '011010', '111001', '101011', '101000', '011010', '100001', '010010', '110000', '001011', '101101', '001001', '101101', '010011', '010101', '101001']
res: 010011100101001101010011010000110101010001000110011110110101100100110000011101010101111100110100011100100110010101010100011010000110010101011111010010110011000101101110011001110101111100110000011001100100001001100001011100110110010100110110001101000111110100
binflag: ['01001110', '01010011', '01010011', '01000011', '01010100', '01000110', '01111011', '01011001', '00110000', '01110101', '01011111', '00110100', '01110010', '01100101', '01010100', '01101000', '01100101', '01011111', '01001011', '00110001', '01101110', '01100111', '01011111', '00110000', '01100110', '01000010', '01100001', '01110011', '01100101', '00110110', '00110100', '01111101', '00']
flag: NSSCTF{Y0u_4reThe_K1ng_0fBase64}
'''

5. EzADVM

主逻辑在libezadvm.so里,需要解压apk

用IDA分析,是vm,但是并没有模拟到汇编层面

提出opcode打印指令,大部分是循环

opcode = [0x01, 0x01, 0x21, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x99, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0x53, 0x57, 0x44, 0x44, 0xBF, 0xBB, 0xBF, 0xBB, 0x99, 0x53, 0x57, 0x44, 0x44, 0x53, 0x57, 0x44, 0x44, 0x88, 0xFF, 0x53, 0x57, 0x44, 0x44]for i in opcode:match i:case 0xA1:print("enc[i - 1] = v25 & v22")case 0xC3:print("v22 = v17 | v18")case 0xB2:print("v23 = ~v17")case 0xE5:print("v24 = ~v18")case 0xF1:print("v17 = input[i]")print("v18 = input[++i]")case 0xD4:print("v25 = v24 | v23")case 0xBF:print("v6 = i++")print("v21[0] = enc[v6]")case 0x99:print("i = 0")case 0xBB:print("enc[i - 1] = i + v21[0] - 1")
'''
v17 = input[i]
v18 = input[++i]
v22 = v17 | v18
v23 = ~v17
v24 = ~v18
v25 = v24 | v23
enc[i - 1] = v25 & v22    
#((~input[i])|(~input[i+1]))&((input[i])|(input[i+1])) 相当于input[i]^input[i+1]
…………
i = 0
v6 = i++
v21[0] = enc[v6]
enc[i - 1] = i + v21[0] - 1       #enc[i - 1] = i + enc[i] - 1
…………
i = 0
'''

主要逻辑就是一个 ((~input[i])|(~input[i+1]))&((input[i])|(input[i+1])) 相当于input[i]^input[i+1]以及 +i的操作

enc = [  0x1D, 0x01, 0x12, 0x1A, 0x16, 0x42, 0x39, 0x0F, 0x38, 0x09, 0x13, 0x31, 0x28, 0x38, 0x67, 0x6E, 0x1B, 0x61, 0x7C, 0x24, 0x1F, 0x47, 0x44, 0x81, 0x6A, 0x2C, 0x6D, 0x2B, 0x2C, 0x2D, 0x6A, 0x9C]
for i in range(32):enc[i] -= i
print(enc)
for i in range(30,-1,-1):enc[i] ^= enc[i + 1]
print(enc)
flag = ''
for i in enc:flag += chr(i)
print(flag)
#NSSCTF{H@ppy_Ch1ne5_NEwY3ar!1!1}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/471721.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mpack简明教程

文章目录 摘要MessagePack简介MPACK的简单使用在定长的buffer存储不定长的数据读取截断的数据 摘要 本文先简单介绍MessagePack的基本概念。 然后&#xff0c;介绍一个MessagePack C API - MPack的通常使用。 接着尝试对MPack截断数据的读取。 注&#xff1a;本文完整代码见…

springboot187社区养老服务平台的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

优化策略模式,提高账薄显示的灵活性和扩展性

接着上一篇文章&#xff0c;账薄显示出来之后&#xff0c;为了提高软件的可扩展性和灵活性&#xff0c;我们应用策略设计模式。这不仅仅是为了提高代码的维护性&#xff0c;而是因为明细分类账账薄显示的后面有金额分析这个功能&#xff0c;从数据库后台分析及结合Java语言特性…

记录一次涩涩情侣飞行棋密码破解

注本公众号&#xff0c;长期推送技术文章 知攻善防实验室 红蓝对抗&#xff0c;Web渗透测试&#xff0c;红队攻击&#xff0c;蓝队防守&#xff0c;内网渗透&#xff0c;漏洞分析&#xff0c;漏洞原理&#xff0c;开源 工具&#xff0c;社工钓鱼&#xff0c;网络安全。 81篇原…

【后端高频面试题--Nginx篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;后端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 后端高频面试题--Nginx篇 往期精彩内容什么是Nginx&#xff1f;为什么要用Nginx&#xff1f;为…

「递归算法」:两两交换链表中的节点

一、题目 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xf…

[力扣 Hot100]Day27 合并两个有序链表

题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 出处 思路 简单题&#xff0c;两个指针就能解决。 代码 class Solution { public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {if(!list1)…

Linux第55步_根文件系统第2步_测试使用busybox生成的根文件系统

测试使用busybox生成的根文件系统。测试内容较多&#xff0c;很杂。 1、修改“nfs-kernel-server” 1)、打开终端 输入“sudo vi /etc/default/nfs-kernel-server回车”&#xff0c;打开“nfs-kernel-server”文件。 输入密码“123456回车” 见下图&#xff1a; 2)、在最后…

情人节到了,写一份爱心程序(python)

前言 情人节到了&#xff0c;写一份爱心代码给喜欢的人呀 公式 首先我们介绍下爱心的公式的参数方程&#xff1a; x 16 s i n 3 ( t ) x 16sin^3(t) x16sin3(t) y 13 c o s ( t ) − 5 c o s ( 2 t ) − 2 c o s ( 3 t ) − c o s ( 4 t ) y 13cos(t) - 5cos(2t) - 2co…

Kubernetes 核心概念

一、什么是 Kubernetes 1、含义&#xff1a; Kubernetes 是一个自动化的容器编排平台&#xff0c;它负责应用的部署、应用的弹性以及应用的管理。 2、核心功能&#xff1a; (1) 调度&#xff1a; Kubernetes 的调度器可以把用户提交的容器放到 Kubernetes 管理的集群的某一…

Android Studio 实现图书借阅(管理)系统

&#x1f345;文章末尾有获取完整项目源码方式&#x1f345; 目录 前言 一、任务介绍 1.1 背景 1.2目的和意义 二、 实现介绍 视频演示 2.1 启动页实现 2.2 注册页面实现 2.3 登陆页面实现 2.4 图书列表的实现 2.5 当前借阅页面实现 2.6 我的页面实现…

京东购物拉新保姆级教程

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…