没报名,赛后问朋友要的题,看了看。

loser (Nononono!.exe)

赛中2解
该程序实现了一个类似Base64的算法和一个标准TEA解密算法,用来对输入数据进行编码和加密,并与加密后的结果进行比较,由于程序使用C++,结构体众多,逆向难度中等偏上。

首先是一个类似Base64的编码算法,开始做的时候测试了几个数据,看着很像base64但是其实并不是,算法是以3个字节为一组,每一个字节分别按位与 0x3f 用以获取低6位,然后第2个和第三个and后的数据是要换位置的,第四个字节是前面三个字节的高2位,所以没有加密只是编码,在下面Exp可以看如何解码。

其次是一个TEA解密,拿到key后我们只需要写一个TEA加密,就可以“解密”了。值得注意的是在我们加密前,需要对l和r两个参数进行xor ord('S')即可。
最后是enc了,我们搜索字符串常量right
2024-11-17T12:43:52.png
可以看出 unk_140031520 大概率就是enc了,我们双击进去进行X-Ref,发现它在下面的函数进行了初始化。
2024-11-17T12:44:33.png
copy下来,就可以写exp了。
一个特别小的注意点就是,enc是DWORD big-endian。

Exp:

from regadgets import *
from z3 import *
def decrypt(enc):
    assert len(enc) % 4 == 0
    table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    result = []
    for i in range(0, len(enc), 4):
        a1 = table.index(enc[i + 0])
        a2 = table.index(enc[i + 2])
        a3 = table.index(enc[i + 1])
        a4 = table.index(enc[i + 3])
        result.append(a1 | ((a4 & 0b110000) << 2))
        result.append(a2 | ((a4 & 0b001100) << 4))
        result.append(a3 | ((a4 & 0b000011) << 6))
    return bytes(result)

v4 = [0] * 48
v4[0] = 165
v4[1] = 100
v4[2] = 159
v4[3] = 4
v4[4] = 57
v4[5] = 183
v4[6] = 166
v4[7] = 23
v4[8] = 34
v4[9] = 205
v4[10] = 38
v4[11] = 77
v4[12] = 125
v4[13] = 16
v4[14] = 130
v4[15] = 219
v4[16] = 133
v4[17] = 219
v4[18] = 39
v4[19] = 57
v4[20] = 66
v4[21] = 60
v4[22] = 30
v4[23] = 165
v4[24] = 34
v4[25] = 205
v4[26] = 38
v4[27] = 77
v4[28] = 125
v4[29] = 16
v4[30] = 130
v4[31] = 219
v4[32] = 214
v4[33] = 55
v4[34] = 104
v4[35] = 128
v4[36] = 177
v4[37] = 249
v4[38] = 21
v4[39] = 25
v4[40] = 68
v4[41] = 24
v4[42] = 66
v4[43] = 36
v4[44] = 143
v4[45] = 120
v4[46] = 162
v4[47] = 44
print(len(v4))
v4 = byte2dword(v4, endian='big')
v4 = [i ^ ord('S') for i in v4]

dec = tea_encrypt(v4, key=[ord('L'), ord('Z'), ord('S'), ord('D')])
print(decrypt(dec.decode()))
# 48
# b'LZSDS{how_how_how_how_how_ow_ow_ow!}'

minire

有个elf的upx,随便找了个脱壳教程
https://blog.csdn.net/m0_49936845/article/details/119976496

main函数
2024-11-09T14:18:27.png

下面的else是假的,你需要手动传第一个参数是root才会进第一个条件。(顺便提一下,fake的flag是fksdde7039,MD5爆破出的)

然后去real里面,是一个真正让你输入的地方,不过只是输出了input:,真正的逻辑在下面那个函数。
但是核心函数基本无法直接反编译,我们直接看汇编吧。
2024-11-09T14:19:56.png

经典的VM(Handler + Dispatcher)
2024-11-09T14:20:26.png
我们可以找到一个getchar sub_402907然后就可以不断进行硬件断点跟数据了

注意这一块
2024-11-09T14:21:30.png

稍微分析一下
2024-11-09T14:22:16.png
2024-11-09T14:22:41.png
2024-11-09T14:22:59.png

然后我们下断点
2024-11-09T14:23:19.png
进行条件断点,打印值
2024-11-09T14:23:25.png

这样我们就trace了vm

x[0]^=4
x[0]+=12
x[0]^=11
x[0]^=12
x[0]-=2
x[0]-=1
x[0]^=6
x[1]+=10
x[1]^=12
x[1]+=5
x[2]+=4
x[2]+=14
x[3]-=10
x[3]-=3
x[3]+=13
x[3]+=7
x[3]-=9
x[3]^=14
x[4]-=7
x[4]-=15
x[5]^=14
x[6]^=2
x[6]+=0
x[6]^=2
x[6]+=9
x[6]+=3
x[6]-=2
x[6]+=13
x[6]^=1
x[7]+=8
x[7]+=12
x[7]^=15
x[7]+=5
x[7]^=3
x[7]+=8
x[8]+=8
x[8]+=2
x[8]^=8
x[8]-=12
x[8]+=11
x[8]-=3
x[8]^=9
x[8]-=2
x[8]+=8
x[9]-=0
x[9]-=2
x[10]+=11
x[11]-=2
x[11]^=7
x[11]-=1
x[11]-=5
x[12]+=1
x[12]-=13
x[12]+=12
x[13]-=2
x[13]-=14
x[13]-=9
x[13]^=14
x[13]+=1
x[13]+=10
x[13]-=7
x[13]-=1
x[13]+=9
x[14]-=0
x[14]-=11
x[14]^=4
x[14]+=9
x[15]^=14
x[15]+=5
x[15]-=12
x[15]-=4
x[15]-=4
x[15]+=15
x[15]+=14
x[15]-=4
x[15]^=5
x[15]-=12
x[16]^=11
x[16]+=13
x[16]-=11
x[16]^=4
x[16]+=10
x[16]-=8
x[17]+=10
x[17]+=15
x[17]+=2
x[17]-=6
x[17]-=9
x[17]-=9
x[17]+=3
x[17]+=5
x[17]-=15
x[17]+=2
x[18]-=14
x[18]-=13
x[19]^=7
x[19]-=15
x[19]-=1
x[19]^=3
x[19]-=3
x[19]+=11
x[19]+=10
x[19]+=10
x[20]+=8
x[20]-=6
x[20]-=7
x[20]^=4
x[20]-=1
x[20]^=3
x[21]+=5
x[21]+=2
x[21]+=10
x[21]^=0
x[22]-=7
x[22]+=0
x[22]+=8
x[22]+=1
x[22]+=1
x[22]^=10
x[22]-=14
x[22]^=15
x[22]-=7
x[22]^=8
x[23]^=4
x[23]-=9
x[23]+=15
x[24]+=12
x[24]^=2
x[24]^=4
x[24]-=7
x[24]+=1
x[25]+=0
x[25]+=9
x[25]^=2
x[25]+=14
x[25]^=11
x[25]^=1
x[25]+=2
x[25]+=9
x[25]-=9
x[26]+=6
x[27]^=10
x[27]-=4
x[27]-=13
x[27]^=8
x[27]-=14
x[27]+=14
x[27]^=14
x[28]+=1
x[28]^=4
x[28]-=9
x[28]+=9
x[28]-=5
x[28]+=13
x[28]+=1
x[28]^=10
x[29]^=9
x[30]+=14
x[30]+=12
x[30]^=0
x[30]-=0
x[30]-=15
x[30]^=11
x[30]-=11
x[30]+=8
x[31]+=11
x[31]+=6
x[31]+=1
x[31]^=12
x[31]-=6
x[31]-=14
x[32]-=11
x[32]^=13
x[32]+=5
x[32]^=2
x[32]-=2
x[33]+=13
x[33]^=6
x[33]+=15
x[33]^=0
x[33]-=3
x[33]-=12
x[33]-=15
x[33]^=11
x[34]+=9
x[34]+=10
x[34]+=10
x[34]^=10
x[35]-=13
x[36]^=7
x[36]-=0
x[37]-=11
x[37]+=14
x[37]-=8
x[37]+=4
x[37]+=3
x[37]+=13
x[37]^=3
x[37]^=10

在这之后,我们需要寻找enc(标准加密值)
我们在vm_readByte处下断,然后我们就可以看到enc不断浮现在我们眼前。
最后脚本一把梭

from regadgets import *
from z3 import *
from copy import deepcopy
x = [BitVec(f"x{i}", 8) for i in range(38)]
y = deepcopy(x)

x[0]^=4
x[0]+=12
x[0]^=11
x[0]^=12
x[0]-=2
x[0]-=1
x[0]^=6
x[1]+=10
x[1]^=12
x[1]+=5
x[2]+=4
x[2]+=14
x[3]-=10
x[3]-=3
x[3]+=13
x[3]+=7
x[3]-=9
x[3]^=14
x[4]-=7
x[4]-=15
x[5]^=14
x[6]^=2
x[6]+=0
x[6]^=2
x[6]+=9
x[6]+=3
x[6]-=2
x[6]+=13
x[6]^=1
x[7]+=8
x[7]+=12
x[7]^=15
x[7]+=5
x[7]^=3
x[7]+=8
x[8]+=8
x[8]+=2
x[8]^=8
x[8]-=12
x[8]+=11
x[8]-=3
x[8]^=9
x[8]-=2
x[8]+=8
x[9]-=0
x[9]-=2
x[10]+=11
x[11]-=2
x[11]^=7
x[11]-=1
x[11]-=5
x[12]+=1
x[12]-=13
x[12]+=12
x[13]-=2
x[13]-=14
x[13]-=9
x[13]^=14
x[13]+=1
x[13]+=10
x[13]-=7
x[13]-=1
x[13]+=9
x[14]-=0
x[14]-=11
x[14]^=4
x[14]+=9
x[15]^=14
x[15]+=5
x[15]-=12
x[15]-=4
x[15]-=4
x[15]+=15
x[15]+=14
x[15]-=4
x[15]^=5
x[15]-=12
x[16]^=11
x[16]+=13
x[16]-=11
x[16]^=4
x[16]+=10
x[16]-=8
x[17]+=10
x[17]+=15
x[17]+=2
x[17]-=6
x[17]-=9
x[17]-=9
x[17]+=3
x[17]+=5
x[17]-=15
x[17]+=2
x[18]-=14
x[18]-=13
x[19]^=7
x[19]-=15
x[19]-=1
x[19]^=3
x[19]-=3
x[19]+=11
x[19]+=10
x[19]+=10
x[20]+=8
x[20]-=6
x[20]-=7
x[20]^=4
x[20]-=1
x[20]^=3
x[21]+=5
x[21]+=2
x[21]+=10
x[21]^=0
x[22]-=7
x[22]+=0
x[22]+=8
x[22]+=1
x[22]+=1
x[22]^=10
x[22]-=14
x[22]^=15
x[22]-=7
x[22]^=8
x[23]^=4
x[23]-=9
x[23]+=15
x[24]+=12
x[24]^=2
x[24]^=4
x[24]-=7
x[24]+=1
x[25]+=0
x[25]+=9
x[25]^=2
x[25]+=14
x[25]^=11
x[25]^=1
x[25]+=2
x[25]+=9
x[25]-=9
x[26]+=6
x[27]^=10
x[27]-=4
x[27]-=13
x[27]^=8
x[27]-=14
x[27]+=14
x[27]^=14
x[28]+=1
x[28]^=4
x[28]-=9
x[28]+=9
x[28]-=5
x[28]+=13
x[28]+=1
x[28]^=10
x[29]^=9
x[30]+=14
x[30]+=12
x[30]^=0
x[30]-=0
x[30]-=15
x[30]^=11
x[30]-=11
x[30]+=8
x[31]+=11
x[31]+=6
x[31]+=1
x[31]^=12
x[31]-=6
x[31]-=14
x[32]-=11
x[32]^=13
x[32]+=5
x[32]^=2
x[32]-=2
x[33]+=13
x[33]^=6
x[33]+=15
x[33]^=0
x[33]-=3
x[33]-=12
x[33]-=15
x[33]^=11
x[34]+=9
x[34]+=10
x[34]+=10
x[34]^=10
x[35]-=13
x[36]^=7
x[36]-=0
x[37]-=11
x[37]+=14
x[37]-=8
x[37]+=4
x[37]+=3
x[37]+=13
x[37]^=3
x[37]^=10

s = Solver()
enc = [0x60, 0x7F, 0x73, 0x6B, 0x65, 0x4F, 0x80, 0x5D, 0x64, 0x50, 0x64, 0x2C, 0x37, 0x33, 0x5C, 0x74, 0x45, 0x65, 0x55, 0x60, 0x4A, 0x84, 0x6E, 0x50, 0x7F, 0x58, 0x5F, 0x27, 0x7F, 0x5A, 0x8C, 0x6B, 0x62, 0x60, 0x59, 0x59, 0x45, 0x85]

for i in range(len(x)):
    s.add(enc[i] == x[i])
for m in z3_get_models(s):
    print(m)
    for i in y:
        print(chr(m[i].as_long()), end='')
    print('')
# flag{AjJIRY77BbuNgpPSswNwCY8gSyawo6fB}

joyVBS

纯送分题
https://www.onlinegdb.com/online_vb_compiler
print出来代码

assembly 'a, Version=0.0, Culture=neutral, PublicKeyToken=null' saved successfully to '/home/a.out'.
Compilation successful
Compilation took 00:00:00.7942080
MsgBox "VBScript, often abbreviated as VBS, is an event-driven programming language developed by Microsoft, primarily used for scripting in the Windows environment."
MsgBox "It is based on the Visual Basic programming language and is designed to be simple and easy to use, especially for those familiar with the BASIC programming language."
MsgBox "And for me, it is the first programming language that I've leart"
MsgBox "Hackers! Have fun with this VBS challenge!"
flag = InputBox("Enter the FLAG:", "Hack for fun")
wefbuwiue = "NalvN3hKExBtALBtInPtNHTnKJ80L3JtqxTboRA/MbF3LnT0L2zHL2SlqnPtJLAnFbIlL2SnFT8lpzFzA2JHrRTiNmT9"

qwfe = 9+2+2+1

Function Base64Decode(base64EncodedString)
    Dim xml, elem
    Set xml = CreateObject("MSXML2.DOMDocument")
    Set elem = xml.createElement("tmp")
    elem.dataType = "bin.base64" 
    elem.text = base64EncodedString 
    Dim stream
    Set stream = CreateObject("ADODB.Stream")
    stream.Type = 1 'Binary
    stream.Open
    stream.Write elem.nodeTypedValue 
    stream.Position = 0
    stream.Type = 2 'Text
    stream.Charset = "utf-8"
    Base64Decode = stream.ReadText
    stream.Close
End Function
Function Caesar(str,offset)
        Dim length,char,i
        Caesar = ""
        length = Len(str)
        For i = 1 To length
                char = Mid(str,i,1)
                If char >= "A" And char <= "Z" Then
                        char = Asc("A") + (Asc(char) - Asc("A") + offset) Mod 26
                        Caesar = Caesar & Chr(char)
                ElseIf char >= "a" And char <= "z" Then
                        char = Asc("a") + (Asc(char) - Asc("a") + offset) Mod 26
                        Caesar = Caesar & Chr(char)
                Else
                        Caesar = Caesar & char
                End If
        Next
End Function

If flag = Base64Decode(Caesar(wefbuwiue, 26-qwfe)) Then
    MsgBox "Congratulations! Correct  FLAG!"
Else
    MsgBox "Wrong flag."
End If

凯撒加密+base64
2024-11-09T14:26:36.png
flag{VB3_1s_S0_e1sY_4_u_r1gh3?btw_1t_iS_a1s0_Us3Fu1_a3D_1nTe3eSt1ng!}

exec

Python Function Hook

import base64
hook_exec = exec
def my_exec(x):
    print('myexec', x)
    hook_exec(x)
exec = my_exec
...

这样就能拿到每次exec的代码,从而得到


a=True
len=len
G=list
g=range
s=next
R=bytes
o=input
Y=print
def l(S):
 i=0
 j=0
 while a:
  i=(i+1)%256
  j=(j+S[i])%256
  S[i],S[j]=S[j],S[i]
  K=S[(S[i]+S[j])%256]
  yield K
def N(key,O):
 I=len(key)
 S=G(g(256))
 j=0
 for i in g(256):
  j=(j+S[i]+key[i%I])%256
  S[i],S[j]=S[j],S[i]
 z=l(S)
 n=[]
 for k in O:
  n.append(s(z)+2)
 return bytes(n).hex()
def E(s,parts_num):
 Q=len(s.decode())
 S=Q//parts_num
 u=Q%parts_num
 W=[]
 j=0
 for i in g(parts_num):
  T=j+S
  if u>0:
   T+=1
   u-=1
  W.append(s[j:T])
  j=T
 return W
if __name__=='__main__':
 L=o('input the flag: >>> ').encode()
 assert len(L)%2==0,'flag length should be even'
 t=b'v3ry_s3cr3t_p@ssw0rd'
 O=E(L,2)
 U=[]
 for i in O:
  U.append(N(t,i))
 print(U)
 if U==['1796972c348bc4fe7a1930b833ff10a80ab281627731ab705dacacfef2e2804d74ab6bc19f60','2ea999141a8cc9e47975269340c177c726a8aa732953a66a6af183bcd9cec8464a']:
  Y('Congratulations! You got the flag!')
 else:
  Y('Wrong flag!')

无法直接运行是因为U的第二个少了个',补上就行,上面代码我稍微改了一下,输出魔改rc4的keystream
然后直接解就行
2024-11-09T14:27:19.png
flag{thEn_I_Ca5_BE_YoUR_Onl7_ExeCUti6n_So_Use_m3_t0_R0n_tH17_Ex3Cuti0n}

RE5

异常处理改了tea的key,每一轮的sum值是由srand(0),每次取随机数相加得到的,然后直接解标准tea即可。

from regadgets import *
from typing import List, Tuple, Union
from ctypes import c_uint32
rng = WindowsRand(0)
def tea_decrypt_plus(
    src: Union[Tuple[int, int], bytes, List[int]], key: Union[List[int], bytes], delta: int = 0x9E3779B9, rounds: int = 32
) -> Union[Tuple[int, int], bytes, List[int]]:
    if type(src) == bytes:
        result = b''
        for i in pack_dword(byte2dword(src)):
            result += dword2byte(tea_decrypt_plus(i, key, delta, rounds))
        return result
    elif type(src) == list:
        result = b''
        for i in pack_dword(src):
            result += dword2byte(tea_decrypt_plus(i, key, delta, rounds))
        return result
    elif type(src) != tuple:
        raise "wrong src type"
    # For bytes key
    _rands = rng.rands(32)
    if type(key) == bytes:
        key = byte2dword(key)
    elif type(key) != list:
        raise "wrong key type"
    l, r = c_uint32(src[0]), c_uint32(src[1])
    _sum = c_uint32(sum(_rands))
    k = [c_uint32(i) for i in key]
    for i in range(rounds):
        r.value -= (
            ((l.value << 4) + k[2].value)
            ^ (l.value + _sum.value)
            ^ ((l.value >> 5) + k[3].value)
        )
        l.value -= (
            ((r.value << 4) + k[0].value)
            ^ (r.value + _sum.value)
            ^ ((r.value >> 5) + k[1].value)
        )
        _sum.value -= _rands[rounds - i - 1]
    return (l.value, r.value)

enc = b"\xF8\x63\x20\xEA\x52\xF2\x66\x8F\xEF\x72\x2A\x90\x74\xDA\x1F\x41\x4D\x0D\x59\x19\x17\x43\xE7\xCA\x3F\x0F\x87\x63\x61\xAE\x53\xD7\x22\x3D\x43\x4D\xDD\xC2\xBC\xB2\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x2F\x00\x00\x00\x01\x00\x00\x00\x66\x6C\x61\x67\x7B\x31\x32\x33\x31\x34\x31\x32\x33\x34\x31\x32\x34\x31\x32\x34\x32\x31\x33\x34\x31\x32\x33\x34\x31\x32\x33\x31\x32\x34\x33\x32\x33\x7D\x00\x00\x39\xDC\xE1\x2E\xF1\xEA\xD6\x40\x9A\x76\x29\x5E\x17\xB6\xF4\x38\xD0\x14\xF5\x8C\xA2\x7E\xEB\xBE\xD5\xFA\xBD\x18\xBF\x05\x97\x49"
# enc = b"\x9A\x76\x29\x5E\x17\xB6\xF4\x38"
# enc = b"\x39\xDC\xE1\x2E\xF1\xEA\xD6\x40"
enc = byte2dword(enc)

# print(tea_decrypt(enc, key=[2,2,3,4]))
print(tea_decrypt_plus(enc, key=[2,2,3,3]))

flag{d555ce75ec293c8ed232d83dffb0ff82} 三血

BigTea

唯一的一血,全程黑箱trace+猜的,控制流混淆太恶心了
Xor Trace,有小数字(0~3的xor),对应xxtea的key[(p & 3) ^ e] ^ z,所以直接认为是xxtea

1287150135 = 858927483 ^ 2139777868
3 = 3 ^ 0
3083858674 = 2100375857 ^ 3405693891
3475065957 = 3435709932 ^ 65636745
3581236543 = 3541242640 ^ 107365935
2686381197 = 76041513 ^ 2761335204
1270372984 = 875704628 ^ 2139777868
2 = 3 ^ 1
.....
2296010693 = 1761772981 ^ 3789083248
3006293146 = 1572571602 ^ 4002147656
0 = 2 ^ 2
1724993655 = 425409339 ^ 2139777868
1982135953 = 1995319112 ^ 13294041
2651112074 = 2511582128 ^ 196571450
237532170 = 436319505 ^ 338280731
3939128127 = 71417463 ^ 4002147656
1 = 2 ^ 3
2522458527 = 141479974 ^ 2654435769
289771357 = 285669852 ^ 4421249
2254779822 = 2263679584 ^ 8927182
378091989 = 2166619358 ^ 2544551179

我们慢慢分析,XXTEA的key,可以从Trace里面盯出来,前面异或算出来的是索引值,所以我们很容易就能拿到四个key,然后我们输入11112222作为待加密数据,由于xxtea的特性,z==y,那么我们很方便的可以看到下面四个值在trace中的样子,然后可以倒推出delta = 0x70D7D4CC

Ly = y.value << 2
Ry = y.value >> 3
Lz = z.value << 4
Rz = z.value >> 5 
keys
0x7f8a6b4c
0x9e3779b9
0xdeafbeef
0xcafec3c3

2024-11-09T14:28:46.png
然后,我们可以使用自己的xxtea加密数据,发现我们的加密数据只在trace的中间,而不是最后,说明加密可能不只一轮或者是xxtea魔改轮数,经过测试是后者,通过fuzz,我们可以知道魔改是 6 + 52//n -> 32 + 52 // n,我们抄出来就行了,最后至于找enc,是通过在最后一轮对于密文下断,然后在程序内存中搜索第一个加密的,进行硬件断点,然后跑,就可以找到cmp。
2024-11-09T14:29:18.png
然后
2024-11-09T14:29:27.png
我们可以观察到下面对cl进行的操作,cl如果不为0则两段密文不一样,我们每次运行打断点手动置0,然后输入很长的input,就可以拿到所有的对比值

cmp 673017408,   1214171175
cmp 3365566770,  3066933611
cmp 1583712898,  4062421290
cmp 1719532837,  3922368852
cmp 2253378100,  2540993788
cmp 1994934834,  1332676358
cmp 4110442914,  22469667
cmp 4185531028,  3633624522
cmp 1279845426,  2241914041
cmp 1481920662,  3542748258
cmp 725179328,   1546291565

最后,使用regadgets库(由于还在开发,小范围测试,所以把库内的代码都复制了出来)进行解密。即可。

from typing import List, Union
from ctypes import c_uint32

def xxtea_std_shift(z, y, sum, k, p, debug = False):
    if debug:
        print("-----------------XXTEA_STD_SHIFT-----------------")
    e = (sum.value >> 2) & 3
    PE = (p & 3) ^ e
    Ly = y.value << 2
    Ry = y.value >> 3
    Lz = z.value << 4
    Rz = z.value >> 5 

    LzRy = Rz ^ Ly
    LyRz = Ry ^ Lz
    SY = sum.value ^ y.value
    K = k[PE].value
    KZ = K ^ z.value
    result = (LzRy + LyRz) ^ (KZ + SY)
    if debug:
        print("sum = ", hex(sum.value))
        print("e   = ", hex(e))
        print("PE  = ", hex(PE))
        print("SY  = ", hex(SY))
        print("z   = ", hex(z.value))
        print("y   = ", hex(y.value))
        print("Ly  = ", hex(Ly))
        print("Ry  = ", hex(Ry))
        print("Lz  = ", hex(Lz))
        print("Rz  = ", hex(Rz))
        print("LzRy= ", hex(LzRy & 0xffffffff))
        print("LyRz= ", hex(LyRz & 0xffffffff))
        print("K   = ", hex(K))
        print("KZ  = ", hex(KZ))
        print("ret = ", hex(result & 0xffffffff))
        print("-----------------XXTEA_STD_SHIFT-----------------")
    return result

def xxtea_decrypt(
    src: Union[List[int], bytes],
    key: List[int],
    delta: int = 0x9E3779B9,
    round_base: int = 6,
    round_addi: int = 52,
    shift_func=xxtea_std_shift,
    debug=False,
) -> Union[List[int], bytes]:
    in_bytes = False
    if type(src) == bytes:
        src = byte2dword(src)
        in_bytes = True
    if type(key) == bytes:
        key = byte2dword(key)
    if in_bytes:
        return dword2byte(xxtea_decrypt(src, key, delta, round_base, round_addi, shift_func, debug))
    src = [c_uint32(i) for i in src]
    key = [c_uint32(i) for i in key]
    sum, e, y = c_uint32(0), c_uint32(0), c_uint32(0)
    delta = c_uint32(delta)
    n = len(src)
    rounds = round_base + round_addi // n
    sum.value = rounds * delta.value
    y = src[0]
    for _ in range(rounds):
        for p in range(n - 1, 0, -1):
            z = src[p - 1]
            shift_result = shift_func(z, y, sum, key, p, debug)
            src[p].value -= shift_result 
            y = src[p]
        p -= 1
        z = src[n - 1]
        shift_result = shift_func(z, y, sum, key, p, debug)
        src[0].value -= shift_result
        y = src[0]
        sum.value -= delta.value
    return [i.value for i in src]


enc = [1214171175,3066933611,4062421290,3922368852,2540993788,1332676358,22469667,3633624522,2241914041,3542748258,1546291565]
enc = xxtea_decrypt(enc, key=[0x7f8a6b4c, 0x9e3779b9, 0xdeafbeef, 0xcafec3c3],delta=0x7f8a6b4c, round_base=32)
print(dword2byte(enc))
# b'flag{9aad3962-8ad5-48d0-83dc-1e60a81439a1}\x00\x00'

Rafflesia

动态调试,有反调试,直接用ScyllaHide过掉。
base64换表,base64稍微改了一下:最后xor了0x18
最后在memcmp下断拿密文就行
2024-11-09T14:30:14.png

FlvtterM

Blutter逆向
然后就没时间做了,看到个换表base58,前面有一个x[i+1] ^= x[i]和一个换位置,但是最前面还有一个SBox相关的操作,SBox这个没看出来是什么。

ez_vm

程序获取argv,也就是启动程序的参数(是十六进制数),然后就parse成buffer,走两次加密,一次16字节,两次互相不影响。
加密流程如下,从内存中dump出来三个table,然后就嗯调,抄出来东西(python)如下。

from typing import List, Tuple
from struct import unpack, pack

# retval: (sbox, inv_sbox)
def generate_sbox(_from: bytes, _to: bytes) -> Tuple[List[int], List[int]]:
    inv_sbox = [_to.index(i) for i in _from]
    s_box = [_from.index(i) for i in _to]
    return s_box, inv_sbox

def sbox_transform(_from: bytes, box: List[int]):
    r = [_from[box[i]] for i in range(len(_from))]
    if type(_from) == bytes:
        return bytes(r)
    else:
        return r
        
def byte2dword(x: List[int]):
    if len(x) % 4 != 0:
        if type(x) == bytes:
            x += b'\x00' * (4 - (len(x) % 4))
        else:
            x += [0] * (4 - (len(x) % 4))
    return [v[0] for v in (unpack('<I', bytes(x[i:i+4])) for i in range(0, len(x), 4))]

table1 = byte2dword(open('table1.bin', 'rb').read())
table2 = open('table2.bin', 'rb').read()
table3 = open('table3.bin', 'rb').read()
xtime = lambda x, y: (x // 2 ** y) & 0xf
before = bytes.fromhex('01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00')
after  = bytes.fromhex('01 06 0B 00 05 0A 0F 04 09 0E 03 08 0D 02 07 0C')
box, ibox = generate_sbox(before, after)

def one_time(x, ctr):
    r = [0, 0, 0, 0]
    r[0] = table2[xtime(table1[x[0]], ctr) << 4 | xtime(table1[0x100 + x[1]], ctr)]
    r[1] = table2[xtime(table1[0x200 + x[2]], ctr) << 4 | xtime(table1[0x300 + x[3]], ctr)]
    r[2] = table2[xtime(table1[x[0]], ctr - 4) << 4 | xtime(table1[0x100 + x[1]], ctr - 4)]
    r[3] = table2[xtime(table1[0x200 + x[2]], ctr - 4) << 4 | xtime(table1[0x300 + x[3]], ctr - 4)]
    return (r[0] ^ r[1]) << 4 | (r[2] ^ r[3])

def magic(x):
    r = [0, 0, 0, 0]
    r[0] = one_time(x, 28)
    r[1] = one_time(x, 20)
    r[2] = one_time(x, 12)
    r[3] = one_time(x, 4)
    return r

def encrypt(src, offset):
    src = sbox_transform(src, box)
    result = []
    for i in range(0, 16, 4):
        r = src[i:i+4]
        r = magic([j | i << 8 | (offset) << 12 for j in r])
        r = magic([j | i << 8 | (9 + offset) << 12 for j in r])
        result.extend(r)
    return result

def denc(src: bytes):
    for i in range(9):
        src = encrypt(src, i)
    src = sbox_transform(src, box)
    src = [table3[src[i] + (i << 8)] for i in range(len(src))]
    return src

if __name__ == '__main__':
    # 测试的一组加密数据
    t = list(bytes.fromhex('FE DC BA 98 76 54 32 10 FE DC BA 98 76 54 32 10'))
    t = denc(t)
    print([hex(i) for i in t])
    # 测试的加密结果
    # ['0x6c', '0x53', '0xfc', '0xe5', '0x4', '0xf6', '0x93', '0x1a', '0xdb', '0x25', '0xfd', '0x81', '0xeb', '0xde', '0x5b', '0x6d']

# 真正的enc(32字节,两次加密后的结果)
enc = b"\xC4\x0C\xC0\x20\xFC\x48\xF6\xD2\x6C\xD2\xFC\x2B\x5C\xA7\x2E\x65\x41\xFE\x0E\x64\x05\x6E\xD5\x9C\xCC\x41\x1D\x10\xBE\xA0\xF5\x09"

但是其实可以直接binwalk,发现一堆AES S-Box,结合上面逆向(赤石)出来的,我们基本上可以确定是AES白盒
2024-11-04T11:47:15.png

AES白盒,使用DFA脚本
需要使用dfa攻击恢复出密钥
观察到前九轮都是使用encrypt
最后进行了一次transform
说明应该在第九轮注入故障

def denc(src: bytes, pos, cb):
    for i in range(9):
        if i == 8:
            src[pos] = random.randint(0,255)
        src = encrypt(src, i)
    src = sbox_transform(src, box)
    src = [table3[src[i] + (i << 8)] for i in range(len(src))]
    return src

产生的数据4字节不同,符合特征
使用phoenixAES进行恢复最后一轮密钥

import phoenixAES
phoenixAES.crack_file('tracefile', [], True, False, 3)

得到BF2256727EF09577C7F720C7D84D697A
使用stark恢复第一轮密钥

aes_keyschedule.exe BF2256727EF09577C7F720C7D84D697A 10
K00: 77656C636F6D65746F71776232303234
K01: 724674401D2B1134725A6656406A5462
K02: 7266DE496F4DCF7D1D17A92B5D7DFD49
K03: 8932E505E67F2A78FB688353A6157E1A
K04: D8C147213EBE6D59C5D6EE0A63C39010
K05: E6A18DDAD81FE0831DC90E897E0A9E99
K06: A1AA632979B583AA647C8D231A7613BA
K07: D9D7978BA0621421C41E9902DE688AB8
K08: 1CA9FB96BCCBEFB778D576B5A6BDFC0D
K09: 7D192CB2C1D2C305B907B5B01FBA49BD
K10: BF2256727EF09577C7F720C7D84D697A

恢复密钥welcometoqwb2024
拿到password后,解密就行了。

from Crypto.Cipher import AES

password = b'welcometoqwb2024'
text = b"\xC4\x0C\xC0\x20\xFC\x48\xF6\xD2\x6C\xD2\xFC\x2B\x5C\xA7\x2E\x65\x41\xFE\x0E\x64\x05\x6E\xD5\x9C\xCC\x41\x1D\x10\xBE\xA0\xF5\x09"  # 需要加密的内容,bytes类型
aes = AES.new(password, AES.MODE_ECB)
den_text = aes.decrypt(text)
print("明文:", den_text)
# 明文: b'7f28bc5e9f3f149525cedf0bf6606cf0'

mips

emu是魔改的qemu-6.2.0

file mips_bin
mips_bin: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, not stripped

发现是大端序,可以通过如下方法动态调试

qemu-mips -g 12345 ./mips_bin
#另外开一个窗口
gdb-multiarch ./mips_bin
set arch mips
set endian big
target remote localhost:12345

2024-11-04T11:49:01.png
手动改掉v8的值进入子进程中

a="sxrujtv`labiVzbp`vpg|"
for i in range(21):
     print(chr(ord(a[i])^(0x15-i)),end="")

得到fake flag
正常的qemu使用时应该没有提示输入的信息
2024-11-04T11:49:21.png
2024-11-04T11:49:27.png

./emu -d 可以打印一些翻译的语句的trace, 基本可以确定翻译前后, 指令语义未发生变化
当输入乱打的flag时, 会走到0x3fc 0x404 0x408就是wrong那一块, 输出wrong
当输入fake flag时, 会走到0x3e4 0x3e8 0x3ec就是right那一块, 但是同样输出wrong
要么这个check根本不重要, 有另一个check
emu sub_3DE49E
Hook syscall read(case 4003)校验flag{}格式
2024-11-04T11:49:54.png
hook syscall write(case 4004)修改输出
2024-11-04T11:50:03.png

交叉:引用if块里面第2个全局变量dword_C3231C找到check, 花指令简单nop掉
sub_33D8E0:

__int64 __fastcall sub_33D8E0(__int64 a1)
{
  __int64 result; // rax
  int v2; // [rsp+10h] [rbp-20h]
  int i; // [rsp+14h] [rbp-1Ch]
  int j; // [rsp+18h] [rbp-18h]
  __int64 v5; // [rsp+20h] [rbp-10h]
  __int64 v6; // [rsp+28h] [rbp-8h]

  v5 = *(a1 + 528);
  v2 = 0;
  result = *(v5 + 128);
  if ( *(v5 + 128) == 0x23000 )
  {
    result = format_check;
    if ( format_check )
    {
      v6 = sub_33D48E(&unk_C33280);
      for ( i = 0; i <= 21; ++i )
        *(i + v6) ^= dword_C32324;
      sub_33D886(v6, 7LL, 11LL);
      result = sub_33D886(v6, 12LL, 16LL);
      for ( j = 0; j <= 21; ++j )
      {
        result = dword_B9CA80[j];
        if ( *(j + v6) != result )
        {
          v2 = 1;
          break;
        }
      }
      if ( !v2 && j == 22 )
        dword_C3231C = 1;
    }
  }
  return result;
}

前面rc4的部分应该没啥问题: sub_33D48E里面

def rc4_init(s, key, key_len):
    j = 0
    for i in range(256):
        j = (j + s[i] + key[i%key_len])%256
        tmp = s[i]
        s[i] = s[j]
        s[j] = tmp

def rc4_generate_keystream(s, length):
    i = 0
    j = 0
    key_stream = []
    while length:
        i = (i + 1) % 256    # 可以保证每256次循环后s盒中的每个元素至少被交换一次
        j = (j + s[i]) % 256
        tmp = s[i]
        s[i] = s[j]
        s[j] = tmp
        key_stream.append(s[(s[i] + s[j]) % 256])
        length -= 1
    return key_stream

def main():
    key = [ord(i) for i in "6105t3"]      # 准备一些变量
    key_len = len(key)
    enc = [0xC4, 0xEE, 0x3C, 0xBB, 0xE7, 0xFD, 0x67, 0x1D, 0xF8, 0x97, 0x68, 0x9D, 0x0B, 0x7F, 0xC7, 0x80, 0xDF, 0xF9, 0x4B, 0xA0, 0x46, 0x91]

    enc_len = len(enc)
    cipher = [0] * enc_len
    print(enc_len)

    s = [i for i in range(256)]    # 初始化s盒
    rc4_init(s, key, key_len)      # 使用key打乱s盒
    key_stream = rc4_generate_keystream(s[:], enc_len) # 生成密钥流

然后异或一个key2和上面生成的keystream

key2 = [0xDE, 0xAD, 0xBE, 0xEF]
    for i in range(enc_len):     # 逐字节异或加密
        cipher[i] = enc[i] ^ key_stream[i] ^ key2[i % 4]

还有注意sub_33D48E外面还有一个异或:

for ( i = 0; i <= 21; ++i )
      a1a[i] ^= dword_C32324;

我们整理一下思路
SRC -> 移位加密 -> xor_cycle([0xDE, 0xAD, 0xBE, 0xEF]) -> RC4 -> XOR单字节 -> 两次交换 -> ENC

写出解题脚本就可以了,移位加密我实在不会逆,所以Z3解决了

from regadgets import *
from z3 import *
from copy import deepcopy

'''
swap(a1, 7, 11);
swap(a1, 12, 16);
'''
from z3 import *

for i in range(256):
    enc = [0x000000C4, 0x000000EE, 0x0000003C, 0x000000BB, 0x000000E7, 0x000000FD, 0x00000067, 0x0000001D, 0x000000F8, 0x00000097, 0x00000068, 0x0000009D, 0x0000000B, 0x0000007F, 0x000000C7, 0x00000080, 0x000000DF, 0x000000F9, 0x0000004B, 0x000000A0, 0x00000046, 0x00000091]
    l = len(enc)
    enc[7], enc[11] = enc[11], enc[7]
    enc[12], enc[16] = enc[16], enc[12]
    enc = bxor_cycle(enc, [i])
    enc = rc4_crypt(rc4_init(b'6105t3'), enc)
    enc = bxor_cycle(enc, [0xDE, 0xAD, 0xBE, 0xEF])
    x = [BitVec(f"x{i}", 8) for i in range(l)]
    s = Solver()
    for j in range(len(enc)):
        v3 = ((RotateRight(x[j], 1) << 6) ^ 0xC0 | LShR(RotateRight(x[j], 1), 2) ^ 0x3B) ^ 0xBE
        temp = RotateRight(v3, 3) ^ 0xAD
        v1 = RotateRight(temp, 4) ^ 0xDE 
        s.add(RotateRight(v1, 5) == enc[j])
    s.check()
    m = s.model()
    r = []
    for i in x:
        r.append(m[i].as_long())
    r = bytes(r)
    def is_printable(byte_data):
        return all(32 <= b <= 126 for b in byte_data) 
    if is_printable(r):
        print(r)
 '''
 b'T`HpZw6s6wv6lk<ZmEfn3x'
b'UaIq[v7r7vw7mj=[lDgo2y'
b'VbJrXu4q4ut4ni>XoGdl1z'
b'WcKsYt5p5tu5oh?YnFem0{'
b'PdLt^s2w2sr2ho8^iAbj7|'
b'QeMu_r3v3rs3in9_h@ck6}'
b'RfNv\\q0u0qp0jm:\\kC`h5~'
b'^jBzP}<y<}|<fa6PgOld9r'
b'_kC{Q|=x=|}=g`7QfNme8s'
b'YmE}Wz;~;z{;af1W`Hkc>u'
b'ZnF~Ty8}8yx8be2TcKh`=v'
b'DpX`Jg&c&gf&|{,J}Uv~#h'
b'Au]eOb#f#bc#y~)OxPs{&m'
b'Bv^fLa e a` z}*L{Spx%n'
b'Cw_gM`!d!`a!{|+MzRqy$o'
b'LxPhBo.k.on.ts$Bu]~v+`'
b'NzRj@m,i,ml,vq&@w_|t)b'
b"O{SkAl-h-lm-wp'Av^}u(c"
b'H|TlFk*o*kj*pw FqYzr/d'
b'I}UmGj+n+jk+qv!GpX{s.e'
b'J~VnDi(m(ih(ru"Ds[xp-f'
'''
flag{QeMu_r3v3rs3in9_h@ck6}

斯内克

算法题,中途下架了
下架之前:
每走一步会对目标函数地址运算一次,然后和某16位结果比较,相同就执行这个函数,返回值为一时成功,输入就是这个函数的参数
重新上线之后:
每次拐弯会对目标函数地址运算一次,然后和某16位结果比较,相同就执行这个函数,返回值为一时成功,输入就是这个函数的参数
rand()%20生成食物的坐标x和y,srand(0xdeadbeef)
sub_1400121E0是 哈希 MD5的Init,里面有4个魔数
hash_Md5有三个参数,第一个是函数内容,第二个是函数大小,第三个是retval,返回一个16字节的MD5 buffer
2024-11-04T11:53:25.png

然后我们大概可以了解逻辑

from typing import *
from copy import deepcopy
from hashlib import md5

class WindowsRand():
    def __init__(self, seed: int):
        self.holdrand = seed
    
    def rand(self) -> int:
        self.holdrand = self.holdrand * 214013 + 2531011
        return (self.holdrand >> 16) & 0x7fff
    
    def rands(self, count: int) -> List[int]:
        return [self.rand() for _ in range(count)]

def ror8(x, n):
    n &= 7
    return ((x >> n) | (x << (8 - n))) & 0xFF

a = [0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x38, 0x4C, 0xB0, 0x38, 0x6D, 0xEE, 0x3F, 0xC4, 0xB4, 0xB4, 0x09, 0x6A, 0xF0, 0x38, 0x2C, 0x79, 0xF6, 0x34, 0xE9, 0x89, 0x38, 0xAC, 0x7F, 0x35, 0xD4, 0xB4, 0xB4, 0x38, 0x6D, 0x77, 0xF6, 0xB6, 0x38, 0x6D, 0x78, 0xF6, 0xB6, 0x2B, 0x18, 0xB4, 0xB4, 0xB4, 0x3B, 0x81, 0x81, 0x81, 0x81, 0xEF, 0x4E, 0x38, 0x4C, 0x7D, 0xF6, 0x33, 0xD4, 0xB4, 0xB4, 0xB0, 0xE8, 0xF4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB0, 0xE8, 0xF6, 0x2B, 0x27, 0xA3, 0x1D, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xB4, 0xB0, 0xF8, 0x04, 0x38, 0x89, 0xE3, 0xC3, 0xCA, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xC4, 0xB0, 0xF8, 0x04, 0x38, 0xB3, 0x67, 0xE3, 0x16, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xD4, 0xB0, 0xF8, 0x04, 0x38, 0xB6, 0xD3, 0xB6, 0xA9, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xE4, 0xB0, 0xF8, 0x04, 0x38, 0x89, 0xD8, 0xC7, 0x33, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xB4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xB4, 0x38, 0x4C, 0xED, 0xB5, 0xD4, 0xB4, 0xB4, 0x4C, 0xF4, 0xD4, 0x2C, 0xF8, 0x85, 0x37, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xC4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xC4, 0x38, 0x4C, 0xED, 0xB5, 0xD4, 0xB4, 0xB4, 0x4C, 0xF4, 0xD4, 0x2C, 0xF8, 0x85, 0x37, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xD4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xD4, 0x38, 0x4C, 0xED, 0xB5, 0xD4, 0xB4, 0xB4, 0x4C, 0xF4, 0xD4, 0x2C, 0xF8, 0x85, 0x37, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xE4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xE4, 0x38, 0x4C, 0xED, 0xB5, 0xD4, 0xB4, 0xB4, 0x4C, 0xF4, 0xD4, 0x2C, 0xF8, 0x85, 0x37, 0xB0, 0xEC, 0xFE, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0x6F, 0x14, 0x4C, 0xEC, 0xFE, 0xB4, 0xB4, 0xB4, 0x2F, 0xC0, 0x2C, 0xEC, 0xFE, 0xB4, 0xB4, 0xB4, 0xCC, 0x6C, 0xFE, 0xB4, 0xB4, 0xB4, 0xB6, 0x24, 0xCC, 0x72, 0xB4, 0xB4, 0xB4, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xB4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xC4, 0x4C, 0x79, 0x85, 0x37, 0xD0, 0xD2, 0xF4, 0x5B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xE1, 0xC4, 0x4C, 0xF9, 0x05, 0x37, 0xD0, 0x62, 0x04, 0xE3, 0x60, 0x5B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xE1, 0xC4, 0xE4, 0x79, 0x05, 0x37, 0x4C, 0xE9, 0xF4, 0xCC, 0xE2, 0xE4, 0x4C, 0xE1, 0x4C, 0xF9, 0xED, 0x38, 0xF8, 0x4C, 0xE8, 0xF4, 0xF8, 0xE4, 0xE0, 0xA8, 0x4C, 0xC1, 0xE3, 0x60, 0xE4, 0x79, 0x04, 0x37, 0x4C, 0xD0, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xB4, 0x2C, 0xF8, 0x85, 0x37, 0x4C, 0xE8, 0xF6, 0x4C, 0x69, 0xF4, 0xE4, 0x40, 0x4C, 0xD0, 0x2C, 0xE8, 0xF4, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xC4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xB4, 0x4C, 0x79, 0x85, 0x37, 0xD0, 0xD2, 0xF4, 0x5B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xE1, 0xB4, 0x4C, 0xF9, 0x05, 0x37, 0xD0, 0x62, 0x04, 0xE3, 0x60, 0x5B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xE1, 0xB4, 0xE4, 0x79, 0x05, 0x37, 0x4C, 0xE9, 0xF4, 0xD0, 0x62, 0x64, 0xCC, 0xE2, 0xE4, 0x4C, 0xE1, 0x4C, 0xF9, 0xED, 0x38, 0xF8, 0x4C, 0xE8, 0xF4, 0xF8, 0xE4, 0xE0, 0xA8, 0x4C, 0xC1, 0xE3, 0x60, 0xE4, 0x79, 0x04, 0x37, 0x4C, 0xD0, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xC4, 0x2C, 0xF8, 0x85, 0x37, 0x52, 0x54, 0x2F, 0x2F, 0x2F, 0xB0, 0xEC, 0x00, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0x6F, 0x14, 0x4C, 0xEC, 0x00, 0xB4, 0xB4, 0xB4, 0x2F, 0xC0, 0x2C, 0xEC, 0x00, 0xB4, 0xB4, 0xB4, 0xCC, 0x6C, 0x00, 0xB4, 0xB4, 0xB4, 0xB6, 0x24, 0xCC, 0x72, 0xB4, 0xB4, 0xB4, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xD4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xE4, 0x4C, 0x79, 0x85, 0x37, 0xD0, 0xD2, 0xF4, 0x5B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xE1, 0xE4, 0x4C, 0xF9, 0x05, 0x37, 0xD0, 0x62, 0x04, 0xE3, 0x60, 0x5B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xE1, 0xE4, 0xE4, 0x79, 0x05, 0x37, 0x4C, 0xE9, 0xF4, 0xCC, 0xE2, 0xE4, 0x4C, 0xE1, 0x4C, 0xF9, 0xED, 0x38, 0xF8, 0x4C, 0xE8, 0xF4, 0xF8, 0xE4, 0xE0, 0xA8, 0x4C, 0xC1, 0xE3, 0x60, 0xE4, 0x79, 0x04, 0x37, 0x4C, 0xD0, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xD4, 0x2C, 0xF8, 0x85, 0x37, 0x4C, 0xE8, 0xF6, 0x4C, 0x69, 0xF4, 0xE4, 0x40, 0x4C, 0xD0, 0x2C, 0xE8, 0xF4, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xE4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xD4, 0x4C, 0x79, 0x85, 0x37, 0xD0, 0xD2, 0xF4, 0x5B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xE1, 0xD4, 0x4C, 0xF9, 0x05, 0x37, 0xD0, 0x62, 0x04, 0xE3, 0x60, 0x5B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xE1, 0xD4, 0xE4, 0x79, 0x05, 0x37, 0x4C, 0xE9, 0xF4, 0xD0, 0x62, 0x64, 0xCC, 0xE2, 0xE4, 0x4C, 0xE1, 0x4C, 0xF9, 0xED, 0x38, 0xF8, 0x4C, 0xE8, 0xF4, 0xF8, 0xE4, 0xE0, 0xA8, 0x4C, 0xC1, 0xE3, 0x60, 0xE4, 0x79, 0x04, 0x37, 0x4C, 0xD0, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xE4, 0x2C, 0xF8, 0x85, 0x37, 0x52, 0x54, 0x2F, 0x2F, 0x2F, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xB4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xD4, 0x4C, 0x79, 0x85, 0x37, 0x4C, 0xF8, 0x04, 0x37, 0xE3, 0xD0, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xB4, 0x2C, 0xF8, 0x85, 0x37, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xC4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xE4, 0x4C, 0x79, 0x85, 0x37, 0x4C, 0xF8, 0x04, 0x37, 0xE3, 0xD0, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xC4, 0x2C, 0xF8, 0x85, 0x37, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xE4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xB4, 0x4C, 0x79, 0x85, 0x37, 0x4C, 0xF8, 0x04, 0x37, 0xE3, 0xD0, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xE4, 0x2C, 0xF8, 0x85, 0x37, 0x3B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0xC0, 0xC4, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xD4, 0x4C, 0x79, 0x85, 0x37, 0x4C, 0xF8, 0x04, 0x37, 0xE3, 0xD0, 0x2B, 0xF4, 0xB4, 0xB4, 0xB4, 0x38, 0x4A, 0x50, 0xD4, 0x2C, 0xF8, 0x85, 0x37, 0xA0, 0xEC, 0x42, 0xB4, 0xB4, 0xB4, 0x3D, 0xA0, 0xEC, 0x52, 0xB4, 0xB4, 0xB4, 0xBE, 0xA0, 0xEC, 0x62, 0xB4, 0xB4, 0xB4, 0x51, 0xA0, 0xEC, 0x6F, 0xB4, 0xB4, 0xB4, 0x3D, 0xA0, 0xEC, 0x7F, 0xB4, 0xB4, 0xB4, 0x5B, 0xA0, 0xEC, 0x12, 0xB4, 0xB4, 0xB4, 0x8D, 0xA0, 0xEC, 0x22, 0xB4, 0xB4, 0xB4, 0x65, 0xA0, 0xEC, 0x32, 0xB4, 0xB4, 0xB4, 0xA7, 0xA0, 0xEC, 0xBF, 0xB4, 0xB4, 0xB4, 0x4D, 0xA0, 0xEC, 0xCF, 0xB4, 0xB4, 0xB4, 0xAC, 0xA0, 0xEC, 0xDF, 0xB4, 0xB4, 0xB4, 0xF8, 0xA0, 0xEC, 0xEF, 0xB4, 0xB4, 0xB4, 0x06, 0xA0, 0xEC, 0xFF, 0xB4, 0xB4, 0xB4, 0xE9, 0xA0, 0xEC, 0x8F, 0xB4, 0xB4, 0xB4, 0x3B, 0xA0, 0xEC, 0x9F, 0xB4, 0xB4, 0xB4, 0xA3, 0xA0, 0xEC, 0xAF, 0xB4, 0xB4, 0xB4, 0x31, 0xB0, 0xEC, 0xF5, 0xC4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0x6F, 0x14, 0x4C, 0xEC, 0xF5, 0xC4, 0xB4, 0xB4, 0x2F, 0xC0, 0x2C, 0xEC, 0xF5, 0xC4, 0xB4, 0xB4, 0xCC, 0x6C, 0xF5, 0xC4, 0xB4, 0xB4, 0xB5, 0x68, 0xE6, 0x38, 0xCA, 0xEC, 0xF5, 0xC4, 0xB4, 0xB4, 0x24, 0x1B, 0xF8, 0x04, 0x37, 0x38, 0xCA, 0x6D, 0xF5, 0xC4, 0xB4, 0xB4, 0x24, 0x1B, 0x7D, 0x85, 0x42, 0xB4, 0xB4, 0xB4, 0x63, 0xD0, 0xF7, 0xF4, 0xD3, 0xC0, 0x6F, 0xF4, 0x6F, 0x00, 0xBB, 0xC4, 0x38, 0x4C, 0x3F, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD]

assert len(a) == 1152
for i in range(len(a)):
    a[i] = ror8(a[i], 5)
rng = WindowsRand(0xdeadbeef)

def get_next_dou():
    x = rng.rand() % 20
    y = rng.rand() % 20
    return x, y

def up_encode(a):
    r = deepcopy(a)
    for i in range(len(r)):
        r[i] -= 102
        r[i] &= 0xff
    return r

def down_encode(a):
    r = deepcopy(a)
    for i in range(len(r)):
        r[i] = ror8(r[i], 5)
    return r

def left_encode(a):
    r = deepcopy(a)
    r = r[6:] + r[:6]
    return r

def right_encode(a):
    r = deepcopy(a)
    for i in range(len(r)):
        r[i] += 0x1e
        r[i] &= 0xff
    return r

def is_right(a):
    true_result = bytes([0x9C, 0x06, 0xC0, 0x8F, 0x88, 0x2D, 0x79, 0x81, 0xE9, 0x1D, 0x66, 0x33, 0x64, 0xCE, 0x5E, 0x2E])
    re =  md5(bytes(a)).digest()
    return re == true_result

然后算法不会写,长大后再学习,先放这里了。

remem

能直接运行但是不能直接拖入ida,稍微修复一下elf头,前十六个字节从cat搬过来就行了。
有一个syscall -> clone 是为了检查flag{前缀的,无关紧要

from regadgets import *
from z3 import *
from typing import List
from struct import unpack

def byte2dword_big(x: List[int]):
    if len(x) % 4 != 0:
        if type(x) == bytes:
            x += b'\x00' * (4 - (len(x) % 4))
        else:
            x += [0] * (4 - (len(x) % 4))
    return [v[0] for v in (unpack('>I', bytes(x[i:i+4])) for i in range(0, len(x), 4))]

x = [BitVec(f"x{i}", 32) for i in range(5)]
s = Solver()
# a1 = 4138516404
# a2 = 774266043
# a3 = 4083938303
# a4 = 420409376
# a5 = 25624236
a1, a2, a3, a4, a5 = x[0], x[1], x[2], x[3], x[4]
# s.add(a5 & 0xff == ord('}'))
# a1, a2, a3, a4, a5 = byte2dword_big(b'l@`0JK+KL^(EZw\\*I0Te')
# a1, a2, a3, a4, a5 = 1130446384, 1580411220, 1079910944, 1028674135, 1782732379
b1=a1*a1*3
b2=a1*a2*6 
b3=a2*0x52
b4=a2*6
b5=a1*a1*2
b6=a2*0xd
b7=a1*0x11
b8=a1*a3*5
b9=a3*a3*5
b10=a3*0x58
b11=a3*a4*4
b12=a3*a3*5
b13=a4*0xe8
b14=a4*a4*0x23
b15=a5*8
b16=a5*a5*16
# print([hex(i & 0xffffffffffffffff)[2:] for i in [b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16]])
enc = [1] * 5
enc[4] = 0x555CC98C 
enc[3] = 0x1EBFA92F
enc[2] = 0x509A3978
enc[1] = 0x35368926
enc[0] = 0x42DB9F06  
# enc = [i & 0xffffffffffffffff for i in enc]


# s.add((a5*a5*16) & 0xffffffff + (a5 * 8) & 0xffffffff - (a4 * a4 * 35) & 0xffffffff == enc[0])
# s.add((a4*232) & 0xffffffff + (a3*a3*5) & 0xffffffff - (a3*a4*4) & 0xffffffff  == enc[1])
# s.add((a3*88) & 0xffffffff + (a3*a3*5) & 0xffffffff - (a1*a3*5) & 0xffffffff == enc[2])
# s.add((a1*a1*2) & 0xffffffff + (a2*13) & 0xffffffff + (a1*17) & 0xffffffff == enc[3])
# s.add((a1*a1*3) & 0xffffffff + (a1*a2*6) & 0xffffffff + (a2*82) & 0xffffffff + (a2*6) & 0xffffffff == enc[4])
# print(hex((b16 + b15 - b14) & 0xffffffffffffffff))
# print(hex((b13 + b12 - b11) & 0xffffffffffffffff))
# print(hex((b10 + b9 - b8) & 0xffffffffffffffff))
# print(hex((b7 + b6 + b5) & 0xffffffffffffffff))
# print(hex((b3 + b4 + b2 - b1) & 0xffffffffffffffff))

# print(hex((b16+b15-b14) & 0xffffffffffffffff))
# print(hex(((b16+b15-b14) & 0xffffffffffffffff) % 0x5E2F4391))
# print(hex(((b13+b12-b11) & 0xffffffffffffffff) % 0x5E2F4391))
# print(hex(((b10+b9-b8) & 0xffffffffffffffff) % 0x5E2F4391))
# print(hex(((b7+b6+b5) & 0xffffffffffffffff) % 0x5E2F4391))
# print(hex(((b3+b4+b2-b1) & 0xffffffffffffffff) % 0x5E2F4391))
# print(hex((b13+b12-b11) % 0x5E2F4391))

s1 = ((b16+b15-b14) & 0xffffffffffffffff) % 0x5E2F4391
s2 = ((b13+b12-b11) & 0xffffffffffffffff) % 0x5E2F4391
s3 = ((b10+b9-b8)   & 0xffffffffffffffff) % 0x5E2F4391
s4 = ((b7+b6+b5)    & 0xffffffffffffffff) % 0x5E2F4391
s5 = ((b3+b4+b2-b1) & 0xffffffffffffffff) % 0x5E2F4391
S1 = s5 ^ enc[0]
S2 = S1 ^ s4 ^ enc[1]
S3 = S2 ^ s3 ^ enc[2]
S4 = S3 ^ s2 ^ enc[3]
S5 = S4 ^ s1 ^ enc[4]
# s.add((s1 ^ s2 ^ s3 ^ s4 ^ s5 ^ enc[0] ^ enc[1] ^ enc[2] ^ enc[3] ^ enc[4]) == 0)
s.add(S5 == 0)
# print('S', hex(S1))
# print('S', hex(S2))
# print('S', hex(S3))
# print('S', hex(S4))
# print('S', hex(S5))
def z3_all_bv_is_printable(solver: Solver, var: List[BitVecRef]) -> None:
    for v in var:
        for i in range(v.size() // 8):
            solver.add((v >> (i*8)) & 0xff >= 0x20)
            solver.add((v >> (i*8)) & 0xff < 0x7f)
z3_all_bv_is_printable(s, x)

for m in z3_get_models(s):
    r = b''
    re = []
    for i in x:
        r += l2b(m[i].as_long())
    print(r) 
# ((0x3434B5358+b14+a5)-b13)//0x5E2F4391

# 0x42DB9F06 ,0x35368926,0x509A3978,0x1EBFA92F,0x555CC98C

我们写z3来约束,但是...如果

s.add(S1 == 0)
s.add(S2 == 0)
s.add(S3 == 0)
s.add(S4 == 0)
s.add(S5 == 0)

那么就会unsat,如果按程序的只检查S5就会无穷组解,不是很懂是z3的问题还是我的问题,我看别人队伍好像是用SageMath求解(tql),但是目前还不会,长大后再学习,复现出来了更新blog。

boxxx

1是墙壁,0是通路,3是箱子,4是箱子要去的地方,2是初始点

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 0 3 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
0 0 0 0 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 
0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0
0 0 0 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0
0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
0 1 1 1 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 
0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 
第0层
13
wwaaddssaaaww

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 2 0 0 3 0 0 0 4 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 0 
0 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0
0 1 1 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 
0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0
0 0 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 0
0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 
0 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 1 1 1 0
0 0 1 0 0 0 3 0 0 0 1 0 0 0 1 0 0 0 1 0
0 0 1 1 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0
0 0 4 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
0 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
第1层
50
ddddddsdddddddssaaaassssaaaassaassdawwddsssdsaaaaa

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 
1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 0 1 0 3 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 0 1 1 1 0 1 1 1 0 1 1 1 1 1 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
1 * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
第2层
78
aawwwwwwaaaaawwwaaaaaasdwdsswddddssaaaaaaaddddddddddddssaaaaasaaaaaaaawwwwwwww


1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 0 0 0 3 0 0 0 0 1 0 0 0 0 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 
1 0 0 0 0 0 0 1 0 0 0 0 2 1 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

第3层
16

wwaaaaaaaaaasaww
-------------------------------------------------------------------------
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1
1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 1 1 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 1
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 
第4层
47
wwaaaaaaaaadddddddddssaaaaaaaaaawwwawdddddddddd


1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 4 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1
1 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 1 
1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1
1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1
1 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1
1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 1 1 1 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 3 0 1 0 0 1
1 1 1 1 1 1 1 1 4 0 0 0 0 0 0 0 1 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
第5层
54
dddddwwaaaaaaaaaaaaadddddddddddddssssssssssassdsaaaaaa

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 1 0 0 0 0 2 1 0 0 0 0 0 0 0 0 1
1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 0 1
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 
1 0 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1
1 1 1 1 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1
1 0 0 0 0 0 1 0 1 0 1 1 1 1 1 0 1 1 0 1
1 0 1 1 1 1 1 0 1 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 0 0 0 0 1 0 1 0 1 1 1 1 1 0 0 1 
1 0 1 0 1 1 1 1 1 0 1 0 1 0 0 0 0 0 0 1
1 0 0 0 3 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 0 1 0 1 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 0 1 
1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
第6层 
68  
aaaasssssaaaassssdddddddddddawwwddddwwdddssassaaaassssdsaaaaaaaaaaaa

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 4 0 0 0 0 0 0 0 0 0 0 0 2 0 0 3 0 0 1
1 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 0 0 1 
1 0 1 0 1 4 0 0 0 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 1 0 1 1 1 1 1 0 1 0 1 0 1 0 0 1
1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 0 1
1 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 1 
1 0 0 0 3 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1
1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1
1 0 0 0 3 0 0 0 0 0 0 0 0 0 0 4 1 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 
1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1
1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 

第7层
145
aaaaaaaassaassssssdaaassddddwwwwwsssaawwwwwwddddddddddddddwwaaaaaaaaaaaaaaaddddddddddddddddssssssssssssssssssaaaaaaaaaaaaaaaaawwwwwwddddddddddddd

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 1 0 1 1 1 0 1 1 1 1 1 1 0 1 
1 0 0 0 1 0 1 3 0 0 1 0 1 0 0 0 1 0 0 1
1 1 1 1 1 0 0 2 1 1 1 0 1 0 1 0 1 0 0 1
1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1
1 0 1 1 1 1 1 4 1 0 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1
1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 
1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

第8层
21 
aasaaaasssssddwwwddddddwwddwwwwaaaassss

恭喜你完成本次关卡!※
flag是每个关卡中每个箱子移动的最短的次数拼接的md5码值和几个字符,1.flag{四个字符_md5值},2.注意同一张图箱子不一定只有一 个哦3.同一关需要计算所有箱子的总的最小移动次数,将每一关的最短次数拼接  解释:例如第一关是3第二关是5,就是md5(35...)

大脑出了一点问题,看成人走的个数了,上文中所有个数均是最短但是不是题目问的。。。

题目中的四个字符是从后面几张map提取的

from regadgets import *
maze = byte2dword(open('maze.bin', 'rb').read())
for k in range(0, 13, 1): # 最后四张地图是字符
    for i in range(0, 20, 1):
        for j in range(0, 20, 1):
            print(maze[400*k + i*20+j], end=' ')
        print('')
    print('----------------------')

不出意外就是qwb!
2024-11-04T11:59:18.png

之后复现了,一次就成功了

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 0 3 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
0 0 0 0 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 
0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0
0 0 0 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0
0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
0 1 1 1 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 
0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 

第0层:2次

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 2 0 0 3 0 0 0 4 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 0 
0 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0
0 1 1 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 
0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0
0 0 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 0
0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 
0 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 1 1 1 0
0 0 1 0 0 0 3 0 0 0 1 0 0 0 1 0 0 0 1 0
0 0 1 1 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0
0 0 4 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0
0 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

第1层: 12次

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 
1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 0 1 0 3 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 0 1 1 1 0 1 1 1 0 1 1 1 1 1 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
1 * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

第2层:13次

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 0 0 0 3 0 0 0 0 1 0 0 0 0 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 
1 0 0 0 0 0 0 1 0 0 0 0 2 1 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

第3层:9次


1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1
1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 1 1 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 1
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 

第4层:
21次


1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 4 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1
1 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 1 
1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1
1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1
1 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1
1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 1 1 1 0 1 1 1 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 3 0 1 0 0 1
1 1 1 1 1 1 1 1 4 0 0 0 0 0 0 0 1 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1

第5层:
13次

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 1 0 0 0 0 2 1 0 0 0 0 0 0 0 0 1
1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 0 1
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 
1 0 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1
1 1 1 1 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1
1 0 0 0 0 0 1 0 1 0 1 1 1 1 1 0 1 1 0 1
1 0 1 1 1 1 1 0 1 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 0 0 0 0 1 0 1 0 1 1 1 1 1 0 0 1 
1 0 1 0 1 1 1 1 1 0 1 0 1 0 0 0 0 0 0 1
1 0 0 0 3 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 0 1 0 1 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 0 1 
1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

第6层:
25次

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 4 0 0 0 0 0 0 0 0 0 0 0 2 0 0 3 0 0 1
1 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 0 0 1 
1 0 1 0 1 4 0 0 0 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 1 0 1 1 1 1 1 0 1 0 1 0 1 0 0 1
1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 0 1
1 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 1 
1 0 0 0 3 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
1 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1
1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1
1 0 0 0 3 0 0 0 0 0 0 0 0 0 0 4 1 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 
1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1
1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
第7层
31次




1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 1 0 1 1 1 0 1 1 1 1 1 1 0 1 
1 0 0 0 1 0 1 3 0 0 1 0 1 0 0 0 1 0 0 1
1 1 1 1 1 0 0 2 1 1 1 0 1 0 1 0 1 0 0 1
1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1
1 0 1 1 1 1 1 4 1 0 1 1 1 1 1 1 1 0 0 1
1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1
1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 
1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

第8层
3次

md5(212139211325313)

flag{qwb!_fec2d316d20dbacbe0cdff8fb6ff07b9}

Solve2.apk

没出,因为没时间了,如果多给10分钟就行。
纯java,然后是恶心的混淆,JEBPro直接调试,然后可以发现有一个数组里有两个Box,256大小,然后网上搜索这个可以找到Twofish加密算法。
网上搜了一下Twofish Java,发现基本上和这个东西一样
https://android.googlesource.com/platform/tools/base/+/master/jobb/src/main/java/Twofish/Twofish_Algorithm.java

我们可以观察一下,发现缺陷在这里,这里传入两个key部分,然后进行了一些操作,我们直接用GDA Pro来进行Frida Hook,拿到key是 bytes(range(16))
2024-11-04T12:05:28.png

接下来就是获取enc了,我们把控制流混淆的==全部用正则表达式清掉,然后再搜==,就发现有且仅有一处了,然后JEBPro调试smali,有个if-eq,直接看v2数组的值就是enc,我们就可以twofish解密,得到第一组flag(前16字节),然后把第一组flag输入程序(忘了说了这个之前还有一一段文本以>结尾,是tea加密,我们要把flag放在>之后),然后过前16字节检查,再去断if-eq,可以拿到第二组的加密后flag,结果我twofish解不出来,这时距离比赛结束只有20s了,似了。
赛后对源码进行搜索,找到个异或,应该就是简单的异或,当时如果用测试用的输入异或enc,直接就能出了,可惜时间不够,遗憾。
Tip:赛后别人说是RC4。