Week1#
ezIDA#
64位IDA打开,Shift+F12打开strings窗口能看到flag。
ezASM#
汇编语言看得有点头大,找到关键的 check flag 部分
xor al, 0x22
cmp al, byte [c + esi]
发现是异或0x22
加密,信息在section .data
已经给出,用脚本解密。
num=[74, 69, 67, 79, 71, 89, 99, 113, 111, 125, 107, 81, 125, 107, 79, 82, 18, 80, 86, 22, 76, 86, 125, 22, 125, 112, 71, 84, 17, 80, 81, 17, 95, 34]
flag=[]
for i in num:
i^=0x22
flag.append(chr(i))
print(''.join(flag))
ezPYC#
题目给出了一个用python编写但打包成了exe的程序,先用工具 pyinstxtractor.py 把exe文件还原为pyc文件,再找在线反编译工具导出py文件。
程序的逻辑同样是异或加密,复用反编译后的代码再修改一点点,进行解密。
flag=[87, 75, 71, 69, 83, 121, 83, 125, 117, 106, 108, 106, 94, 80, 48, 114, 100, 112, 112, 55, 94, 51, 112, 91, 48, 108, 119, 97, 115, 49, 112, 112, 48, 108, 100, 37, 124, 2]
c=[1, 2, 3, 4]
result=[]
for i in range(0, 36, 1):
result.append(chr(c[i % 4] ^ flag[i]))
print(''.join(result))
ezupx#
简单的upx脱壳。脱壳后在IDA中反编译,可以看出与0x32
进行了异或。直接脚本解密。

num= [0x64,0x7B,0x76,0x73,0x60,0x49,0x65,0x5D,0x45,0x13,0x6B,0x02,0x47,0x6D,0x59,0x5C,0x02,0x45,0x6D,0x06,0x6D,0x5E,0x03,0x46,0x46,0x5E,0x01,0x6D,0x02,0x54,0x6D,0x67,0x62,0x6A,0x13,0x4F,0x32]
for i in num:
i^=0x32
flag.append(chr(i))
print(''.join(flag))
Week2#
ezcpp#
魔改TEA,delta换成了0xDEADBEEF
,右移改成左移。
四次TEA加密的代码都挤到主函数里来了,不过还是能看出来结构的。
8个字节分组加密,但是每次加密的明文只比上一组向后移了一个字节,最后只加密了前11个字节。(这里用的是最开始的附件,后面更新的附件修复了)
#include<stdio.h>
void modify_tea_decry(unsigned int *data, unsigned int *key)
{
unsigned int d1 = data[0], d2 = data[1];
unsigned int delta = 0xDEADBEEF, number = delta * 32;
for (int i = 0; i < 32; i++)
{
d2 -= ((d1<<4) + key[2]) ^ ((d1<<5) + key[3]) ^ (d1 + number);
d1 -= ((d2<<4) + key[0]) ^ ((d2<<5) + key[1]) ^ (d2 + number);
number -= delta;
}
data[0] = d1;
data[1] = d2;
}
int main()
{
unsigned char data[33] = {
0x88, 0x6A, 0xB0, 0xC9, 0xAD, 0xF1, 0x33, 0x33,
0x94, 0x74, 0xB5, 0x69, 0x73, 0x5F, 0x30, 0x62,
0x4A, 0x33, 0x63, 0x54, 0x5F, 0x30, 0x72, 0x31,
0x65, 0x6E, 0x54, 0x65, 0x44, 0x3F, 0x21, 0x7D};
unsigned int key[] = {1234,2341,3412,4123};
for(int i = 3; i >= 0; i--)
modify_tea_decry((unsigned int*)(data+i),key);
printf("%s",data);
return 0;
}
android#
java层检测用户名,RC4
native层检测密码
babyre#
可以比较直观的看到开了4个线程,分别对应4种不同的加密方式。每加密一个字节切换到固定顺序的下一个线程,依次加密完输入的flag。
关于key
的部分埋了不少坑,先是.init_array
中的函数改了 key
,之后主函数中异或了0x11
进行加密。加密过程中还会进行异常处理,结果只异或了 key
的前3个字节。
从F5伪码不能直接看出异常的触发,需要看反汇编。idiv
在除数为零时触发 SIGFPE
信号作为异常。而除数var_38 = i - 3
,在异或第4个字节时等于0。
#include<stdio.h>
int main()
{
unsigned char key[] = {0x66,0x65,0x69,0x66,0x65,0x69};
int flag[] = {
0x2F14, 0x004E, 0x4FF3, 0x006D, 0x32D8, 0x006D, 0x6B4B, -110,
0x264F, 0x005B, 0x52FB, -100, 0x2B71, 0x0014, 0x2A6F, -107,
0x28FA, 0x001D, 0x2989, -101, 0x28B4, 0x004E, 0x4506, -38,
0x177B, -4, 0x40CE, 0x007D, 0x29E3, 0x000F, 0x1F11, 0x00FF, 0};
flag[32] = 249 + 1;
for (int i = 0; i < 3; i++)
key[i] ^= 17; // 异常处理
for (int k = 31; k >= 0; k--)
{
switch (k % 4){
case 0:
flag[k] -= flag[k+1] * key[(k+1)%6];
break;
case 1:
flag[k] += flag[k+1] ^ key[(k+1)%6];
break;
case 2:
flag[k] /= flag[k+1] + key[(k+1)%6];
break;
case 3:
flag[k] ^= flag[k+1] - key[(k+1)%6];
break;
}
}
for (int c=0;c<32;c++)
printf("%c",(char)flag[c]);
return 0;
}
作为复现,回过头来看一下Linux的多线程和异常处理:
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
#include <pthread.h>
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
int pthread_exit(void *retval_ptr);
int pthread_join(pthread_t thread, void ** retval);
sem信号量机制实现线程同步
pthread相关的函数实现线程的创建,退出和回收
#include <signal.h>
#include <setjmp.h>
void (*signal(int sig, void (*handler)(int)))(int);
int sigsetjmp(jmp_buf env, int savemask)
void siglongjmp(jmp_buf env, int value)
C语言通过库函数 setjmp
和 longjmp
实现异常处理。setjmp
设置跳转点,其他地方调用 longjmp
跳转到该点抛出异常。POSIX定义了两个新函数 sigsetjmp
和 siglongjmp
,两者之间的唯一区别是 sigsetjmp
增加了一个参数。
setjmp
函数保存程序当前的堆栈环境到env
参数中,接下来的其它地方,你可以通过调用longjmp
函数来恢复先前被保存的程序堆栈环境,并且因此程序控制流会返回到先前调用setjmp
时的执行点。当setjmp
和longjmp
组合一起使用时,能在程序中实现“非本地局部跳转”(“non-local goto”)的机制。这种机制常用于实现把程序的控制流传递到错误处理模块之中;或者程序中不采用正常的返回语句,或函数的正常调用等方法,而使程序能被恢复到先前的一个调用例程(即函数)中。 ——MSDN
signal
函数用于信号处理。本题中捕获算术异常的信号,随即调用 handler
函数中的 siglongjmp
进行异常处理。
arithmetic#
查壳发现魔改UPX,手动修复节区名之后脱壳。
类似变种迷宫题,从out
文件依次加载数据到内存中,按照下三角排列,作为地图。
路径只有两个方向,1和2分别对应向下和右下。程序中用随机数生成路径,不过肯定没有用
最后要求所有路径节点的和大于固定值6752833
,一开始想过爆破,但显然很费时费力。而且在动调时还发生内存溢出,整个out文件的内容不能完全读取。
一般迷宫题比较理想的解法都是写算法求解,翻了下官方wp,确实用的是动态规划。奈何不会算法,这里就仅复现一下思路,不写脚本了。
Week3#
crackme#
c++异常处理,主动抛出异常并轮流调用三个 catch
语句,对应XTEA加密的三步。
这里的XTEA魔改的比较多,改了加密顺序,改了delta,两次左移右移的位数也不相同。
IDA对于异常处理相关代码的识别并不是很好。之前用IDA 7.5版本只能识别出第一个异常的try块;后面改用最新版9.0,三个异常都能识别,而且对应的catch块也直接能对应上。但是F5反编译之后看不到check部分。这一部分只能借助反汇编来看,好在并不复杂。
#include<stdio.h>
void modi_xtea_decry(unsigned int *data, unsigned int *key)
{
unsigned int d1 = data[0], d2 = data[1];
unsigned int delta = 0x33221155;
unsigned int number = 0;
for (int i = 0; i < 32; i++)
{
number ^= delta;
d2 -= ( ((d1<<5) ^ (d1>>6)) + d1) ^ (number + key[(number>>11) & 3]);
d1 -= ( ((d2<<4) ^ (d2>>5)) + d2) ^ (number + key[number & 3]);
}
data[0] = d1;
data[1] = d2;
}
int main()
{
unsigned int key[] = {1234,2345,3456,4567};
unsigned int v18[8];
v18[0] = 0x32FC31EA;
v18[1] = 0xF0566F42;
v18[2] = 0xF905B0B2;
v18[3] = 0x5F4551BE;
v18[4] = 0xFB3EFCBB;
v18[5] = 0x6B6ADB30;
v18[6] = 0x4839879;
v18[7] = 0x2F4378DF;
for(int i = 0; i < 8; i += 2)
modi_xtea_decry(v18+i,key);
printf("%s",(char*)v18);
return 0;
}
利用动调来追踪输入会比较方便一些
findme#
IDA反编译程序,在主函数中看到一个fake_flag,下面是一串乱码。观察乱码最后面是等号,猜测是Base系列编码。解码后发现还是一个fake_flag。
main
函数很短,除了上面两个假flag,只剩下输出Buffer一个语句。查看Buffer
变量的内容,发现是字符M
,但是紧接着四个字节后又有一个字节'Z'
。这里联想到PE文件的MZ
头。但是正常它只会出现在文件的最前面部分,中间也没有间隔。于是打开Hex窗口看了后面的数据,又发现了This program cannot be run in DOS mode
这一标志性的信息。可以确定在题目的程序里面又藏了一个PE文件。
能够看出内嵌的文件把原来的每个字节都扩充成了4个字节,高位的3个字节(小端序)都补零对齐。在010Editor中把有这种特征的部分提取出来,另存为enc.exe
,然后写了几行c代码把它恢复成正常的PE文件。
#include<stdio.h>
int main()
{
int buf;
char byte;
FILE *enc = fopen("C:\\Users\\LENOVO\\Desktop\\enc.exe","rb+");
FILE *dec = fopen("C:\\Users\\LENOVO\\Desktop\\dec.exe","wb+");
while(!feof(enc))
{
fread(&buf,sizeof(int),1,enc);
byte = buf & 0xff;
fwrite(&byte,sizeof(char),1,dec);
}
fclose(enc);
fclose(dec);
return 0;
}
反编译提取出来的程序,在IDA中没找到main函数。分析汇编部分,看到了不少花指令,而且形式都相似,如下:
jz loc_xx
jnz loc_xx
db 0xC7
从头开始把所有花指令都patch成nop
,重新建立函数,可以正常反编译main
函数。除去输入输出,主函数调用了sub_401068
和sub_40110C
两个函数,最后把处理后的输入和数组byte_405148
比较判断。分别跟踪这两个函数,发现大部分比较熟悉(算法和Week2的一道题很像,当时没做出来,后面看wp才知道是RC4)结合网络资料,判断出这两个函数是经过小改的RC4算法。
改动主要有三点
S盒初始状态,各元素都是索引值的相反数(从unsigned char的角度来看,溢出成
256-i
)密钥流的生成,取S盒中从后向前第
s[v1]+s[v3]
个元素,同样看成s[256-(s[v1]+s[v3])]
。这部分IDA反编译的代码不好理解,
array[-(buffer[v1]+buffer[v3])]
,最后索引值取负。但是负的索引在C语言没有意义。如果理解为unsigned char,由于array
长度只有32,同样也会出现越界的情况。于是分析一下对应的汇编,得出结论是这里负号要看成从array地址减去那个索引值。在栈中查看
array
和buffer
之间的偏移量,发现刚好是256,这两个数组无缝衔接。那么从array地址减去k
对应的元素也就是buffer
从后向前第k
个元素。加密没有进行异或,而是原文和对应密钥流相加。
最后进行解密。按照原算法的流程推出密钥流,之后反过来从加密数据中逐一减去即可。
array= [0x7D, 0x2B, 0x43, 0xA9, 0xB9, 0x6B, 0x93, 0x2D, 0x9A,
0xD0, 0x48, 0xC8, 0xEB, 0x51, 0x59, 0xE9, 0x74, 0x68, 0x8A,
0x45, 0x6B, 0xBA, 0xA7, 0x16, 0xF1, 0x10, 0x74, 0xD5, 0x41,
0x3C, 0x67, 0x7D]
buffer = [0]+[256-i for i in range(1,256)]
v = b'deadbeef'
v6 = list(v*32)
v2 = 0
for j in range(256):
v2 = (buffer[j]+v6[j]+v2) % 256
buffer[v2],buffer[j] = buffer[j],buffer[v2]
v1 = v3 = 0
for i in range(32):
v1 = (v1+1) % 256
v3 = (buffer[v1]+v3) % 256
buffer[v1],buffer[v3] = buffer[v3],buffer[v1]
index = 256 - (buffer[v1]+buffer[v3]) & 0xff
array[i] = (array[i]-buffer[index]) & 0xff
print(bytes(array))
encrypt#
主函数遍布Windows加密API,去MSDN上一查都是<bcrypt.h>
这个库中的。
结合文档和程序中的字符串信息,推测出是AES-CBC。
在生成 pbKey
的函数附近找到 pbSecret
,推测是key。在前面可以找到iv
mystery#
主函数只有ptrace
反调试,核心代码放到了init
和fini
部分。
init_array
预先加密了密钥,先异或后RC4。fini_array
实现类似主函数的功能,对输入的flag进行魔改RC4(生成密钥流后的异或加密改成了减法)
#include<stdio.h>
void rc4_crypt(unsigned char *data, unsigned char *key, int data_len, int key_len)
{
unsigned char S[256], tmp = 0, t = 0;
int i = 0, j = 0;
for (int i = 0; i < 256; i++) S[i]= i;
for (int i = 0; i < 256; i++)
{
j = (j + S[i] + key[i % key_len]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
}
i = 0, j = 0;
for (int l = 0; l < data_len; l++)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
t = (S[i] + S[j]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
data [l] ^= S[t];
}
}
void modi_rc4_crypt(unsigned char *data, unsigned char *key, int data_len, int key_len)
{
unsigned char S[256], tmp = 0, t = 0;
int i = 0, j = 0;
for (int i = 0; i < 256; i++) S[i]= i;
for (int i = 0; i < 256; i++)
{
j = (j + S[i] + key[i % key_len]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
}
i = 0, j = 0;
for (int l = 0; l < data_len; l++)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
t = (S[i] + S[j]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
data [l] += S[t];
}
}
int main()
{
unsigned char key[] = {0x44, 0x4A, 0x56, 0x44, 0x4A, 0x56};
unsigned char key1[] = {0x4D, 0x4E, 0x41, 0x70, 0x4B, 0x4A, 0x4D, 0x5A, 0x48, 0x0E};
unsigned char data[] ={
0x50, 0x42, 0x38, 0x4D, 0x4C, 0x54, 0x90, 0x6F, 0xFE, 0x6F,
0xBC, 0x69, 0xB9, 0x22, 0x7C, 0x16, 0x8F, 0x44, 0x38, 0x4A,
0xEF, 0x37, 0x43, 0xC0, 0xA2, 0xB6, 0x34, 0x2C};
for (int i = 0; i < 6; i++)
key[i] ^= 0x2F;
for (int j = 0; j < 10; j++)
key1[j] ^= 0x2F;
rc4_crypt(key1,key,10,6);
modi_rc4_crypt(data,key1,28,10);
printf("%s",data);
}
Week4#
crackme2#
先是异常处理,出题人应该想借异常来隐藏代码。结合上周的经验,IDA9.0能够识别出来这部分异常处理,反编译结果还算清晰。
mov byte ptr ds:0, 1
引发空指针解引用的异常,直接跳转执行__expect(1)
块中的代码(查询MSDN可知,try-except
语句是 Microsoft 特定的扩展,支持 C / C++ 中的结构化异常处理SEH
)
继续分析,NtQueryInformationProcess(···, ProcessDebugPort, &ProcessInformation, ···)
检查是否处于调试状态,结合后面smc进行反调试。先把这里的反调试patch掉。
smc大概有两种解决思路
- IDApython脚本进行patch
- 解密完成处下断点dump
动调还是方便一点,在第二次调用VirtualPrrotect
的地方下断点,此时SMC已经解密完成。在反汇编窗口中找到sub_14000105C
对应地址,重新反编译看到真正的代码逻辑。这里的反调和smc设计的很巧妙,在解密之前已经是一个正常的函数,只不过最后解出fake flag,如果不仔细看很难发现这里暗藏玄机。
解密后发现是方程,用z3求解。
考虑到方程中用了左移,最开始用z3的Bitvecs(8)
创建变量,不过确实慢,要跑大概两个多小时。而且比较疑惑的是这种方法解出的flag只有部分正确,其余的超过ascii可见字符范围。
hgame{S\xcdC\xdf\xb4n\xe4\xdfs0\xec\xf61ng_equ4t\xb1On\xf3}
参考官方wp,改用Ints
创建变量,效果立竿见影。得到正确flag
from z3 import *
(v5,v28,v11,v10,v24,v41,v22,v40,v7,v18,v29,v27,v9,v31,v30,v20,v23,v39,v15,v21,v26,v2,v42,v6,v16,v1,v17,v25,v8,v4,v19,v3,v12,v13) = Ints("v5 v28 v11 v10 v24 v41 v22 v40 v7 v18 v29 v27 v9 v31 v30 v20 v23 v39 v15 v21 v26 v2 v42 v6 v16 v1 v17 v25 v8 v4 v19 v3 v12 v13")
s = Solver()
s.add(v18+201*v24+194*v10+142*v20+114*v39+103*v11+52*(v17+v31)+((v9+v23)*2**6)+14*(v21+4*v25+v25)+9*(v40+23*v27+v2+3*v1+4*v2+4*v6)+5*(v16+23*v30+2*(v3+2*v19)+5*v5+39*v15+51*v4)+24*(v8+10*v28+4*(v42+v7+2*v26))+62*v22+211*v41+212*v29==296473)
s.add(207*v41+195*v22+151*v40+57*v5+118*v6+222*v42+103*v7+181*v8+229*v9+142*v31+51*v29+122*(v26+v20)+91*(v2+2*v16)+107*(v27+v25)+81*(v17+2*v18+v18)+45*(v19+2*(v11+v24)+v11+v24)+4*(3*(v23+v21+2*v23+5*v4)+v39+29*(v10+v1)+25*v15)+26*v28+101*v30+154*v3==354358)
s.add(177*v40+129*v26+117*v42+143*v28+65*v8+137*v25+215*v21+93*v31+235*v39+203*v11+15*(v7+17*v30)+2*(v24+91*v9+95*v29+51*v41+81*v20+92*v18+112*(v10+v6)+32*(v22+2*(v1+v23))+6*(v2+14*v16+19*v15)+83*v5+53*v4+123*v19)+v17+175*v27+183*v3==448573)
s.add(113*v19+74*v3+238*v6+140*v2+214*v26+242*v8+160*v21+136*v23+209*v9+220*v31+50*v24+125*v10+175*v20+23*v39+137*v22+149*v18+83*(v4+2*v30)+21*(9*v29+v16)+59*(4*v27+v17)+41*(v1+v41)+13*(v7+11*(v40+v15)+6*v42+4*(v28+2*v11)+v28+2*v11+17*v5)+36*v25==384306)
s.add(229*v21+78*v1+v2+v9+133*v27+74*v6+69*v26+243*v7+98*v28+253*v8+142*v25+175*v31+105*v41+221*v10+121*v39+218*(v19+v29)+199*(v24+v30)+33*(v40+7*v17)+4*(27*v20+50*v11+45*v18+19*(v3+v42)+v16+16*v23+52*v4)+195*v22+211*v5+153*v15==424240)
s.add(181*v25+61*v2+65*v21+58*v31+170*v29+143*v24+185*v10+86*v11+97*v22+235*(v23+v27)+3*(53*v41+74*(v8+v3)+13*(v42+6*v9)+11*(v39+7*v20)+15*(v18+4*v17)+v7+35*v1+29*v15)+4*(57*v6+18*(v5+2*v26)+v28+17*v16+55*v30)+151*v40+230*v4+197*v19==421974)
s.add(209*v21+249*v30+195*v2+219*v25+201*v39+85*v18+213*(v17+v31)+119*(v11+2*v41)+29*(8*v24+v40+4*v27+v27)+2*(v8+55*(2*v29+v19)+3*(v10+39*v9+2*(v6+20*v20)+35*v7)+4*(v5+31*v42+28*v3)+26*v28+46*(2*v26+v16)+98*v1)+53*v23+171*v15+123*v4==442074)
s.add(162*v19+74*v5+28*v27+243*v42+123*v28+73*v8+166*v23+94*v24+113*v11+193*v22+122*(v6+2*v7)+211*(v10+v25)+21*(v17+7*v41)+11*(v4+23*(v16+v39)+2*(v40+5*v30+2*(2*v18+v29)+2*v18+v29))+5*(46*v9+26*v20+4*(v31+2*v21)+v15+27*v2+10*v1)+36*(v3+5*v26)==376007)
s.add(63*v19+143*v5+250*v6+136*v2+214*v40+62*v26+221*v42+226*v7+171*v28+178*v8+244*v23+(v9*2**7)+150*v31+109*v29+70*v41+127*v20+204*v39+121*v22+173*v18+69*(v25+v30+v27)+74*(v16+2*v15+v15)+22*(7*v24+v17+10*v11)+40*(v1+4*v21+v21)+81*v10+94*v4+84*v3==411252)
s.add(229*v15+121*v4+28*v30+206*v16+145*v27+41*v1+247*v6+118*v26+241*v28+79*v8+102*v25+124*v23+65*v9+68*v31+239*v17+148*v24+245*v39+115*v11+163*v22+137*v18+53*(v5+2*v29)+126*(v40+2*v10)+38*(v7+v21+4*v7+6*v41)+12*(v2+16*v42)+109*v20+232*v3+47*v19==435012)
s.add(209*v21+233*v40+93*v1+241*v2+137*v8+249*v17+188*v29+86*v24+246*v10+149*v20+99*v11+37*v22+219*v18+17*(v6+10*v25)+49*(v5+3*v3+4*v28+v28)+5*(16*v39+11*(v41+2*v27+v27)+12*v7+v31+30*v16+27*v19)+18*(v23+2*(v4+v26+2*v4)+v4+v26+2*v4)+24*v9+109*v42+183*v30+154*v15==392484)
s.add(155*v15+247*v40+157*v28+119*v23+161*v17+133*v20+85*v22+229*(v7+v24)+123*(2*v31+v42)+21*(v41+12*v30)+55*(v9+v5+v18+2*v5)+15*(v3+16*v10+9*v21)+2*(v2+115*v29+111*v16+26*v6+88*v8+73*v39+71*v11+28*(v26+2*(v25+2*v1))+51*v27+99*v4+125*v19)==437910)
s.add(220*v3+200*v4+139*v15+33*v5+212*v30+191*v16+30*v27+233*v1+246*v6+89*v2+252*v40+223*v42+19*v25+141*v21+163*v9+185*v17+136*v31+46*v24+109*v10+217*v39+75*v22+157*v18+125*(v11+v19)+104*(2*v41+v20)+43*(v28+2*v29+v29)+32*(v8+v7+2*v8+2*(v23+v26))==421905)
s.add(211*v24+63*v15+176*v5+169*v16+129*v27+146*v40+111*v26+68*v42+39*v25+188*v23+130*v9+(v31*2**6)+91*v41+208*v20+145*v39+247*v18+93*(v22+v17)+71*(v6+2*v11)+103*(v8+2*v30)+6*(v21+10*v28+28*v7+9*v29+19*v2+24*v1+22*v3)+81*v10+70*v4+23*v19==356282)
s.add(v12==v10+2*(v31+4*(v29+v17))+v31+4*(v29+v17))
s.add(94*v42+101*v2+152*v40+200*v7+226*v8+211*v23+121*v24+74*v11+166*v18+((v6+3*v28)*2**6)+41*(4*v9+v21)+23*(v39+11*v41)+7*(v20+10*v25+2*v12+v12)+3*(78*v30+81*v16+55*v27+73*v1+4*v26+v15+85*v3+65*v19)+62*v22+88*v5+110*v4==423091)
s.add(133*v22+175*v15+181*v30+199*v16+123*v27+242*v1+75*v6+69*v2+153*v40+33*v26+100*v42+229*v7+177*v8+134*v31+179*v29+129*v41+14*v10+247*v24+228*v20+92*v11+86*(v9+2*v18)+94*(v23+v21)+37*(v17+4*v3)+79*(v25+2*v28)+72*v5+93*v39+152*v4+214*v19==391869)
s.add(211*v24+213*v18+197*v40+159*v25+117*v21+119*v9+98*v17+218*v41+106*v39+69*v11+43*(v2+v29+2*v2)+116*(v4+v10+2*v26)+5*(v42+9*v23+35*v20+37*v31)+11*(v16+13*v27+5*v5+8*v30)+6*(29*v28+25*v8+38*v22+v15+13*v1+10*v3)+136*v7+142*v6+141*v19==376566)
s.add(173*v3+109*v15+61*v30+187*v1+79*v6+53*v40+184*v21+43*v23+41*v9+166*v31+193*v41+58*v24+146*v10+(v20*2**6)+89*v39+121*v11+5*(v17+23*v8)+7*(29*v18+v29+4*v7)+13*(3*v42+v16+7*v26+13*v2)+3*(v4+83*v5+51*v27+33*v22+8*(v19+4*v28)+18*v25)==300934)
s.add(78*v1+131*v5+185*v16+250*v40+90*v26+129*v42+255*v28+206*v8+239*v25+150*v10+253*v39+104*v22+58*(v2+2*v7)+96*(v15+v31)+117*(v9+2*v4)+27*(v17+8*v18+v18)+19*(v23+3*v21+4*v29+v29)+7*(22*v41+3*(v11+11*v24)+v3+29*v6+14*v27)+109*v20+102*v30+100*v19==401351)
s.add(233*v19+71*v5+209*v27+82*v6+58*v26+53*v25+113*v23+206*v31+39*v41+163*v20+222*v11+191*v18+123*(v7+v40)+69*(v9+2*v22+v22)+9*(v3+8*v24+7*(3*v1+v28)+5*v16+19*v30)+4*(v15+26*v17+61*v29+43*v42+49*v2+32*v4)+10*(7*(v8+3*v21)+v39+12*v10)==368427)
s.add(139*v30+53*v5+158*v16+225*v1+119*v6+67*v2+213*v40+188*v28+152*v8+187*v21+129*v23+54*v9+125*v17+170*v24+184*v11+226*v22+253*v18+26*(v29+v41)+97*(v4+2*v25)+39*(5*v26+v27)+21*(v39+8*v42)+12*(17*v10+v31+15*v7+12*v19)+165*v20+88*v15+157*v3==403881)
s.add(114*v3+61*v27+134*v40+62*v42+89*v9+211*v17+163*v41+66*v24+201*(v7+v18)+47*(5*v16+v22)+74*(v4+v31)+142*(v2+v28)+35*(v20+6*v26)+39*(v15+6*v30)+27*(v25+9*v23+8*v6)+4*(v21+63*v19+2*(v1+12*(v10+v5)+8*v11+26*v29))+10*(v8+4*v39+v39)==382979)
s.add(122*v25+225*v21+52*v23+253*v9+197*v17+187*v31+181*v29+183*v41+47*v20+229*v39+88*v22+127*(v10+2*v18)+37*(v7+3*v3)+((v11+2*v30+v30)*2**6)+7*(21*v8+v27+18*(v4+v1+2*v16))+6*(23*v24+v26+17*v2+39*v6)+10*(v5+11*v28+21*v42)+149*v19+165*v40+121*v15==435695)
s.add(165*v20+223*v4+249*v5+199*v1+135*v2+133*v26+254*v42+111*v7+189*v28+221*v25+115*v21+186*v9+79*v41+217*v24+122*v11+38*v18+109*(2*v31+v29)+14*(v8+17*v40+8*(v6+2*v16))+4*(11*(5*v30+v39)+6*(v10+2*v22)+v27+52*v17+50*v23)+229*v15+86*v3+234*v19==453748)
s.add(181*v25+94*v42+125*v1+226*v26+155*v7+95*v21+212*v17+91*v31+194*v29+98*v24+166*v11+120*v22+59*v18+32*(v9+v8)+158*(v6+v5)+101*(v41+v19)+63*(v4+2*v23)+67*(v28+2*v20)+11*(v39+10*v16+11*v10)+39*(v30+4*(v2+v15))+233*v40+56*v27+225*v3==358321)
s.add(229*v21+135*v4+197*v15+118*v5+143*v16+134*v6+204*v40+173*v26+81*v7+60*v28+58*v8+179*v23+142*v9+178*v17+230*v31+148*v29+224*v41+194*v24+223*v10+87*v20+200*v39+233*v11+49*v22+127*(v25+v30)+31*(4*v27+v18)+42*(v1+6*v2)+109*v42+75*v3+165*v19==456073)
s.add(41*v4+253*v3+163*v15+193*v30+155*v16+113*v27+131*v6+55*v2+21*v40+53*v26+13*v8+201*v25+237*v9+223*v31+95*v24+194*v20+62*v39+119*v11+171*v22+135*v18+69*(v10+3*v28)+211*(v1+v29)+4*(43*v7+v42+40*v17)+6*(v5+33*v41+20*(2*v19+v21)+24*v23)==407135)
s.add(v13==v6+v1+8*v6+4*(v8+2*v27))
s.add(111*v19+190*v3+149*v4+173*v28+118*v23+146*v29+179*v10+51*v20+49*v39+61*v11+125*v22+162*v18+214*(v25+v30)+14*(2*v31+v24)+178*(v41+v16)+11*(4*v9+v21+17*v42)+65*(v26+v17+2*v26+2*v5)+4*(v7+38*v15+4*v13+v13+8*v40+43*v2)==369835)
s.add(27*v27+223*v6+147*v26+13*v21+35*(v17+7*v4)+57*(v19+2*v18+3*v11)+11*(v1+17*(v9+v5)+10*v16+3*v31)+2*(53*v23+v25+38*v15+43*v42+115*v29+61*v22+111*(v10+v40)+14*(v20+v7+2*v7+8*v28)+109*v2+100*v41+63*v8)+93*v39+251*v30+131*v3==393303)
s.add(116*v9+152*v29+235*v20+202*v18+85*(v8+3*v11)+221*(v16+v40)+125*(2*v41+v24)+7*(19*v4+9*(v10+2*v25)+v2+33*v3+32*v19)+3*(71*v39+43*v22+32*(v17+v26)+15*(v5+v6+2*v23)+v28+74*v31+48*v42)+10*(v21+11*v30+16*v15)+136*v7+106*v1+41*v27==403661)
s.add(127*v4+106*v15+182*v30+142*v5+159*v16+17*v1+211*v6+134*v2+199*v7+103*v28+247*v23+122*v9+95*v41+62*v10+203*v39+16*v11+41*(6*v42+v25)+9*(22*v24+v20+27*v31+28*v40)+10*(v8+v22+3*v21+8*v17+2*(v22+3*v21+8*v17)+13*v29)+6*(23*v27+v26)+213*v18+179*v3+43*v19==418596)
s.add(149*v19+v1+133*v22+207*v41+182*v26+234*v7+199*v8+168*v21+58*v10+108*v20+142*v18+156*(v9+v25)+16*(v29+6*v31)+126*(v17+2*v39)+127*(v4+2*v27+v40)+49*(v30+4*v16)+11*(v5+22*v11)+5*(v15+v42+45*v24+50*v28)+109*v2+124*v6+123*v3==418697)
flag = []
result = s.model()
vars = (v5,v28,v11,v10,v24,v41,v22,v40,v7,v18,v29,v27,v9,v31,v30,v20,v23,v39,v15,v21,v26,v2,v42,v6,v16,v1,v17,v25,v8,v4,v19,v3)
for var in vars:
flag.append(result[var].as_long())
print(bytes(flag).decode())
change#
hook,有点像回调函数
两个加密函数(隔一个字节)交替进行加密。
data = [0x13, 0x0A, 0x5D, 0x1C, 0x0E, 0x08, 0x23, 0x06, 0x0B, 0x4B, 0x38, 0x22, 0x0D, 0x1C, 0x48, 0x0C,
0x66, 0x15, 0x48, 0x1B, 0x0D, 0x0E, 0x10, 0x4F]
key=b"am2qasl"
flag = []
for i in range(len(data)):
if(i % 2 == 0):
result = (data[i] -10) ^ key[i % len(key)]
else:
result = data[i] ^ key[i % len(key)]
flag.append(result)
print(bytes(flag))