学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

2万

积分

41

好友

1157

主题
发表于 2019-7-5 12:59:05 | 查看: 8350| 回复: 3

相关题目:

♦ 压缩包套娃

压缩包套娃

附件:first.zip

solution

本题是个多层密码加密的题,主要考察sha256爆破RSA copper smith攻击古典密码CRC32爆破

0x01 first key

打开key.py:

import hashlib
import os
s=os.urandom(8)
print s[0:5].encode('hex')
print hashlib.sha256(s).hexdigest()
#3fcb70c42b
#4c6e139bd07cc2c00c8d39995727b697efa4171a9e475d194e654a0f4b0c3285
#password:s.encode('hex')

是个sha256的简单爆破,提供的脚本如下:

import hashlib
a='4c6e139bd07cc2c00c8d39995727b697efa4171a9e475d194e654a0f4b0c3285'
b=0x3fcb70c42b
def num2str(num):
    h=hex(num)[2:].replace("L","")
    if len(h)%2!=0:
        h='0'+h
    return h.decode('hex')

for i in range(0x100):
    for j in range(0x100):
        for m in range(0x100):
                tmp=num2str(b)+chr(i)+chr(j)+chr(m)
                if hashlib.sha256(tmp).hexdigest()==a:
                    print tmp.encode('hex')

爆破得到password:

3fcb70c42b95bbdf

0x02 second key

根据key进入second.zip后,得到的是一个thrid.zipkey.sage

from Crypto.PublicKey import RSA

key=RSA.generate(1024)
print hex(key.n),hex(key.e)
#0x907c4c35ef8defb9b0a5bf8ba3f1ad5d0d12ba79cb2913e6ef149a7b62ade6b08fad9618650c3508d8357933f83d1984516af4a1f6236ed734095d88a1c987912bf911d0187184c5182344bfab2203feb24b1f4ef7a94dfa86e5dc68caeead4318e3c043c9b19e1726b27c7948b522f89b5f83f37ea66de0e1ea2af36a38406bL 0x10001

m='*************'
c=power_mod(m,key.e,key.n)
print hex(c)
#0x6bad8e8bc4abe06db93504d120eca56ce6637906d5e2ada9c0010ac706490dfe877e913657ac9105b85ee83ea42c5b6989f067dcb2bacd24daad6679d30f304cda8dcf30509ccf67528ce9373bf469353052042bf1d73ee18e61e7b5eae9914b1619a48fcf48e97f483e50719d346af17e60b4bfd2d9f6ba68a44838db707c1dL

print hex((key.p>>200)<<200)
#0xb6b5afc607cdfb5b103b49b3f83a4fdca35ecf74e259a31b2c22898fe55aaea1ae88ad4be1d6b900000000000000000000000000000000000000000000000000L
#密码就在m中:)

从题目中我们可以知道:这是个RSA因子高位已知攻击。尝试copper smith攻击,sage脚本如下:

# -*- coding: utf-8 -*-
import time
from sage import *
# display matrix picture with 0 and X
def matrix_overview(BB, bound):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d ' % ii)
        for jj in range(BB.dimensions()[1]):
            a += '0' if BB[ii,jj] == 0 else 'X'
            a += ' '
        if BB[ii, ii] >= bound:
            a += '~'
        print a

def coppersmith_howgrave_univariate(pol, modulus, beta, mm, tt, XX):
    """
    Coppersmith revisited by Howgrave-Graham

    finds a solution if:
    * b|modulus, b >= modulus^beta , 0 < beta <= 1
    * |x| < XX
    """
    #
    # init
    #
    dd = pol.degree()
    nn = dd * mm + tt

    #
    # checks
    #
    if not 0 < beta <= 1:
        raise ValueError("beta should belongs in (0, 1]")

    if not pol.is_monic():
        raise ArithmeticError("Polynomial must be monic.")

    #
    # calculate bounds and display them
    #
    # Coppersmith revisited algo for univariate
    #
    # change ring of pol and x
    polZ = pol.change_ring(ZZ)
    x = polZ.parent().gen()

    # compute polynomials
    gg = []
    for ii in range(mm):
        for jj in range(dd):
            gg.append((x * XX)**jj * modulus**(mm - ii) * polZ(x * XX)**ii)
    for ii in range(tt):
        gg.append((x * XX)**ii * polZ(x * XX)**mm)

    # construct lattice B
    BB = Matrix(ZZ, nn)

    for ii in range(nn):
        for jj in range(ii+1):
            BB[ii, jj] = gg[ii][jj]

    # display basis matrix
    if debug:
        matrix_overview(BB, modulus^mm)

    # LLL
    BB = BB.LLL()

    # transform shortest vector in polynomial
    new_pol = 0
    for ii in range(nn):
        new_pol += x**ii * BB[0, ii] / XX**ii

    # factor polynomial
    potential_roots = new_pol.roots()
    print "potential roots:", potential_roots

    return potential_roots
length_N = 1024
N = 0x907c4c35ef8defb9b0a5bf8ba3f1ad5d0d12ba79cb2913e6ef149a7b62ade6b08fad9618650c3508d8357933f83d1984516af4a1f6236ed734095d88a1c987912bf911d0187184c5182344bfab2203feb24b1f4ef7a94dfa86e5dc68caeead4318e3c043c9b19e1726b27c7948b522f89b5f83f37ea66de0e1ea2af36a38406bL
qbar =0xb6b5afc607cdfb5b103b49b3f83a4fdca35ecf74e259a31b2c22898fe55aaea1ae88ad4be1d6b900000000000000000000000000000000000000000000000000L

F.<x> = PolynomialRing(Zmod(N), implementation='NTL');
pol = x - qbar
dd = pol.degree()

beta = 0.5                             # q >= N^beta
epsilon = beta / 7                     # <= beta/7
mm = ceil(beta**2 / (dd * epsilon))    # optimized
tt = floor(dd * mm * ((1/beta) - 1))   # optimized
XX = ceil(N**((beta**2/dd) - epsilon)) # |diff| < X

# Coppersmith
start_time = time.time()
roots = coppersmith_howgrave_univariate(pol, N, beta, mm, tt, XX)
c=0x6bad8e8bc4abe06db93504d120eca56ce6637906d5e2ada9c0010ac706490dfe877e913657ac9105b85ee83ea42c5b6989f067dcb2bacd24daad6679d30f304cda8dcf30509ccf67528ce9373bf469353052042bf1d73ee18e61e7b5eae9914b1619a48fcf48e97f483e50719d346af17e60b4bfd2d9f6ba68a44838db707c1d
q=qbar-roots[0][0]
p=N/q
e=0x10001
d=inverse_mod(e,(p-1)*(q-1))
m=power_mod(c,d,N)
print '{:x}'.format(int(m)).decode('hex')

得到结果:

So,the key is h3ll0

0x03 thrid key

根据key打开third.zip后,发现有个fourth.zipkey.py

import sys

alphaL = "abcdefghijklnmopqrstuvwxyz"
alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
num    = "0123456789"
keychars = num+alphaL+alphaU

if len(sys.argv) != 3:
  print("Usage: %s SECRET_KEY PLAINTEXT"%(sys.argv[0]))
 sys.exit()
key = sys.argv[1].upper()
if not key.isalnum():
  print("Your key is invalid, it may only be alphanumeric characters")
  sys.exit()
plaintext = sys.argv[2]
ciphertext=""

for i in range(len(plaintext)):
  rotate_amount = keychars.index(key[i%len(key)])
  if plaintext in alphaL:
    enc_char = ord('a') + (3*(ord(plaintext)-ord('a'))+2*rotate_amount)%26
  elif plaintext in alphaU:
    enc_char = ord('A') + (5*(ord(plaintext)-ord('A'))+rotate_amount)%26
  elif plaintext in num:
    enc_char = ord('0') + (7*(ord(plaintext)-ord('0'))+3*rotate_amount)%10
  else:
    enc_char = ord(plaintext)
  ciphertext = ciphertext + chr(enc_char)

print("Encryption complete, ENC(%s,%s) = %s"%(plaintext,key,ciphertext))

# Encryption complete, ENC(ciphertext) = nxos ge kmqb dizh uic:d4k_4y6, cdz nxc jutv rgpv uk: FFB
# key hint:h3ll0长得像哪个单词呢?

leet的hello可以写成h3ll0,而且h3ll0很像hello。因此密钥为hello。

从中可以看出,key并没有很大程度影响enc_char内容,因此可以当常数看待,变成简单的Affine密码问题,解密脚本如下:

import gmpy2

alphaL = "abcdefghijklnmopqrstuvwxyz"
alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
num    = "0123456789"
keychars = num+alphaL+alphaU

key="hello"

enc_text="nxos ge kmqb dizh uic:d4k_4y6, cdz nxc jutv rgpv uk: FFB"

plaintext=""
i1=gmpy2.invert(3,26)
i2=gmpy2.invert(5,26)
i3=gmpy2.invert(7,10)
for i in range(len(enc_text)):
    rotate_amount = keychars.index(key[i%len(key)])
    if enc_text in alphaL:
        char = ord('a') + (i1*((ord(enc_text)-ord('a'))-2*rotate_amount))%26
    elif enc_text in alphaU:
        char = ord('A') + (i2*((ord(enc_text)-ord('A'))-rotate_amount))%26
    elif enc_text in num:
        char = ord('0') + (i3*((ord(enc_text)-ord('0'))-3*rotate_amount))%10
    else:
        char = ord(enc_text)
    plaintext = plaintext + chr(char)
print(plaintext)

得到结果:

this is your next key:n3w_6u9, and the next hint is: CRC

0x04 fourth key

根据key进入fourth.zip,发现有个flag.zip,打得开flag.zip,但是解压要密码。又有提示:CRC,因此采取CRC32爆破。但是爆破一个是5bytes,一个是6bytes。因此我们分别用两个脚本爆破。

# -*- coding: utf-8 -*-
# 5bytes CRC32
import itertools
import binascii
import string

class crc32_reverse_class(object):
    # the code is modified from https://github.com/theonlypwner/crc32/blob/master/crc32.py
    def __init__(self, crc32, length, tbl=string.printable,
                 poly=0xEDB88320, accum=0):
        self.char_set = set(map(ord, tbl))
        self.crc32 = crc32
        self.length = length
        self.poly = poly
        self.accum = accum
        self.table = []
        self.table_reverse = []

    def init_tables(self, poly, reverse=True):
        # build CRC32 table
        for i in range(256):
            for j in range(8):
                if i & 1:
                    i >>= 1
                    i ^= poly
                else:
                    i >>= 1
            self.table.append(i)
        assert len(self.table) == 256, "table is wrong size"
        # build reverse table
        if reverse:
            found_none = set()
            found_multiple = set()
            for i in range(256):
                found = []
                for j in range(256):
                    if self.table[j] >> 24 == i:
                        found.append(j)
                self.table_reverse.append(tuple(found))
                if not found:
                    found_none.add(i)
                elif len(found) > 1:
                    found_multiple.add(i)
            assert len(self.table_reverse) == 256, "reverse table is wrong size"

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

    def ranges(self, 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 calc(self, data, accum=0):
        accum = ~accum
        for b in data:
            accum = self.table[(accum ^ b) & 0xFF] ^ ((accum >> 8) & 0x00FFFFFF)
        accum = ~accum
        return accum & 0xFFFFFFFF

    def findReverse(self, desired, accum):
        solutions = set()
        accum = ~accum
        stack = [(~desired,)]
        while stack:
            node = stack.pop()
            for j in self.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) & 0xFF)
                        a >>= 8
                        a ^= self.table[node]
                    solutions.add(tuple(data))
                else:
                    stack.append(((node[0] ^ self.table[j]) << 8,) + node[1:] + (j,))
        return solutions

    def dfs(self, length, outlist=['']):
        tmp_list = []
        if length == 0:
            return outlist
        for list_item in outlist:
            tmp_list.extend([list_item + chr(x) for x in self.char_set])
        return self.dfs(length - 1, tmp_list)

    def run_reverse(self):
        # initialize tables
        self.init_tables(self.poly)
        # find reverse bytes
        desired = self.crc32
        accum = self.accum
        # 4-byte patch
        if self.length >= 4:
            patches = self.findReverse(desired, accum)
            for patch in patches:
                checksum = self.calc(patch, accum)
                print 'verification checksum: 0x{0:08x} ({1})'.format(
                    checksum, 'OK' if checksum == desired else 'ERROR')
            for item in self.dfs(self.length - 4):
                patch = map(ord, item)
                patches = self.findReverse(desired, self.calc(patch, accum))
                for last_4_bytes in patches:
                    if all(p in self.char_set for p in last_4_bytes):
                        patch.extend(last_4_bytes)
                        print '[find]: {1} ({0})'.format(
                            'OK' if self.calc(patch, accum) == desired else 'ERROR', ''.join(map(chr, patch)))
        else:
            for item in self.dfs(self.length):
                if crc32(item) == desired:
                    print '[find]: {0} (OK)'.format(item)

def crc32_reverse(crc32, length, char_set=string.printable,
                  poly=0xEDB88320, accum=0):
    '''

    :param crc32: the crc32 you wnat to reverse
    :param length: the plaintext length
    :param char_set: char_set
    :param poly: poly , default 0xEDB88320
    :param accum: accum , default 0
    :return: none
    '''
    obj = crc32_reverse_class(crc32, length, char_set, poly, accum)
    obj.run_reverse()

def crc32(s):
    '''

    :param s: the string to calculate the crc32
    :return: the crc32
    '''
    return binascii.crc32(s) & 0xffffffff

l=[0x397E0355]

for k in l:
        crc32_reverse(k,5)
        print '======='

得到合适的结果:

6u9ku

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

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) << 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) & 0xFF)
                    a >>= 8
                    a ^= table[node]
                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:
        out('4 bytes: {{0x{0:02x}, 0x{1:02x}, 0x{2:02x}, 0x{3:02x}}}'.format(*patch))
        checksum = calc(patch, accum)
        out('verification checksum: 0x{0:08x} ({1})'.format(
            checksum, 'OK' if checksum == desired else 'ERROR'))
    # 6-byte alphanumeric patches
    for i in permitted_characters:
        for j in permitted_characters:
            patch = [i, j]
            patches = findReverse(desired, calc(patch, accum))
            for last_4_bytes in patches:
                if all(p in permitted_characters for p in last_4_bytes):
                    patch.extend(last_4_bytes)
                    out('alternative: {1}{2}{3}{4}{5}{6} ({0})'.format(
                        'OK' if calc(patch, accum) == desired else 'ERROR', *map(chr, patch)))

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

得到合适的结果:

_w0rld

因此组合一起就出来key:

6u9ku_w0rld

0x05 decode

解压得到flag.txt文件内容:

flag? 就在这里哟
4d5a5747435a33334f35535443595a514e555a56363542514c35525445364c514f525858323d3d3d

先hex解码,得到:

MZWGCZ33O5STCYZQNUZV65BQL5RTE6LQORXX2===

显然这是base64的编码,因此尝试各种base家族解码,最终发现为base32。

得到flag:

flag{we1c0m3_t0_c2ypto}


题目:

first.zip (2.92 KB, 下载次数: 1)

题目所用的所有解题脚本:

decrpto.zip (8.18 KB, 下载次数: 4)

温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046
发表于 2019-11-22 14:30:55
{:6_151:}{:6_151:}{:6_151:}{:6_151:}{:6_151:}
发表于 2020-10-16 10:52:41
谢谢大佬,学习了
发表于 2020-10-19 14:30:07
谢谢大佬,这个脚本写的很赞

小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

GMT+8, 2024-3-29 09:40 , Processed in 0.108755 second(s), 54 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表