示例#1
0
def forgeAdminCookie(verbose=False):
    """ Produce a message which is validated as an admin token by tools.validateAuthString, without knowledge of that function's decryption key.

    Method:
        We'll produce an encryption of the following message (shown here with '|'s inserted to show divisions into blocks of 16 bytes):

'00000000000000000|comment1=cooking|%20MCs;userdata=|;comment2=%20like|%20a%20pound%20of|%20bacon'

        using tools.newAuthString (with empty input). Then we'll XOR this encrypted string with a second string such that the decryption of the modified string will have ";admin=heckyeahX" (where X is some character) as its 4th block.

        The reason we can do this is that flipping the j-th bit in the k-th block of an AES-CBC ciphertext will flip the j-th bit in the (k + 1)-th block of its decryption. (Notice that the k-th block of the ciphertext gets XOR'd with the decryption of the (k + 1)-th block of the ciphertext to produce the (k + 1)-th block of the plaintext!).

        Specifically, we'll modify the 3rd block of the ciphertext by XORing it with XOR(';admin=heckyeahX', ';comment2=%20lik'), where X runs over some range of characters until the decryption of the modified string parses properly. If the decryption parses, it will also be validated as an admin token because it contains 'admin' as a key.

        The reason our first choice of X might not succeed is that, depending on the key (tools.rand_key), the decryption of the 3rd block might contain some metacharacters which prevent the decrypted string from parsing properly. In practice, this method usually succeeds in one or two tries. 

    Arg:
        verbose (bool): if True, print some information about the intermediate steps; silent if False.

    Returns:
        bool: True if a string which is validated as an admin token was successfully produced; False if not.
    """
    cookie = newUserCookie('')
    current = Message(b';comment2=%20lik')
    new_cookie = Message(b'')
    admin_login = False
    letter_val = 65
    while not admin_login and letter_val < 127:
        try:
            wish = Message(b';admin=true;xx=') + Message(bytes([letter_val]))
            if verbose:
                print("trying %s..." % repr(wish.ascii()))
            diff = XOR(current, wish)
            new_cookie = cookie[:32] + XOR(cookie[32:48], diff) + cookie[48:]
            admin_login = isAdminCookie(new_cookie)
            letter_val += 1
        except:
            letter_val += 1
    if verbose:
        if letter_val < 127:
            print("Success in %d try(s)!" % (letter_val - 65))
        else:
            print("Fail!!")
    return new_cookie
示例#2
0
from tools.message import Message
from tools.randomdata import randMsg

# example from the challenge statement
msg_str = "YELLOW SUBMARINE"

msg = Message(msg_str, 'ascii')
print("Original message:", repr(msg.ascii()))

msg.pad(block_size=20)
print("Message padded to a multiple of 20 bytes:", repr(msg.ascii()))

msg.stripPad()
print("De-padded message:", repr(msg.ascii()))

# more tests and examples
trials = 5
len_lower_bound = 0
len_upper_bound = 20

print("\nRunning %d trials with messages of lengths in [%d, %d]:" %
      (trials, len_lower_bound, len_upper_bound))
for trial in range(trials):
    msg = randMsg(len_lower_bound, len_upper_bound)
    print("\nOriginal message of length %d:\n" % len(msg), msg)
    msg.pad(16)
    print("Padded to a multiple of 16 bytes, length %d:\n" % len(msg), msg)
    msg.stripPad(16)
    print("Padding stripped, length %d:\n" % len(msg), msg)

print("\nNote behavior when message length is a multiple of the block size:")
示例#3
0
        For each index i less than the length m of the key, the (n * m + i)-th bytes of the input message (where n runs over the positive integers until the string is exhausted) are collected into a new message. The i-th new string consists of all the bytes of the original message which were encrypted by XOR'ing with the i-th byte of the repeating key. Each of the m new messages is now treated as a single-character-XOR decryption problem, which is solved by calling freqanalysis.scanKeys. The resulting m single-character keys are then pieced together to form the repeating key. 

    Args:
        msg (Message): the message which is to be decrypted.
        
        key_size (int): the length of the repeating key.

        case (bool): see the docstring for freqanalysis.scoreText.

        space (bool): see the docstring for freqanalysis.scoreText.

        verbose (bool): prints decryption of 'msg' with most likely key before returning if True, not if False (default).

    Returns:
        Message: the repeating-XOR key of length 'key_size' which was most likely used to encrypt the input message.
    """
    indices = [[i for i in range(len(msg)) if i % key_size == j]
               for j in range(key_size)]
    blocks = [
        Message(b''.join(msg[i].bytes for i in indices[j]))
        for j in range(key_size)
    ]
    key_chars = [scanKeys(blocks[j], case, space) for j in range(key_size)]
    key = Message(b''.join(char[1].bytes for char in key_chars))
    if verbose:
        print("The best key of length %d is: %s\n" %
              (key_size, repr(key.ascii())))
        print("The decryption of the message with this key is:\n%s" %
              repeatXOR(msg, key).ascii())
    return key
示例#4
0
def test_Message_createDisplayAscii(test_ascii):
    test_msg = Message(test_ascii, 'ascii')
    assert test_msg.ascii() == test_ascii