几道屑misc

这两天的屑比赛屑题目,记录一下,进行一个公示,以后不要再接触这种题目了

深育杯_disk

图片[1]-几道屑misc-魔法少女雪殇

文件名我是不明白这还能直接画键盘的属于是脑洞神,画出来还是pvd我更不理解了,后面那个怎么看怎么像o或者0,你能是d,太厉害了。

图片[2]-几道屑misc-魔法少女雪殇

把脑洞玩明白了属于是。

图片[3]-几道屑misc-魔法少女雪殇

加载上,两个文件,第一个是压缩包套娃,里面有两个img

图片[4]-几道屑misc-魔法少女雪殇

第一个全是空文件,第二个是加密的bitlocker,bitlocker破解可参考文章:

2021starctf misc部分复现 – Pur3 – 博客园 (cnblogs.com)

bitlocker2john+hashcat破解

图片[5]-几道屑misc-魔法少女雪殇

乐,密码abcd1234,进行一个取证大师的挂载

图片[6]-几道屑misc-魔法少女雪殇

自动取证看看。

图片[7]-几道屑misc-魔法少女雪殇

然后发现一个7z,提出来看看

图片[8]-几道屑misc-魔法少女雪殇

获得文件

图片[9]-几道屑misc-魔法少女雪殇

https://www.cnblogs.com/bianjiangjiang/p/14981829.html#/c/subject/p/14981829.html

比赛期间上了提示说是rdp,所以这里也一样直接进行搜搜,找到上面文章和工具,然后解密即可

图片[10]-几道屑misc-魔法少女雪殇

获得一堆位图,找到

图片[11]-几道屑misc-魔法少女雪殇

最后base64解码即可。屑题

深育杯-Login

开局一个web页面,最下面有个获取示例,可以下载压缩包

image-20211113165106124

压缩包三个文件,存在一个副本,发现存在伪加密

image-20211113165143433

将示例-副本.txt提取出即可然后利用明文攻击

image-20211113165501698
图片[15]-几道屑misc-魔法少女雪殇

获得密码,解压后image-20211113165632036

三个1kb的内容, 猜测是crc碰撞。写脚本即可

#!/usr/bin/env python
# CRC32 tools by Victor

import argparse
import os
import sys

permitted_characters = set(
   map(ord, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_'))  # \w

testing = False

args = None


def get_poly():
   poly = parse_dword(args.poly)
   if args.msb:
       poly = reverseBits(poly)
   check32(poly)
   return poly


def get_input():
   if args.instr:
       return tuple(map(ord, args.instr))
   with args.infile as f:  # pragma: no cover
       return tuple(map(ord, f.read()))


def out(msg):
   if not testing:  # pragma: no cover
       args.outfile.write(msg)
       args.outfile.write(os.linesep)

table = []
table_reverse = []


def init_tables(poly, reverse=True):
   global table, table_reverse
   table = []
   # build CRC32 table
   for i in range(256):
       for j in range(8):
           if i & 1:
               i >>= 1
               i ^= poly
           else:
               i >>= 1
       table.append(i)
   assert len(table) == 256, "table is wrong size"
   # build reverse table
   if reverse:
       table_reverse = []
       found_none = set()
       found_multiple = set()
       for i in range(256):
           found = []
           for j in range(256):
               if table[j] >> 24 == i:
                   found.append(j)
           table_reverse.append(tuple(found))
           if not found:
               found_none.add(i)
           elif len(found) > 1:
               found_multiple.add(i)
       assert len(table_reverse) == 256, "reverse table is wrong size"
       if found_multiple:
           out('WARNING: Multiple table entries have an MSB in {0}'.format(
               rangess(found_multiple)))
       if found_none:
           out('ERROR: no MSB in the table equals bytes in {0}'.format(
               rangess(found_none)))


def calc(data, accum=0):
   accum = ~accum
   for b in data:
       accum = table[(accum ^ b) & 0xFF] ^ ((accum >> 8) & 0x00FFFFFF)
   accum = ~accum
   return accum & 0xFFFFFFFF


def rewind(accum, data):
   if not data:
       return (accum,)
   stack = [(len(data), ~accum)]
   solutions = set()
   while stack:
       node = stack.pop()
       prev_offset = node[0] - 1
       for i in table_reverse[(node[1] >> 24) & 0xFF]:
           prevCRC = (((node[1] ^ table[i]) << 8) |
                      (i ^ data[prev_offset])) & 0xFFFFFFFF
           if prev_offset:
               stack.append((prev_offset, prevCRC))
           else:
               solutions.add((~prevCRC) & 0xFFFFFFFF)
   return solutions


def findReverse(desired, accum):
   solutions = set()
   accum = ~accum
   stack = [(~desired,)]
   while stack:
       node = stack.pop()
       for j in table_reverse[(node[0] >> 24) & 0xFF]:
           if len(node) == 4:
               a = accum
               data = []
               node = node[1:] + (j,)
               for i in range(3, -1, -1):
                   data.append((a ^ node[i]) & 0xFF)
                   a >>= 8
                   a ^= table[node[i]]
               solutions.add(tuple(data))
           else:
               stack.append(((node[0] ^ table[j]) << 8,) + node[1:] + (j,))
   return solutions

# Tools


def parse_dword(x):
   return int(x, 0) & 0xFFFFFFFF


def reverseBits(x):
   # http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel
   # http://stackoverflow.com/a/20918545
   x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1)
   x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2)
   x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4)
   x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8)
   x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16)
   return x & 0xFFFFFFFF

# Compatibility with Python 2.6 and earlier.
if hasattr(int, "bit_length"):
   def bit_length(num):
       return num.bit_length()
else:
   def bit_length(n):
       if n == 0:
           return 0
       bits = -32
       m = 0
       while n:
           m = n
           n >>= 32
           bits += 32
       while m:
           m >>= 1
           bits += 1
       return bits


def check32(poly):
   if poly & 0x80000000 == 0:
       out('WARNING: polynomial degree ({0}) != 32'.format(bit_length(poly)))
       out('         instead, try')
       out('         0x{0:08x} (reversed/lsbit-first)'.format(poly | 0x80000000))
       out('         0x{0:08x} (normal/msbit-first)'.format(reverseBits(poly | 0x80000000)))


def reciprocal(poly):
   ''' Return the reversed reciprocal (Koopman notatation) polynomial of a
      reversed (lsbit-first) polynomial '''
   return reverseBits((poly << 1) | 1)


def print_num(num):
   ''' Write a numeric result in various forms '''
   out('hex: 0x{0:08x}'.format(num))
   out('dec:   {0:d}'.format(num))
   out('oct: 0o{0:011o}'.format(num))
   out('bin: 0b{0:032b}'.format(num))

import itertools


def ranges(i):
   for kg in itertools.groupby(enumerate(i), lambda x: x[1] - x[0]):
       g = list(kg[1])
       yield g[0][1], g[-1][1]


def rangess(i):
   return ', '.join(map(lambda x: '[{0},{1}]'.format(*x), ranges(i)))

# Parsers


def get_parser():
   ''' Return the command-line parser '''
   parser = argparse.ArgumentParser(
       description="Reverse, undo, and calculate CRC32 checksums")
   subparsers = parser.add_subparsers(metavar='action')

   poly_flip_parser = argparse.ArgumentParser(add_help=False)
   subparser_group = poly_flip_parser.add_mutually_exclusive_group()
   subparser_group.add_argument(
       '-m', '--msbit', dest="msb", action='store_true',
       help='treat the polynomial as normal (msbit-first)')
   subparser_group.add_argument('-l', '--lsbit', action='store_false',
                                help='treat the polynomial as reversed (lsbit-first) [default]')

   desired_poly_parser = argparse.ArgumentParser(add_help=False)
   desired_poly_parser.add_argument(
       'desired', type=str, help='[int] desired checksum')

   default_poly_parser = argparse.ArgumentParser(add_help=False)
   default_poly_parser.add_argument(
       'poly', default='0xEDB88320', type=str, nargs='?',
       help='[int] polynomial [default: 0xEDB88320]')

   accum_parser = argparse.ArgumentParser(add_help=False)
   accum_parser.add_argument(
       'accum', type=str, help='[int] accumulator (final checksum)')

   default_accum_parser = argparse.ArgumentParser(add_help=False)
   default_accum_parser.add_argument(
       'accum', default='0', type=str, nargs='?',
       help='[int] starting accumulator [default: 0]')

   outfile_parser = argparse.ArgumentParser(add_help=False)
   outfile_parser.add_argument('-o', '--outfile',
                               metavar="f",
                               type=argparse.FileType('w'),
                               default=sys.stdout,
                               help="Output to a file instead of stdout")

   infile_parser = argparse.ArgumentParser(add_help=False)
   subparser_group = infile_parser.add_mutually_exclusive_group()
   subparser_group.add_argument('-i', '--infile',
                                metavar="f",
                                type=argparse.FileType('rb'),
                                default=sys.stdin,
                                help="Input from a file instead of stdin")
   subparser_group.add_argument('-s', '--str',
                                metavar="s",
                                type=str,
                                default='',
                                dest='instr',
                                help="Use a string as input")

   subparser = subparsers.add_parser('flip', parents=[outfile_parser],
                                     help="flip the bits to convert normal(msbit-first) polynomials to reversed (lsbit-first) and vice versa")
   subparser.add_argument('poly', type=str, help='[int] polynomial')
   subparser.set_defaults(
       func=lambda: print_num(reverseBits(parse_dword(args.poly))))

   subparser = subparsers.add_parser('reciprocal', parents=[outfile_parser],
                                     help="find the reciprocal (Koopman notation) of a reversed (lsbit-first) polynomial and vice versa")
   subparser.add_argument('poly', type=str, help='[int] polynomial')
   subparser.set_defaults(func=reciprocal_callback)

   subparser = subparsers.add_parser('table', parents=[outfile_parser,
                                                       poly_flip_parser,
                                                       default_poly_parser],
                                     help="generate a lookup table for a polynomial")
   subparser.set_defaults(func=table_callback)

   subparser = subparsers.add_parser('reverse', parents=[
       outfile_parser,
       poly_flip_parser,
       desired_poly_parser,
       default_accum_parser,
       default_poly_parser],
       help="find a patch that causes the CRC32 checksum to become a desired value")
   subparser.set_defaults(func=reverse_callback)

   subparser = subparsers.add_parser('undo', parents=[
       outfile_parser,
       poly_flip_parser,
       accum_parser,
       default_poly_parser,
       infile_parser],
       help="rewind a CRC32 checksum")
   subparser.add_argument('-n', '--len', metavar='l', type=str,
                          default='0', help='[int] number of bytes to rewind [default: 0]')
   subparser.set_defaults(func=undo_callback)

   subparser = subparsers.add_parser('calc', parents=[
       outfile_parser,
       poly_flip_parser,
       default_accum_parser,
       default_poly_parser,
       infile_parser],
       help="calculate the CRC32 checksum")
   subparser.set_defaults(func=calc_callback)

   return parser


def reciprocal_callback():
   poly = parse_dword(args.poly)
   check32(poly)
   print_num(reciprocal(poly))


def table_callback():
   # initialize tables
   init_tables(get_poly(), False)
   # print table
   out('[{0}]'.format(', '.join(map('0x{0:08x}'.format, table))))


def reverse_callback():
   # initialize tables
   init_tables(get_poly())
   # find reverse bytes
   desired = parse_dword(args.desired)
   accum = parse_dword(args.accum)
   # 4-byte patch
   patches = findReverse(desired, accum)
   for patch in patches:
       text = ''
       if all(p in permitted_characters for p in patch):
           text = '{}{}{}{} '.format(*map(chr, patch))
       out('4 bytes: {}{{0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}}}'.format(text, *patch))
       checksum = calc(patch, accum)
       out('verification checksum: 0x{:08x} ({})'.format(
           checksum, 'OK' if checksum == desired else 'ERROR'))

   def print_permitted_reverse(patch):
           patches = findReverse(desired, calc(patch, accum))
           for last_4_bytes in patches:
               if all(p in permitted_characters for p in last_4_bytes):
                   patch2 = patch + last_4_bytes
                   out('{} bytes: {} ({})'.format(
                       len(patch2),
                       ''.join(map(chr, patch2)),
                       'OK' if calc(patch2, accum) == desired else 'ERROR'))

   # 5-byte alphanumeric patches
   for i in permitted_characters:
       print_permitted_reverse((i,))
   # 6-byte alphanumeric patches
   for i in permitted_characters:
       for j in permitted_characters:
           print_permitted_reverse((i, j))


def undo_callback():
   # initialize tables
   init_tables(get_poly())
   # calculate checksum
   accum = parse_dword(args.accum)
   maxlen = int(args.len, 0)
   data = get_input()
   if not 0 < maxlen <= len(data):
       maxlen = len(data)
   out('rewinded {0}/{1} ({2:.2f}%)'.format(maxlen, len(data),
       maxlen * 100.0 / len(data) if len(data) else 100))
   for solution in rewind(accum, data[-maxlen:]):
       out('')
       print_num(solution)


def calc_callback():
   # initialize tables
   init_tables(get_poly(), False)
   # calculate checksum
   accum = parse_dword(args.accum)
   data = get_input()
   out('data len: {0}'.format(len(data)))
   out('')
   print_num(calc(data, accum))


def main(argv=None):
   ''' Runs the program and handles command line options '''
   parser = get_parser()

   # Parse arguments and run the function
   global args
   args = parser.parse_args(argv)
   args.func()

if __name__ == '__main__':
   main()  # pragma: no cover
image-20211113165841045

爆破结果

image-20211113170015927

三次,总共拼接为

welc0me_sangforctf

解密image-20211113170223119

swp文件直接用vim -r恢复即可

image-20211113170258355

最后登录

image-20211113170346415

没有东西并且禁用了右键,edge插件直接破,右键查看源代码,获得flag

hxb-某取证题

只能说下次出题人出提前把环境清理干净了,一堆碎片文件结果你就外带一个连接zip,你单反你把这个zip单纯用来出题都是个好题目,烂题

开局一个raw,直接vol取证,iehistory获得一个链接,访问可下载zip

image-20211114175132754
image-20211114175211061

压缩包里面两个jpg,直接百度搜了半天,发现文章

(30条消息) ZIP已知明文攻击深入利用_BlusKing-CSDN博客

按照文章里面利用bkcrak进行爆破

jpg_header内容

img

然后指令

.\bkcrack.exe -C target.zip -c t.jpg -p jpg_header -o 0

大概跑了20多分钟跑出来密钥image-20211114175611739

然后

.\bkcrack.exe -C .\target.zip -c a.jpg -k b0a90b36 14dd97b9 f5d648cf -d out2.jpg

把out2.jpg导出,但是由于加密方式问题无法显示,利用脚本,参考文章

CTF中常见明文攻击 – LEOGG – 博客园 (cnblogs.com)

image-20211114175725244

跑一下获得image-20211114175746093

他说桌面壁纸,直接find jpg然后导出即可

image-20211114175921137
image-20211114175934598

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情