“科来杯”第九届山东省大学生网络安全技能大赛决赛部分WriteUp


[toc]

Indiana-corn-sunset-Milford-New-Zealand-Desktop-W

前言

这次比赛让我真正认识到了我是多么的菜!

Misc(杂项)

签到(找js接口)

进入题目是一个小游戏,当然如果你狠nb可以直接通关得到flag,但这里的预期解是找接口。查看源代码,可以发现一个index.js,在index.js里面发现一个w3lc0me.sdnisc.php,且只要传参token=123即可得到flag:

img

ctf的起源(base64隐写)

下载附件flag.txt,得到如下:

image-20201108221137421

很明显是个base64隐写,我们直接上脚本破解即可:

'''
base64隐写解密
'''

base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

flag=''
with open('flag.txt','r') as f:
    for line in f.readlines():
        line=line[:-1]
        num=line.count('=')
        if num == 0 :
            continue
        lastchar = line[-(num+1)]

        #print(line,num,lastchar)
        myindex = base64chars.index(lastchar)
        #print(myindex)
        bin_str = bin(myindex)[2:].zfill(6)
        #print(bin_str)
        flag+=bin_str[6-2*num:]
        #print(bin_str[6-2*num:])
print(''.join([chr(int(flag[i:i + 8], 2)) for i in range(0, len(flag), 8)]))

如下图所示,得到flag:

image-20201108221408660

(自行加上”}”)

简单的js(逆向算法)

下载附件flag.js,得到如下JavaScript代码:

image-20201108221705858

/**
 * Pseudo md5 hash function
 * @param {string} string
 * @param {string} method The function method, can be 'ENCRYPT' or 'DECRYPT'
 * @return {string}
 */
function pseudoHash(string, method) {
  // Default method is encryption
  if (!('ENCRYPT' == method || 'DECRYPT' == method)) {
    method = 'ENCRYPT';
  }
  // Run algorithm with the right method
  if ('ENCRYPT' == method) {
    // Variable for output string
    var output = '';
    // Algorithm to encrypt
    for (var x = 0, y = string.length, charCode, hexCode; x < y; ++x) {
      charCode = string.charCodeAt(x);
      if (128 > charCode) {
        charCode += 128;
      } else if (127 < charCode) {
        charCode -= 128;
      }
      charCode = 255 - charCode;
      hexCode = charCode.toString(16);
      if (2 > hexCode.length) {
        hexCode = '0' + hexCode;
      }

      output += hexCode;

    }
    // Return output

    return output;
  } else if ('DECRYPT' == method) {
    // DECODE MISS
    // Return ASCII value of character
    return string;
  }
}
document.getElementById('password').value = pseudoHash('19131e18041b1d4c47191d19194f1949481a481a1d4c1c461b4d484b191b4e474f1e4b1d4c02', 'DECRYPT');

charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。

toString() 方法可把数字转换为数字字符串。

我们编写逆向解密算法脚本即可得到flag:

flag_enc = '19131e18041b1d4c47191d19194f1949481a481a1d4c1c461b4d484b191b4e474f1e4b1d4c02'
flag = ''
for i in range(0,len(flag_enc),2):
    str = flag_enc[i:i+2]
    flag_index = 255 - int(str,16)
    if (flag_index - 128) < 128:
        flag_index -= 128
    else:
        flag_index += 128
    flag += chr(flag_index)
print(flag)

// flag{db38fbff0f67e7eb3c9d274fd180a4b3}

损坏的流量包

下载附件1.pcapng,直接用binwalk分离,得到一个key.txt,并在key.txt中发现一串base64:

image-20201108223927191

解码即可成功得到flag:

image-20201108224015093

也可以直接用strings命令读取。

empty

下载附件,得到一个FAT文件:

image-20201108224231434

我们用取证大师加载取证,恢复fat,可以发现一个png图片:

image-20201108224703788

image-20201108224721710

和一个加密了的docx文档:

image-20201108224756225

image-20201108224857704

那么docx文档的密码肯定在那个png图片里。尝试winhex无果,binwalk等等无果,最终尝试Stegsolve,在一个通道中发现了docx文档的密码:

image-20201108225050673

放在画图里面镜像翻转下即可。输入密码“Sa8!pA9#3fQ”解密:

image-20201108230243118

接下来不会了。

Stego(隐写)

过去和现在

下载题目附件得到一张名为flag.png的图片,这里我是直接binwalk分离文件,直接就可以得到flag的:

image-20201110110930828

但还有一种做法,即用zsteg工具。

zsteg工具专用于检测PNG和BMP图片里的隐写数据。

首先,我们用以下命令查看图片的LSB信息(查看隐藏得信息):

zsteg flag.png

image-20201110111152516

如上图所示,发现zlib压缩的标志,然后我们执行如下命令将其导出:

zsteg -e extradata:0 flag.png > zlib_out

image-20201110111337198

最后,使用以下脚本对其进行解压:

#zlib解压缩
import zlib
def compress(infile, dst, level=9):
    infile = open(infile, 'rb')
    dst = open(dst, 'wb')
    compress = zlib.compressobj(level)
    data = infile.read(1024)
    while data:
        dst.write(compress.compress(data))
        data = infile.read(1024)
    dst.write(compress.flush())
def decompress(infile, dst):
    infile = open(infile, 'rb')
    dst = open(dst, 'wb')
    decompress = zlib.decompressobj()
    data = infile.read(1024)
    while data:
        dst.write(decompress.decompress(data))
        data = infile.read(1024)
    dst.write(decompress.flush())

if __name__ == "__main__":
    #compress('in.txt', 'out.txt')
    decompress('zlib_out', 'out_decompress.txt')

执行脚本,如下图所示,得到flag:

image-20201110111522622

左上角的秘密 *

题目给出两个文件:

image-20201110102151637

enc.py代码中的内容是:

# encoding=utf-8

flag_enc = open("flag_enc.hex", "wb")


def file_encode(flag):
    i = 1
    while True:


        byte_str = flag.read(1)
        if (byte_str == b''):
            exit()

        byte_str = hex_encode(byte_str)
        file_write(flag_enc, byte_str)
        # print(byte_str, end="")
        i = i + 1

def hex_encode(byte_str):

    tmp = int.from_bytes(byte_str, byteorder="big")
    if (tmp % 2 == 0):
        tmp = (tmp + 1) ^ 128
    else:
        tmp = (tmp - 1) ^ 128
    tmp = bytes([tmp])
    return tmp

def file_write(flag_enc, byte_str):
    flag_enc.write(byte_str)



if __name__ == '__main__':
    with open("./flag.png", "rb") as flag:
        file_encode(flag)
    flag_enc.close()

即将图片flag.png加密后写到了flag_enc.hex文件里面,我们先把脚本逆向分析,还原出图片:

flag_dec = open("flag.png","wb")
def file_decode(flag):
    i = 1
    while True:
        byte_str = flag.read(1)
        if (byte_str == b''):
            exit()
        byte_str = hex_decode(byte_str)
        file_write(flag_dec, byte_str)
        # print(byte_str, end="")
        i = i + 1

def hex_decode(byte_str):
    tmp = int.from_bytes(byte_str, byteorder="big")
    tmp = tmp ^ 128
    if (tmp % 2 == 0):
        tmp = tmp + 1
    else:
        tmp = tmp - 1
    tmp = bytes([tmp])
    return tmp

def file_write(flag_dec, byte_str):
    flag_dec.write(byte_str)

if __name__ == '__main__':
    with open("./flag_enc.hex", "rb") as flag:
        file_decode(flag)
    flag_dec.close()

得到的图片如下图所示:

image-20201110103328730

图片放大后可以看到右上角有绿色和黑色的东西:

image-20201110104208396

我们提取图片像素点的RGB值(注意得到的全是十进制的值):

#python3
from PIL import Image
im = Image.open('flag.png')
width = im.size[0]
height = im.size[1]
pim = im.load() # 读取图片的像素信息
bin_result = ''
tmp = 1
for h in range(height):
    for w in range(width):
     if(pim[w,h][0] == tmp):
         print(pim[w,h]) # (R,G,B)表示第一通道
         tmp += 1
         break

得到如下像像素RGB值:

image-20201110105208234

然后我们编写如下脚本将RGB中的G(green)值提取出来:

rgb = '''
(1, 90, 1)
(2, 109, 2)
(3, 120, 3)
(4, 104, 4)
(5, 90, 5)
(6, 51, 6)
(7, 116, 7)
(8, 106, 8)
(9, 78, 9)
(10, 109, 10)
(11, 85, 11)
(12, 48, 12)
(13, 89, 13)
(14, 122, 14)
(15, 107, 15)
(16, 53, 16)
(17, 89, 17)
(18, 84, 18)
(19, 89, 19)
(20, 122, 20)
(21, 79, 21)
(22, 68, 22)
(23, 104, 23)
(24, 106, 24)
(25, 78, 25)
(26, 87, 26)
(27, 81, 27)
(28, 121, 28)
(29, 89, 29)
(30, 84, 30)
(31, 108, 31)
(32, 104, 32)
(33, 90, 33)
(34, 84, 34)
(35, 90, 35)
(36, 108, 36)
(37, 90, 37)
(38, 106, 38)
(39, 90, 39)
(40, 104, 40)
(41, 79, 41)
(42, 68, 42)
(43, 81, 43)
(44, 122, 44)
(45, 89, 45)
(46, 50, 46)
(47, 86, 47)
(48, 104, 48)
(49, 78, 49)
(50, 110, 50)
(51, 48, 51)
(52, 61, 52)
(53, 52, 60)
(54, 53, 58)
(55, 55, 57)
(56, 55, 61)
(57, 56, 62)
(58, 56, 61)
(59, 58, 66)
(60, 59, 73)
(61, 55, 57)
(62, 60, 71)
(63, 56, 63)
(64, 62, 73)
(65, 63, 74)
(66, 64, 77)
(67, 65, 78)
(68, 67, 75)
(69, 67, 78)
(70, 68, 79)
(71, 71, 71)
(72, 71, 79)
(73, 72, 77)
(74, 73, 78)
(75, 74, 79)
(76, 75, 80)
(77, 76, 82)
(78, 77, 85)
(79, 79, 79)
(80, 78, 91)
(81, 81, 81)
(82, 82, 82)
(83, 83, 83)
(84, 84, 84)
(85, 85, 85)
(86, 86, 86)
(87, 87, 87)
(88, 88, 88)
(89, 89, 89)
(90, 90, 90)
(91, 91, 91)
(92, 92, 92)
(93, 93, 93)
(94, 94, 94)
(95, 95, 95)
(96, 96, 96)
(97, 97, 97)
(98, 98, 98)
(99, 99, 99)
(100, 102, 99)
(101, 103, 100)
(102, 109, 102)
(103, 108, 104)
(104, 104, 104)
(105, 107, 106)
(106, 106, 106)
(107, 109, 108)
(108, 110, 105)
(109, 114, 108)
(110, 115, 111)
(111, 121, 112)
(112, 117, 111)
(113, 115, 114)
(114, 112, 113)
(115, 117, 114)
(116, 120, 119)
(117, 122, 116)
(118, 122, 125)
(119, 121, 118)
(120, 127, 120)
(121, 126, 119)
(122, 126, 125)
(123, 128, 121)
(124, 135, 119)
(125, 131, 127)
(126, 136, 125)
(127, 137, 126)
(128, 137, 134)
(129, 134, 130)
(130, 133, 126)
(131, 138, 130)
(132, 140, 129)
(133, 138, 134)
(134, 136, 133)
(135, 137, 134)
(136, 138, 133)
(137, 139, 136)
(138, 143, 137)
(139, 144, 140)
(140, 140, 138)
(141, 143, 142)
(142, 147, 143)
(143, 145, 144)
(144, 146, 143)
(145, 150, 144)
(146, 161, 154)
(147, 149, 146)
(148, 153, 149)
(149, 156, 149)
(150, 157, 150)
(151, 161, 153)
(152, 158, 148)
(153, 160, 153)
(154, 161, 153)
(155, 160, 154)
(156, 158, 153)
(157, 159, 158)
(158, 165, 157)
(159, 166, 159)
(160, 167, 159)
(161, 168, 161)
(162, 167, 161)
(163, 168, 162)
(164, 169, 163)
(165, 175, 166)
(166, 173, 166)
(167, 173, 169)
(168, 174, 170)
(169, 174, 168)
(170, 175, 171)
(171, 173, 168)
(172, 177, 173)
(173, 178, 172)
(174, 179, 173)
(175, 177, 174)
(176, 181, 175)
'''
rgbs = rgb.split('\n')
for i in rgbs:
    try:
        tmp = i.split(', ')[1]
        print(tmp, end=' ')
    except:
        pass

得到:

90 109 120 104 90 51 116 106 78 109 85 48 89 122 107 53 89 84 89 122 79 68 104 106 78 87 81 121 89 84 108 104 90 84 90 108 90 106 90 104 79 68 81 122 89 50 86 104 78 110 48 61 52 53 55 55 56 56 58 59 55 60 56 62 63 64 65 67 67 68 71 71 72 73 74 75 76 77 79 78 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 102 103 109 108 104 107 106 109 110 114 115 121 117 115 112 117 120 122 122 121 127 126 126 128 135 131 136 137 137 134 133 138 140 138 136 137 138 139 143 144 140 143 147 145 146 150 161 149 153 156 157 161 158 160 161 160 158 159 165 166 167 168 167 168 169 175 173 173 174 174 175 173 177 178 179 177 181 

然后,我们将这些值转为字符:

image-20201110110220289

得到如下base64密文:

ZmxhZ3tjNmU0Yzk5YTYzODhjNWQyYTlhZTZlZjZhODQzY2VhNn0=

解密即可得到flag:

image-20201110110325334

crypto(密码学)

简单的rsa

题目给出如下:

image-20201108231043091

共模攻击,直接套脚本:

from gmpy2 import *
import libnum

n=int('a1d4d377001f1b8d5b2740514ce699b49dc8a02f12df9a960e80e2a6ee13b7a97d9f508721e3dd7a6842c24ab25ab87d1132358de7c6c4cee3fb3ec9b7fd873626bd0251d16912de1f0f1a2bba52b082339113ad1a262121db31db9ee1bf9f26023182acce8f84612bfeb075803cf610f27b7b16147f7d29cc3fd463df7ea31ca860d59aae5506479c76206603de54044e7b778e21082c4c4da795d39dc2b9c0589e577a773133c89fa8e3a4bd047b8e7d6da0d9a0d8a3c1a3607ce983deb350e1c649725cccb0e9d756fc3107dd4352aa18c45a65bab7772a4c5aef7020a1e67e6085cc125d9fc042d96489a08d885f448ece8f7f254067dfff0c4e72a63557',16)
e1=int('f4c1158f',16)
e2=int('f493f7d1',16)
s = gcdext(e1, e2)
s1 = s[1]
s2 = -s[2]

c1=12051796366524088489284445109295502686341498426965277230069915294159131976231473789977279364263965099422235647723775278060569378071469131866368399394772898224166518089593340803913798327451963589996734323497943301819051718709807518655868569656941242449109980876397661605271517459716669684900920279597477446629607627693769738733623143693170696779851882404994923673483971528314806130892416509854017091137325195201225617407959645788145876202882024723106204183257094755002924708009138560347432552090905489132135154932987521239299578509008290614398700799670928805692609756924823628055245227290288940649158862576448537833423
c2=16648382384980770705624348910895797622774711113202207693584907182552301186239613809347201161450012615995859738410661452438496756353485538305614949211776668793864984429696790944750894691957799234264508530084026894611228513698963347402329109838109621609770406925700520983387811451074838470370044678634099202003480925903267508744006195455234025325060817223813858985074720872124168142943926467694676717713503559007112874381750005406371400109962943508349497151148446064846096531445037416174913915923050332242843403926133165817310272633884358263778516770288515592959832151762499526363131801945163501999337808208074381212795
#e2=9647291
c2 = invert(c2, n)
m = (pow(c1,s1,n) * pow(c2 , s2 , n)) % n
print m
print libnum.n2s(m)

image-20201108231154027

如上图得到flag。

Web

银牌1

先随便注册一个用户,登录进去发现假的flag:

img

我们猜测flag生成情况与用户名相关,要登录admin账户,这里我们利用首尾添加空格绕过限制,注册一个与管理员用户名admin相同的账号:

img

注册并登录成功:

img

带上cookie再拿flag

img

银牌2-easy_flask

恶心人的题,详情见y1ng师傅博客:

https://www.gem-love.com/ctf/2598.html

Ending……

明年再战吧……


Author: WHOAMI
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source WHOAMI !
评论
  TOC