MISC
the_best_ctf_game
根据这道题给出的文件查看其16进制即可得到flag。

电脑被黑
题目链接:电脑被黑.zip
从这道提给出的文件中可以看出,存在一个flag.txt文件,但是被删除了,且在trashinfo可以看到删除之前在misc01目录下

所以使用工具恢复即可。但是根据题目,这个应该是一个linux的磁盘dump文件,所以先挂载到虚拟机中查看本身存在哪些文件,挂载后有三个文件,一个是提示flag被删掉的图片,一个是假flag文件,还有一个demo文件,使用extundelete工具恢复后可以得到被删除的flag.txt。不过该文件内容应该是被加密过的,和demo有关,分析demo,其中核心逻辑比较简单就是从文件中读取字符,然后进行异或和加操作,其中v4和v5的初值是34和0,文件中要求打开一个名为deom的文本,但该文本不存在,所以根据flag.txt中的16进制逆出算法即可。

下面为python编写的解密脚本
flag=[0x44,0x2A,0x03,0xE5,0x29,0xA3,0xAF,0x62,0x05,0x31,0x4E,0xF3,0xD6,0xEB,0x90,0x66,0x24,0x5C,0xB7,0x92,0xF6,0xD7,0x4D,0x0B,0x6A,0x41,0xA3,0x85,0xEF,0x90,0x5A,0x7E,0x5B,0xEC,0xC1,0xF0,0xD4,0x61,0x12,0x12,0x45,0xEB,0xB8]
ans=[]
v4=34
v5=0
for i in flag:
ans.append((int(v4%0x100)^i)-v5)
v4+=34
v5=(v5+2)&0xf
print(ans)
for i in ans:
print(chr(i),end='')
RE
z3
题目链接:z3.zip
分析程序后可以看到有大量的多项式运算,且根据题目名称提示,使用z3编写脚本计算出解即可得到flag。
from z3 import *
s = Solver()
input = [Int('input[%d]'%i) for i in range(42)]
s.add(0x4F17 == 34 * input[3] + 12 * input[0] + 53 * input[1] + 6 * input[2] + 58 * input[4] + 36 * input[5] + input[6],
0x9CF6 == 27 * input[4] + 73 * input[3] + 12 * input[2] + 83 * input[0] + 85 * input[1] + 96 * input[5] + 52 * input[6],
0x8DDB == 24 * input[2] + 78 * input[0] + 53 * input[1] + 36 * input[3] + 86 * input[4] + 25 * input[5] + 46 * input[6],
0x8EA6 == 78 * input[1] + 39 * input[0] + 52 * input[2] + 9 * input[3] + 62 * input[4] + 37 * input[5] + 84 * input[6],
0x6929 == 48 * input[4] + 14 * input[2] + 23 * input[0] + 6 * input[1] + 74 * input[3] + 12 * input[5] + 83 * input[6],
0x9911 == 15 * input[5] + 48 * input[4] + 92 * input[2] + 85 * input[1] + 27 * input[0] + 42 * input[3] + 72 * input[6],
0x40A2 == 26 * input[5] + 67 * input[3] + 6 * input[1] + 4 * input[0] + 3 * input[2] + 68 * input[6],
0x2F3E == 34 * input[10] + 12 * input[7] + 53 * input[8] + 6 * input[9] + 58 * input[11] + 36 * input[12] + input[13],
0x62B6 == 27 * input[11] + 73 * input[10] + 12 * input[9] + 83 * input[7] + 85 * input[8] + 96 * input[12] + 52 * input[13],
0x4B82 == 24 * input[9] + 78 * input[7] + 53 * input[8] + 36 * input[10] + 86 * input[11] + 25 * input[12] + 46 * input[13],
0x486C == 78 * input[8] + 39 * input[7] + 52 * input[9] + 9 * input[10] + 62 * input[11] + 37 * input[12] + 84 * input[13],
0x4002 == 48 * input[11] + 14 * input[9] + 23 * input[7] + 6 * input[8] + 74 * input[10] + 12 * input[12] + 83 * input[13],
0x52D7 == 15 * input[12] + 48 * input[11] + 92 * input[9] + 85 * input[8] + 27 * input[7] + 42 * input[10] + 72 * input[13],
0x2DEF == 26 * input[12] + 67 * input[10] + 6 * input[8] + 4 * input[7] + 3 * input[9] + 68 * input[13],
0x28DC == 34 * input[17] + 12 * input[14] + 53 * input[15] + 6 * input[16] + 58 * input[18] + 36 * input[19] + input[20],
0x640D == 27 * input[18] + 73 * input[17] + 12 * input[16] + 83 * input[14] + 85 * input[15] + 96 * input[19] + 52 * input[20],
0x528F == 24 * input[16] + 78 * input[14] + 53 * input[15] + 36 * input[17] + 86 * input[18] + 25 * input[19] + 46 * input[20],
0x613B == 78 * input[15] + 39 * input[14] + 52 * input[16] + 9 * input[17] + 62 * input[18] + 37 * input[19] + 84 * input[20],
0x4781 == 48 * input[18] + 14 * input[16] + 23 * input[14] + 6 * input[15] + 74 * input[17] + 12 * input[19] + 83 * input[20],
0x6B17 == 15 * input[19] + 48 * input[18] + 92 * input[16] + 85 * input[15] + 27 * input[14] + 42 * input[17] + 72 * input[20],
0x3237 == 26 * input[19] + 67 * input[17] + 6 * input[15] + 4 * input[14] + 3 * input[16] + 68 * input[20],
0x2A93 == 34 * input[24] + 12 * input[21] + 53 * input[22] + 6 * input[23] + 58 * input[25] + 36 * input[26] + input[27],
0x615F == 27 * input[25] + 73 * input[24] + 12 * input[23] + 83 * input[21] + 85 * input[22] + 96 * input[26] + 52 * input[27],
0x50BE == 24 * input[23] + 78 * input[21] + 53 * input[22] + 36 * input[24] + 86 * input[25] + 25 * input[26] + 46 * input[27],
0x598E == 78 * input[22] + 39 * input[21] + 52 * input[23] + 9 * input[24] + 62 * input[25] + 37 * input[26] + 84 * input[27],
0x4656 == 48 * input[25] + 14 * input[23] + 23 * input[21] + 6 * input[22] + 74 * input[24] + 12 * input[26] + 83 * input[27],
0x5B31 == 15 * input[26] + 48 * input[25] + 92 * input[23] + 85 * input[22] + 27 * input[21] + 42 * input[24] + 72 * input[27],
0x313A == 26 * input[26] + 67 * input[24] + 6 * input[22] + 4 * input[21] + 3 * input[23] + 68 * input[27],
0x3010 == 34 * input[31] + 12 * input[28] + 53 * input[29] + 6 * input[30] + 58 * input[32] + 36 * input[33] + input[34],
0x67FE == 27 * input[32] + 73 * input[31] + 12 * input[30] + 83 * input[28] + 85 * input[29] + 96 * input[33] + 52 * input[34],
0x4D5F == 24 * input[30] + 78 * input[28] + 53 * input[29] + 36 * input[31] + 86 * input[32] + 25 * input[33] + 46 * input[34],
0x58DB == 78 * input[29] + 39 * input[28] + 52 * input[30] + 9 * input[31] + 62 * input[32] + 37 * input[33] + 84 * input[34],
0x3799 == 48 * input[32] + 14 * input[30] + 23 * input[28] + 6 * input[29] + 74 * input[31] + 12 * input[33] + 83 * input[34],
0x60A0 == 15 * input[33] + 48 * input[32] + 92 * input[30] + 85 * input[29] + 27 * input[28] + 42 * input[31] + 72 * input[34],
0x2750 == 26 * input[33] + 67 * input[31] + 6 * input[29] + 4 * input[28] + 3 * input[30] + 68 * input[34],
0x3759 == 34 * input[38] + 12 * input[35] + 53 * input[36] + 6 * input[37] + 58 * input[39] + 36 * input[40] + input[41],
0x8953 == 27 * input[39] + 73 * input[38] + 12 * input[37] + 83 * input[35] + 85 * input[36] + 96 * input[40] + 52 * input[41],
0x7122 == 24 * input[37] + 78 * input[35] + 53 * input[36] + 36 * input[38] + 86 * input[39] + 25 * input[40] + 46 * input[41],
0x81F9 == 78 * input[36] + 39 * input[35] + 52 * input[37] + 9 * input[38] + 62 * input[39] + 37 * input[40] + 84 * input[41],
0x5524 == 48 * input[39] + 14 * input[37] + 23 * input[35] + 6 * input[36] + 74 * input[38] + 12 * input[40] + 83 * input[41],
0x8971 == 15 * input[40] + 48 * input[39] + 92 * input[37] + 85 * input[36] + 27 * input[35] + 42 * input[38] + 72 * input[41],
0x3A1D == 26 * input[40] + 67 * input[38] + 6 * input[36] + 4 * input[35] + 3 * input[37] + 68 * input[41])
s.check()
for i in range(42):
print(chr(s.model()[input[i]].as_long()),end='')
hyperthreading
题目链接:hyperthreading.zip
这道题代码比较简单,创建了三个线程,执行了连个函数,其中一个线程执行的函数是一个简单的反调试,其处理方法是把其最后执行的exit函数nop掉或者把test ax,ax改为xor ax,ax,让其函数返回值恒为0即可。

处理过反调试后,观察另一个线程函数,这个函数中存在一定的干扰,有混淆和异常,单步调试会走到有一步存在空地址,直接执行会崩掉,所以这里找到存放输入字符串的地址,在存放输入flag的内存处加一个内存断点,让程序执行,根据断点程序停到了真正的主要逻辑部分,其分析如下

因为算法涉及到移位,不能逆算法,但是由于是单表加密,所以爆破起来也比较简单,下面是解密脚本,运行后根据flag格式加上{}即可。
a=qwertyuiopasdfghjklzxcvbnm-1234567890QWERTYUIOPASDFGHJKLZXCVBNM
b=[]
flag=[0xDD,0x5B,0x9E,0x1D,0x20,0x9E,0x90,0x91,0x90,0x90,0x91,0x92,0xDE,0x8B,0x11,0xD1,0x1E,0x9E,0x8B,0x51,0x11,0x50,0x51,0x8B,0x9E,0x5D,0x5D,0x11,0x8B,0x90,0x12,0x91,0x50,0x12,0xD2,0x91,0x92,0x1E,0x9E,0x90,0xD2,0x9F]
for i in a:
tmp=((((ord(i)>>2)^(ord(i)<<6))^0x23)+0x23)%256
b.append(tmp)
print(b)
for i in flag:
for j in range(len(b)):
if i==b[j]:
print(a[j],end='')
break
list
题目链接:list.zip
把程序放进idapro中分析,程序结构相对比较复杂,但其实逻辑还是比较简单的。动态调试后何以找到主要逻辑所在的函数,其主要在图中所示的函数中。

进入函数后,在这里可以看出flag长度的要求,是38位,不是则会直接跳过flag处理部分

接着往下分析,可以看到执行了malloc函数开辟了一块内存空间,然后把地址给了ax,再赋给dx

然后对输入字符串进行遍历,并讲结果存放在分配好的内存dx中

接着往下分析,下面的分析如图

在遍历了输入字符串后,与内存中给定的数据进行异或,然后把异或运算的结果存入上面dx的下一位,也就是输入字符串的后面,然后把上一次运算的地址在dx后偏移4位存入,再把上面分配额地址dx放入到变量var30中,进行下一次遍历,所以上面变量var30中赋给ax的地址就是上一次遍历分配的内存地址,即上一次的存储地址,最后把这一次的地址赋给上面备份的var30(上一次的地址)后偏移8位,也就是说整个再内存中存储额是一个双向链表结构,首先存储输入字符串的其中一位,下一位是异或运算后的字符串,接着存储上一个模块的地址和下一个模块的地址。

截止到这里程序的运算逻辑就结束了,所以只要把内存中运算后的flag数据和上面用来异或的数据运算即可的到flag。解密脚本如下
a=[0x68,0x27,0x21,0x21,0x70,0x64,0x61,0x32,0x64,0x34,0x7D,0x72,0x73,0x73,0x73,0x51,0x51,0x0A,0x5,0x7,0x40,0x46,0x46,0x46,0x19,0x77,0x25,0x25,0x74,0xFA,0xEB,0x16,0x53,0x2E,0x23,0x52,0x4e,0x77]
b=[0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x12,0x13,0x14,0x15,0x21,0x22,0x23,0x24,0x25,0x31,0x32,0x33,0x34,0x35,0x41,0x42,0x43,0x44,0x45,0x51,0x52,0x53,0x54,0x55,0x12,0x13,0x11,0x14,0x15]
j=37
for i in range(38):
print(chr(a[j]^b[i]),end='')
j-=1
<pre class="wp-block-preformatted"><br></br>
easyre1
题目链接:easyre1.zip
把题目放进ida中分析,通过字符串可以直接找到主要逻辑所在的位置,在输入了字符串后,程序对比了输入字符串的长度,要求其长度为32位,否则直接输出错误。

下面程序调用了一个名为first的函数,其是一个标准的b64,然后程序crypt函数,有四个参数,这四个参数分别是输入字符串的b64和其长度,程序给的字符串和其长度

进入这个crypt函数进行分析后,可以发现这个函数对给定的字符串进行了一些加密操作,然后把加密的结果与输入字符串的b64进行异或,异或的结果才是后面过程用到的数据,所以不必关注加密的过程,直接在下面获取加密的结果即可,所以其实这个函数是一个RC4加密,密钥就是内存中的字符串。

RC4加密的重点就是密钥流生成,函数中调用了一个名为init的函数,起作用就是生成密钥流

这个密钥流在最后的异或过程中就可以看到,记下来即可。 在后面的过程中,对上面加密后的结果8位一组进行顺序调转后存入Dest中

其中LOBYTE这些都是IDA的宏定义,其就先当与是把一个BYTE分成四部分,这里的结果就是把数据顺序调转,然后把这个数据与0x90604956进行异或,这个数据是固定的

然后对异或后小于0的结果与22222222h进行异或

然后与正确的结果进行对比,其与上面的异或过程是相同的,所以也是每8位进行比较。

所以在这里可以直接获取到正确的结果。 到这里整个过程就分析完了,所以整个过程相当于进行了三次异或,所以解密直接异或回去即可(其中一次是RC4的异或)。解密脚本如下
a=[0x00000000FCA8D10B,0x0000000043225D2C, 0x000000003DDA00BA, 0x000000007E8B2802, 0x0000000061C189F7, 0x00000000E4EAAF07, 0x00000000800FE27F, 0x00000000D6C3594F, 0x000000005653F16A, 0x0000000022EE3F49, 0x00000000B13760C5]
b=[0x7,0xf5,0xb0,0x4,0x2,0x5,0x14,0x9d,0x97,0x01,0xd5,0xbe,0x38,0x29,0x9b,0xa1,0xcc,0xa6,0xef,0xa9,0x0b,0x8c,0xdb,0x45,0x70,0xc1,0x26,0x20,0x7b, 0x22,0xe5,0x2c,0x53,0xce,0x5b,0x8f,0x64,0x3e,0xc4,0xfc,0xca,0x1a,0x67,0x1c]
flag=''
for i in range(len(a)):
#a[i]=a[i]^0x22222222^0x90604956
a[i]=a[i]^0x90604956
#print(hex(a[i]))
for i in a:
tmp=hex(i)
if(len(tmp)!=10):
tmp=tmp[:2]+'0'+tmp[2:]
for j in range(8,0,-2):
flag+=(tmp[j:j+2])
#print(tmp[j:j+2])
j=0
for i in range(0,len(flag)+1,2):
print(chr(int(flag[i:i+2],16)^b[j]),end='')
j+=1
if(j%4==0):
print(' ',end='')
因为上面的过程中对小于0的结果进行了一次异或,但是我们并不知道异或其是否是小于0,所以这里需要一下爆破,即需要执行两个版本的脚本,另一个版本就是在脚本中注释中的版本,对比两个版本的结果,因为已知其结果是一个b64,所以可以排除掉一些不和规则的结果

在剩余的结果中,只有一个组合是符合的,一组一组尝试后可以得到一个最终的b64结果

进行解码即可得到最终的flag。


